You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@mynewt.apache.org by will sanfilippo <wi...@runtime.io> on 2017/01/17 04:48:30 UTC

Bluetooth specification question after seeing Android 7.1.1 disconnect

Hello:

Was wondering if there were any folks out there that could comment on something regarding a disconnect issue with an Android Phone running 7.1.1 and our bluetooth stack (the controller).

What appears to be happening is this: 

* Nimble wants to do Data Length Extension and enqueues a LL_LENGTH_REQ when a connection gets created. Nimble is a peripheral btw.
* The Android controller wants to do a feature exchange so it enqueues a LL_FEATURE_REQ.
* Android controller sends the LL_FEATURE_REQ.
* Nimble controller sends a LL_LENGTH_REQ.
* Once the nimble controller succeeds in sending the LL_LENGTH_REQ, it sends the LL_FEATURE_RSP.
* Android responds with a LL_REJECT_IND with error code 0x24 LMP PDU not allowed.
* Android resends the LL_FEATURE_REQ.
* Nimble responds with LL_FEATURE_RSP.
* Android sends LL_LENGTH_REQ
* Nimble controller sends LL_LENGTH_RSP.
* All goes fine until nimble controller times out due to a failed LL control procedure: the nimble stack never received a LL_LENGTH_RSP.

NOTE: from the above it is hard to say why the Android controller sent the LL_REJECT_IND. Basically, it appears that the LL_LENGTH_REQ messed up the Android controller as the Android controller was expecting a LL_FEATURE_RSP.

My questions are the following:
* I think this is a bug on the part of the Android controller. The specification allows for non-real time response to control PDU’s and it is quite possible that a controller starts a procedure “at the same time” that the remote controller starts a procedure. What I would have expected is that the Android controller should have responded to the LL_LENGTH_REQ with a LL_LENGTH_RSP. Eventually, the Android controller gets the LL_FEATURE_RSP and all should have been fine. Do folks agree with this?
* A controller should not use a LL_REJECT_IND as a generic response when a controller sends something unexpected. The LL_REJECT_IND is only used during encryption procedures, connection parameter request update procedures and in a couple of cases where there are Control Procedure collisions. Note that the scenario described above is NOT one of the Control Procedure collisions mentioned in the specification.

Thanks!



Re: Bluetooth specification question after seeing Android 7.1.1 disconnect

Posted by will sanfilippo <wi...@runtime.io>.
It was not a phone I was using. I think it was a Nexus 6P. And yeah, I shouldnt’t have said “Android” when I was mentioning the bug. I have used other Android phones and they dont have this issue. Well, I have used one other Android Phone (I think it was a Nexus 5x) and there was no issue.

Regarding the proposed fix. I agree that the spec does not mention what to do when a LL_REJECT_IND (or REJECT_IND_EXT) is received (outside of the control procedures where use of REJECT_IND is expected). The spec is quite clear in other areas though; for example, a Data Length Update procedure ends only when a LL_LENGTH_RSP is received or LL_UNKNOWN_RSP is received.

This might just be me, but I really dislike adding work-arounds to what are pretty clearly bugs and that also clearly violate the spec in other areas. I also "worry" that there might be other unintended consequences by doing this. For example, the nimble controller issues a connection update and the peer responds with LL_REJECT_IND. We cancel the procedure but the peer accepts the connection update (which would cause a supervision timeout).

I wonder if there is a work-around that would fix this particular issue with this controller that would not violate the spec in other areas? Dont get me wrong; I think your idea is very reasonable and makes sense. Especially if you have encountered this with other devices.


> On Jan 17, 2017, at 2:12 AM, Andrzej Kaczmarek <an...@codecoup.pl> wrote:
> 
> Hi Will,
> 
> On Tue, Jan 17, 2017 at 5:48 AM, will sanfilippo <wi...@runtime.io> wrote:
> 
>> Hello:
>> 
>> Was wondering if there were any folks out there that could comment on
>> something regarding a disconnect issue with an Android Phone running 7.1.1
>> and our bluetooth stack (the controller).
>> 
> 
> Which phone do you use? Android has only host stack (Bluedroid) to this is
> likely specific to controller used in particular phone - I've seen similar
> problems when testing other controller and some "generic" Chinese phones.
> 
> 
>> 
>> What appears to be happening is this:
>> 
>> * Nimble wants to do Data Length Extension and enqueues a LL_LENGTH_REQ
>> when a connection gets created. Nimble is a peripheral btw.
>> * The Android controller wants to do a feature exchange so it enqueues a
>> LL_FEATURE_REQ.
>> * Android controller sends the LL_FEATURE_REQ.
>> * Nimble controller sends a LL_LENGTH_REQ.
>> * Once the nimble controller succeeds in sending the LL_LENGTH_REQ, it
>> sends the LL_FEATURE_RSP.
>> * Android responds with a LL_REJECT_IND with error code 0x24 LMP PDU not
>> allowed.
>> 
> 
> IIRC this is the same as I've seen (even the error code is the same) -
> don't have logs now though...
> 
> 
>> * Android resends the LL_FEATURE_REQ.
>> * Nimble responds with LL_FEATURE_RSP.
>> * Android sends LL_LENGTH_REQ
>> * Nimble controller sends LL_LENGTH_RSP.
>> * All goes fine until nimble controller times out due to a failed LL
>> control procedure: the nimble stack never received a LL_LENGTH_RSP.
>> 
>> NOTE: from the above it is hard to say why the Android controller sent the
>> LL_REJECT_IND. Basically, it appears that the LL_LENGTH_REQ messed up the
>> Android controller as the Android controller was expecting a LL_FEATURE_RSP.
>> 
>> My questions are the following:
>> * I think this is a bug on the part of the Android controller. The
>> specification allows for non-real time response to control PDU’s and it is
>> quite possible that a controller starts a procedure “at the same time” that
>> the remote controller starts a procedure. What I would have expected is
>> that the Android controller should have responded to the LL_LENGTH_REQ with
>> a LL_LENGTH_RSP. Eventually, the Android controller gets the LL_FEATURE_RSP
>> and all should have been fine. Do folks agree with this?
>> * A controller should not use a LL_REJECT_IND as a generic response when a
>> controller sends something unexpected. The LL_REJECT_IND is only used
>> during encryption procedures, connection parameter request update
>> procedures and in a couple of cases where there are Control Procedure
>> collisions. Note that the scenario described above is NOT one of the
>> Control Procedure collisions mentioned in the specification.
>> 
> 
> I agree, this is clearly issue on peer side - there is no procedure
> collision here since both length update and feature request can be handled
> at the same time. However, I think what Nimble should do here is to remove
> transaction once LL_REJECT_IND is received.
> 
> I know specification does use LL_REJECT_IND explicitly only in case of
> certain scenarios, but it does not seem to specify what to do if
> LL_REJECT_IND is received as response in other procedures. It makes sense
> to me that if peer indicated explicitly that it will not handle request, we
> should not expect response. I think it is better to have such workaround
> rather that strictly follow the spec and timeout connection.
> 
> BTW, I made small modification in Nimble so it replies LL_REJECT_IND on
> LL_LENGTH_REQ and checked how other device (here: LG G5 with Android 7.0,
> Broadcom controller) handle this and it just seem to do as I described,
> i.e. the connection was not terminated due to transaction timeout.
> 
> BR,
> Andrzej


Re: Bluetooth specification question after seeing Android 7.1.1 disconnect

Posted by Andrzej Kaczmarek <an...@codecoup.pl>.
Hi Will,

On Tue, Jan 17, 2017 at 5:48 AM, will sanfilippo <wi...@runtime.io> wrote:

> Hello:
>
> Was wondering if there were any folks out there that could comment on
> something regarding a disconnect issue with an Android Phone running 7.1.1
> and our bluetooth stack (the controller).
>

Which phone do you use? Android has only host stack (Bluedroid) to this is
likely specific to controller used in particular phone - I've seen similar
problems when testing other controller and some "generic" Chinese phones.


>
> What appears to be happening is this:
>
> * Nimble wants to do Data Length Extension and enqueues a LL_LENGTH_REQ
> when a connection gets created. Nimble is a peripheral btw.
> * The Android controller wants to do a feature exchange so it enqueues a
> LL_FEATURE_REQ.
> * Android controller sends the LL_FEATURE_REQ.
> * Nimble controller sends a LL_LENGTH_REQ.
> * Once the nimble controller succeeds in sending the LL_LENGTH_REQ, it
> sends the LL_FEATURE_RSP.
> * Android responds with a LL_REJECT_IND with error code 0x24 LMP PDU not
> allowed.
>

IIRC this is the same as I've seen (even the error code is the same) -
don't have logs now though...


> * Android resends the LL_FEATURE_REQ.
> * Nimble responds with LL_FEATURE_RSP.
> * Android sends LL_LENGTH_REQ
> * Nimble controller sends LL_LENGTH_RSP.
> * All goes fine until nimble controller times out due to a failed LL
> control procedure: the nimble stack never received a LL_LENGTH_RSP.
>
> NOTE: from the above it is hard to say why the Android controller sent the
> LL_REJECT_IND. Basically, it appears that the LL_LENGTH_REQ messed up the
> Android controller as the Android controller was expecting a LL_FEATURE_RSP.
>
> My questions are the following:
> * I think this is a bug on the part of the Android controller. The
> specification allows for non-real time response to control PDU’s and it is
> quite possible that a controller starts a procedure “at the same time” that
> the remote controller starts a procedure. What I would have expected is
> that the Android controller should have responded to the LL_LENGTH_REQ with
> a LL_LENGTH_RSP. Eventually, the Android controller gets the LL_FEATURE_RSP
> and all should have been fine. Do folks agree with this?
> * A controller should not use a LL_REJECT_IND as a generic response when a
> controller sends something unexpected. The LL_REJECT_IND is only used
> during encryption procedures, connection parameter request update
> procedures and in a couple of cases where there are Control Procedure
> collisions. Note that the scenario described above is NOT one of the
> Control Procedure collisions mentioned in the specification.
>

I agree, this is clearly issue on peer side - there is no procedure
collision here since both length update and feature request can be handled
at the same time. However, I think what Nimble should do here is to remove
transaction once LL_REJECT_IND is received.

I know specification does use LL_REJECT_IND explicitly only in case of
certain scenarios, but it does not seem to specify what to do if
LL_REJECT_IND is received as response in other procedures. It makes sense
to me that if peer indicated explicitly that it will not handle request, we
should not expect response. I think it is better to have such workaround
rather that strictly follow the spec and timeout connection.

BTW, I made small modification in Nimble so it replies LL_REJECT_IND on
LL_LENGTH_REQ and checked how other device (here: LG G5 with Android 7.0,
Broadcom controller) handle this and it just seem to do as I described,
i.e. the connection was not terminated due to transaction timeout.

BR,
Andrzej