Hi,
I recently built an autonomous bluetooth LE network (based on Nordic
nRF51822 central/nRF8001 peripheral µC) which I use for basic home
automation tasks.
To access this network from my Nexus 4 I need to put the phone in a
peripheral role so it can connect to the nRF51822 central.
As bluedroid won't support older Nexus phones in a peripheral role
anytime soon and is difficult to hack I was looking into bluez as an
alternative. I looked through the bluez source over the last few days,
watched your latest commits and list conversations, read up all kind of
README's and API docs.
I'm pleased to see that you're actively working on the kernel-side LE
advertising mgmt API and that you already implemented HAL stubs on the
Android side for the Lollipop 5.0 peripheral role enhancements.
It seems that the min requirement for peripheral role support in Android
would be at least 5 concurrent multi-advertising instances.
What is your schedule for the implementation of the multi-advertising
stubs in the Android bluetoothd HAL daemon? Is someone working on it
already? Would you welcome patches? (I never contributed to bluez,
though, and would require a bit of initial 1:1 support...)
Is there still something else missing on the kernel side or in userland
to make multi-advertisement work? Or is it all just about HAL support now?
Kind regards,
Florian
--
Florian Grandel
Freelance Software Developer
Hi Marcel,
On Mon, Mar 30, 2015 at 2:57 PM, Marcel Holtmann <[email protected]> wrot=
e:
> Hi Jakub,
>
>>>>> Now that most of the logic for a single instance is in place it shoul=
d
>>>>> be straightforward to extend it for multiple instances. I would start
>>>>> by turning the adv_instance field of hci_dev into a list of
>>>>> adv_instances and a way to determine and get a pointer to the
>>>>> currently active instance.
>>>>
>>>> Yes, agreed. That's exactly where I started. Happy to hear that you go=
t the same procedure in mind. I experimented with a dynamically extended ar=
ray and a linked list. The latter seems to be the better choice as it allow=
s us to easily remove entries in the middle of the list.
>>>>
>>>>> You would then modify the code in
>>>>> net/bluetooth/mgmt.c that accesses the instance 1 parameters to use
>>>>> the new getter instead. Once all of that is done, the second step
>>>>> would be a matter of inserting new elements into the advertising list
>>>>> and handling the round-robin logic and the duration parameter.
>>>>
>>>> Agreed. That's what I had in mind, too.
>>>>
>>>>> If it makes things easier I can start tackling the first step which i=
s
>>>>> mostly refactoring my recent code to enable multiple instances. You
>>>>> can then cleanly build the multiple instance logic on top of that.
>>>>
>>>> It's up to you. Just let me know so that I don't interfere with your w=
ork. I don't want to block you as I'll certainly take much longer to get it=
right (newbie + evenings/weekends only). Today I just set up my dev env an=
d made the build + e2e-tests run on a vm with a minimal kernel. So not much=
done in the code, yet.
>>>>
>>>> Apart from that I got a few thoughts while familiarizing myself with t=
he source that you might be able to comment on:
>>>>
>>>> - Why do we have two flags to distinguish between multi- and single-in=
stance advertising (HCI_ADVERTISING[_INSTANCE])? Doesn't that allow for inc=
onsistencies (=3Dboth true)? Wouldn't it be better to interpret one as "adv=
ertising generally en-/disabled" and the other as a switch between single a=
nd multi adv mode? That would also allow us to keep track of the adv mode w=
hen advertising is temporarily disabled and then re-enabled. As Marcel comm=
ented this might be necessary for some controllers in multi-adv mode when a=
dv data cannot be changed on-the-fly.
>>>
>>> the HCI_ADVERTISING maps to the advertising setting. And it always take=
s precedence. It is essentially instance 0. This fact is actually documente=
d. So if both flags are true, then instance 0 is used and all the other one=
s will be disabled.
>>>
>>>> - What do you think of the idea to handle "set adv" and multi-adv more=
uniformly? I have the following in mind:
>>>> 1) whenever an adv mode switch occurs, all current adv instances will =
be canceled and destroyed
>>>> 2) "set adv" will add/replace a single instance to the list
>>>> 3) "add adv" will add instances up to max_instances
>>>> This would probably dry up the code and duplicate memory structures qu=
ite a bit and also remove some logic quirks.
>>>
>>> See comment above, we can not really change legacy API. It has to stay =
around for backwards compatibility. And that is why set advertising takes p=
recedence over anything added by add advertising.
>>>
>>>> - Instances are currently being identified by an integer "adv_info.ins=
tance". When we add instances more dynamically would it not be better to pa=
ss pointers around and get rid of that integer? That would remove the neces=
sity to keep track of, synchronize and verify instance ids.
>>>
>>> What are you planning to verify here. The instance id is coming from us=
erspace.
>>>
>>>> - The mgmt_rp_read_adv_features structure contains an unused instance[=
0]. Seems to be redundant and could be removed, right?
>>>
>>> Read up on what instance[0] actually does in a struct. We have used the=
se constructs before. I am sensing that you misunderstood what this is for.
>>
>> Sorry for my late response, but I wanted to raise a concern about how
>> you want to rotate advertisement data.
>>
>> When you advertise, you probably want someone to scan and find your
>> device. That might be hard, because filtered LE scan is widely used,
>> i.e. BlueZ uses filtered LE scan, that's restarted every 10 seconds.
>> That means, that during those 10 seconds your remote device will be
>> reported once, and changes you're making to advertised data will not
>> be visible. I think same is true for Windows (you can currently scan
>> only from control panel), and Mac (you can configure it to do
>> non-filtered scan in your app)
>
> I heard about the Windows limitations that you can not scan from your app=
lication at all. That is so different compared to any other operating syste=
ms. I think Windows really has to fix things in that area.
Yes, Windows allows only for scans from Control Panel, and that's
single filtered scan. If they fix that, they might let you do filtered
scan from your app (just like BlueZ does right now), and it still
won't work right with round ribbon, example below.
>
>> When you just modify advertisement data, device that's doing filtered
>> LE scan will report one MAC address only once during this scan (except
>> for CSR, which reports RSSI changes).
>> I recently wrote MGMT_OP_START_SERVICE_DISCOVERY, but it also uses
>> filtered scan, and restarts the scan, but only if device with proper
>> UUID was found. It assumes that UUID was there when device started
>> advertising.
>
> But it also runs for a certain amount of time from the kernel perspective=
. And then userspace has to restart it again if it really wants to scan aga=
in. So that means you will see the new advertising data then.
>
Real world example of how that might go wrong and make you not see
your advertisement:
Machine A run interleaved discovery without simuleanous quirk, using
org.bluez.StartDiscovery. That's 5s LE scan (L), then 5s BREDR inquiry
(B), then 5s delay from BlueZ daemon (D).
Machine B advertises 3 BLE devices, 5s each in round-ribbon, (A, B, C).
If both started perfectly at same time, here's what they do:
LLLLLBBBBBDDDDDLLLLLBBBBBDDDDD
AAAAABBBBBCCCCCAAAAABBBBBCCCCC
>> There are two propertiary solutions I know:
>> - one is used in iOS devices, they have special 'overflow' data, that
>> only other iOS device can see (not even MAC), so they can advertise
>> more in one MAC address. I think it's described here but I'm not 100%
>> sure, only for members:
>> https://www.bluetooth.org/DocMan/handlers/DownloadDoc.ashx?doc_id=3D2844=
51
>
> That is something different. One is a new Bluetooth SIG specification and=
the other is some Broadcom vendor specific behavior that Apple relies on. =
Unreleased Bluetooth SIG specification are also off limit on this mailing l=
ist. They are Bluetooth SIG confidential.
>
>> . To use that you need a special chip that would properly handle this
>> data.
>> - second is used in Android phones (currently only Nexus 6) that can
>> advertise as multiple MAC addresses, each having different adv data at
>> the same time (it might be same thing that broadcom propertiary
>> solution you were discussing). It uses multiple MAC addresses to
>> advertise more, so filtered scan will find those devices and report
>> them properly.
>
> I was considering advertising as multiple random addresses, but that has =
the problem that connection handling becomes really complicated. In the end=
you would run multiple instances of you stack that the chip that multiplex=
es with different addresses. However that has the problem that connection h=
andling is super complicated and this really needs special handling in the =
controller. Otherwise you end up with the simple case that your LE HID devi=
ce can not reconnect. This is something we want to avoid.
>
> However judging from the Android HAL, it has to actually advertise with t=
he same address. At least there is not provision that found quickly that al=
lows to change the address. For some stupid reason it can restrict the chan=
nel map, but I have no idea why you would do that anyway. Except for making=
it easier for sniffers to trace you.
>
>> There's command that rotates mac address:
>> HCI_LE_Set_Resolvable_Private_Address_Timeout, but there's no way to
>> go back to 'previous' mac in order to have something like 'round
>> ribbon'. I'm also not sure whether that would have any effect on
>> currently estabilished connections, I think all devices connected to
>> private address get disconnected when it rotates, but I'm not 100%
>> sure. Also when you rotate MAC, controller will not respond to connect
>> event to old address.
>
> That is for LE Privacy when using RPAs. That is a different thing. And th=
e previously connected devices do not get disconnected. It is perfectly fin=
e to have device A connected to RPA1 and device B connected to RPA2. The co=
ntrollers are actually capable of handling this.
>
> If you would be using LE Privacy, then yes, once you rotate the advertisi=
ng data, you should change the RPA as well. Actually we can do that easily =
in the kernel actually. You just set the HCI_RPA_EXPIRED flag and the core =
will take care of the rest. We already do that once an encryption attempt f=
ails so that a new address is used the next time around.
>
>> The other problem is that rotating advertisement will cause slow discove=
ry.
>>
>> So I think rotating only adv data is not good idea. Maybe we can have
>> different mechanism that decide what gets advertised ? I.e.
>> application that's in foreground is deciding what gets advertised. Or
>> applications register their advertisements, and user can pick from
>> system menu what is currently being advertised ?
>
> That is up to bluetoothd. If it chooses to only utilize a single instance=
, then that is fine. That is a policy decision that does not belong into th=
e kernel.
>
> Regards
>
> Marcel
>
Hi Jakub,
>>>> Now that most of the logic for a single instance is in place it should
>>>> be straightforward to extend it for multiple instances. I would start
>>>> by turning the adv_instance field of hci_dev into a list of
>>>> adv_instances and a way to determine and get a pointer to the
>>>> currently active instance.
>>>
>>> Yes, agreed. That's exactly where I started. Happy to hear that you got the same procedure in mind. I experimented with a dynamically extended array and a linked list. The latter seems to be the better choice as it allows us to easily remove entries in the middle of the list.
>>>
>>>> You would then modify the code in
>>>> net/bluetooth/mgmt.c that accesses the instance 1 parameters to use
>>>> the new getter instead. Once all of that is done, the second step
>>>> would be a matter of inserting new elements into the advertising list
>>>> and handling the round-robin logic and the duration parameter.
>>>
>>> Agreed. That's what I had in mind, too.
>>>
>>>> If it makes things easier I can start tackling the first step which is
>>>> mostly refactoring my recent code to enable multiple instances. You
>>>> can then cleanly build the multiple instance logic on top of that.
>>>
>>> It's up to you. Just let me know so that I don't interfere with your work. I don't want to block you as I'll certainly take much longer to get it right (newbie + evenings/weekends only). Today I just set up my dev env and made the build + e2e-tests run on a vm with a minimal kernel. So not much done in the code, yet.
>>>
>>> Apart from that I got a few thoughts while familiarizing myself with the source that you might be able to comment on:
>>>
>>> - Why do we have two flags to distinguish between multi- and single-instance advertising (HCI_ADVERTISING[_INSTANCE])? Doesn't that allow for inconsistencies (=both true)? Wouldn't it be better to interpret one as "advertising generally en-/disabled" and the other as a switch between single and multi adv mode? That would also allow us to keep track of the adv mode when advertising is temporarily disabled and then re-enabled. As Marcel commented this might be necessary for some controllers in multi-adv mode when adv data cannot be changed on-the-fly.
>>
>> the HCI_ADVERTISING maps to the advertising setting. And it always takes precedence. It is essentially instance 0. This fact is actually documented. So if both flags are true, then instance 0 is used and all the other ones will be disabled.
>>
>>> - What do you think of the idea to handle "set adv" and multi-adv more uniformly? I have the following in mind:
>>> 1) whenever an adv mode switch occurs, all current adv instances will be canceled and destroyed
>>> 2) "set adv" will add/replace a single instance to the list
>>> 3) "add adv" will add instances up to max_instances
>>> This would probably dry up the code and duplicate memory structures quite a bit and also remove some logic quirks.
>>
>> See comment above, we can not really change legacy API. It has to stay around for backwards compatibility. And that is why set advertising takes precedence over anything added by add advertising.
>>
>>> - Instances are currently being identified by an integer "adv_info.instance". When we add instances more dynamically would it not be better to pass pointers around and get rid of that integer? That would remove the necessity to keep track of, synchronize and verify instance ids.
>>
>> What are you planning to verify here. The instance id is coming from userspace.
>>
>>> - The mgmt_rp_read_adv_features structure contains an unused instance[0]. Seems to be redundant and could be removed, right?
>>
>> Read up on what instance[0] actually does in a struct. We have used these constructs before. I am sensing that you misunderstood what this is for.
>
> Sorry for my late response, but I wanted to raise a concern about how
> you want to rotate advertisement data.
>
> When you advertise, you probably want someone to scan and find your
> device. That might be hard, because filtered LE scan is widely used,
> i.e. BlueZ uses filtered LE scan, that's restarted every 10 seconds.
> That means, that during those 10 seconds your remote device will be
> reported once, and changes you're making to advertised data will not
> be visible. I think same is true for Windows (you can currently scan
> only from control panel), and Mac (you can configure it to do
> non-filtered scan in your app)
I heard about the Windows limitations that you can not scan from your application at all. That is so different compared to any other operating systems. I think Windows really has to fix things in that area.
> When you just modify advertisement data, device that's doing filtered
> LE scan will report one MAC address only once during this scan (except
> for CSR, which reports RSSI changes).
> I recently wrote MGMT_OP_START_SERVICE_DISCOVERY, but it also uses
> filtered scan, and restarts the scan, but only if device with proper
> UUID was found. It assumes that UUID was there when device started
> advertising.
But it also runs for a certain amount of time from the kernel perspective. And then userspace has to restart it again if it really wants to scan again. So that means you will see the new advertising data then.
> There are two propertiary solutions I know:
> - one is used in iOS devices, they have special 'overflow' data, that
> only other iOS device can see (not even MAC), so they can advertise
> more in one MAC address. I think it's described here but I'm not 100%
> sure, only for members:
> https://www.bluetooth.org/DocMan/handlers/DownloadDoc.ashx?doc_id=284451
That is something different. One is a new Bluetooth SIG specification and the other is some Broadcom vendor specific behavior that Apple relies on. Unreleased Bluetooth SIG specification are also off limit on this mailing list. They are Bluetooth SIG confidential.
> . To use that you need a special chip that would properly handle this
> data.
> - second is used in Android phones (currently only Nexus 6) that can
> advertise as multiple MAC addresses, each having different adv data at
> the same time (it might be same thing that broadcom propertiary
> solution you were discussing). It uses multiple MAC addresses to
> advertise more, so filtered scan will find those devices and report
> them properly.
I was considering advertising as multiple random addresses, but that has the problem that connection handling becomes really complicated. In the end you would run multiple instances of you stack that the chip that multiplexes with different addresses. However that has the problem that connection handling is super complicated and this really needs special handling in the controller. Otherwise you end up with the simple case that your LE HID device can not reconnect. This is something we want to avoid.
However judging from the Android HAL, it has to actually advertise with the same address. At least there is not provision that found quickly that allows to change the address. For some stupid reason it can restrict the channel map, but I have no idea why you would do that anyway. Except for making it easier for sniffers to trace you.
> There's command that rotates mac address:
> HCI_LE_Set_Resolvable_Private_Address_Timeout, but there's no way to
> go back to 'previous' mac in order to have something like 'round
> ribbon'. I'm also not sure whether that would have any effect on
> currently estabilished connections, I think all devices connected to
> private address get disconnected when it rotates, but I'm not 100%
> sure. Also when you rotate MAC, controller will not respond to connect
> event to old address.
That is for LE Privacy when using RPAs. That is a different thing. And the previously connected devices do not get disconnected. It is perfectly fine to have device A connected to RPA1 and device B connected to RPA2. The controllers are actually capable of handling this.
If you would be using LE Privacy, then yes, once you rotate the advertising data, you should change the RPA as well. Actually we can do that easily in the kernel actually. You just set the HCI_RPA_EXPIRED flag and the core will take care of the rest. We already do that once an encryption attempt fails so that a new address is used the next time around.
> The other problem is that rotating advertisement will cause slow discovery.
>
> So I think rotating only adv data is not good idea. Maybe we can have
> different mechanism that decide what gets advertised ? I.e.
> application that's in foreground is deciding what gets advertised. Or
> applications register their advertisements, and user can pick from
> system menu what is currently being advertised ?
That is up to bluetoothd. If it chooses to only utilize a single instance, then that is fine. That is a policy decision that does not belong into the kernel.
Regards
Marcel
On Mon, Mar 30, 2015 at 10:44 AM, Arman Uguray <[email protected]> wrote=
:
> Hi Jakub,
>
>> On Mon, Mar 30, 2015 at 10:23 AM, Jakub Pawlowski <[email protected]=
> wrote:
>> On Sun, Mar 29, 2015 at 5:48 PM, Marcel Holtmann <[email protected]> w=
rote:
>>> Hi Florian,
>>>
>>>> > Now that most of the logic for a single instance is in place it shou=
ld
>>>>> be straightforward to extend it for multiple instances. I would start
>>>>> by turning the adv_instance field of hci_dev into a list of
>>>>> adv_instances and a way to determine and get a pointer to the
>>>>> currently active instance.
>>>>
>>>> Yes, agreed. That's exactly where I started. Happy to hear that you go=
t the same procedure in mind. I experimented with a dynamically extended ar=
ray and a linked list. The latter seems to be the better choice as it allow=
s us to easily remove entries in the middle of the list.
>>>>
>>>>> You would then modify the code in
>>>>> net/bluetooth/mgmt.c that accesses the instance 1 parameters to use
>>>>> the new getter instead. Once all of that is done, the second step
>>>>> would be a matter of inserting new elements into the advertising list
>>>>> and handling the round-robin logic and the duration parameter.
>>>>
>>>> Agreed. That's what I had in mind, too.
>>>>
>>>>> If it makes things easier I can start tackling the first step which i=
s
>>>>> mostly refactoring my recent code to enable multiple instances. You
>>>>> can then cleanly build the multiple instance logic on top of that.
>>>>
>>>> It's up to you. Just let me know so that I don't interfere with your w=
ork. I don't want to block you as I'll certainly take much longer to get it=
right (newbie + evenings/weekends only). Today I just set up my dev env an=
d made the build + e2e-tests run on a vm with a minimal kernel. So not much=
done in the code, yet.
>>>>
>>>> Apart from that I got a few thoughts while familiarizing myself with t=
he source that you might be able to comment on:
>>>>
>>>> - Why do we have two flags to distinguish between multi- and single-in=
stance advertising (HCI_ADVERTISING[_INSTANCE])? Doesn't that allow for inc=
onsistencies (=3Dboth true)? Wouldn't it be better to interpret one as "adv=
ertising generally en-/disabled" and the other as a switch between single a=
nd multi adv mode? That would also allow us to keep track of the adv mode w=
hen advertising is temporarily disabled and then re-enabled. As Marcel comm=
ented this might be necessary for some controllers in multi-adv mode when a=
dv data cannot be changed on-the-fly.
>>>
>>> the HCI_ADVERTISING maps to the advertising setting. And it always take=
s precedence. It is essentially instance 0. This fact is actually documente=
d. So if both flags are true, then instance 0 is used and all the other one=
s will be disabled.
>>>
>>>> - What do you think of the idea to handle "set adv" and multi-adv more=
uniformly? I have the following in mind:
>>>> 1) whenever an adv mode switch occurs, all current adv instances will =
be canceled and destroyed
>>>> 2) "set adv" will add/replace a single instance to the list
>>>> 3) "add adv" will add instances up to max_instances
>>>> This would probably dry up the code and duplicate memory structures qu=
ite a bit and also remove some logic quirks.
>>>
>>> See comment above, we can not really change legacy API. It has to stay =
around for backwards compatibility. And that is why set advertising takes p=
recedence over anything added by add advertising.
>>>
>>>> - Instances are currently being identified by an integer "adv_info.ins=
tance". When we add instances more dynamically would it not be better to pa=
ss pointers around and get rid of that integer? That would remove the neces=
sity to keep track of, synchronize and verify instance ids.
>>>
>>> What are you planning to verify here. The instance id is coming from us=
erspace.
>>>
>>>> - The mgmt_rp_read_adv_features structure contains an unused instance[=
0]. Seems to be redundant and could be removed, right?
>>>
>>> Read up on what instance[0] actually does in a struct. We have used the=
se constructs before. I am sensing that you misunderstood what this is for.
>>
>> Sorry for my late response, but I wanted to raise a concern about how
>> you want to rotate advertisement data.
>>
>> When you advertise, you probably want someone to scan and find your
>> device. That might be hard, because filtered LE scan is widely used,
>> i.e. BlueZ uses filtered LE scan, that's restarted every 10 seconds.
>> That means, that during those 10 seconds your remote device will be
>> reported once, and changes you're making to advertised data will not
>> be visible. I think same is true for Windows (you can currently scan
>> only from control panel), and Mac (you can configure it to do
>> non-filtered scan in your app)
>>
>> When you just modify advertisement data, device that's doing filtered
>> LE scan will report one MAC address only once during this scan (except
>> for CSR, which reports RSSI changes).
>> I recently wrote MGMT_OP_START_SERVICE_DISCOVERY, but it also uses
>> filtered scan, and restarts the scan, but only if device with proper
>> UUID was found. It assumes that UUID was there when device started
>> advertising.
>>
>>
>> There are two propertiary solutions I know:
>> - one is used in iOS devices, they have special 'overflow' data, that
>> only other iOS device can see (not even MAC), so they can advertise
>> more in one MAC address. I think it's described here but I'm not 100%
>> sure, only for members:
>> https://www.bluetooth.org/DocMan/handlers/DownloadDoc.ashx?doc_id=3D2844=
51
>> . To use that you need a special chip that would properly handle this
>> data.
>> - second is used in Android phones (currently only Nexus 6) that can
>> advertise as multiple MAC addresses, each having different adv data at
>> the same time (it might be same thing that broadcom propertiary
>> solution you were discussing). It uses multiple MAC addresses to
>> advertise more, so filtered scan will find those devices and report
>> them properly.
>>
>>
>> There's command that rotates mac address:
>> HCI_LE_Set_Resolvable_Private_Address_Timeout, but there's no way to
>> go back to 'previous' mac in order to have something like 'round
>> ribbon'. I'm also not sure whether that would have any effect on
>> currently estabilished connections, I think all devices connected to
>> private address get disconnected when it rotates, but I'm not 100%
>> sure. Also when you rotate MAC, controller will not respond to connect
>> event to old address.
>>
>> The other problem is that rotating advertisement will cause slow discove=
ry.
>>
>> So I think rotating only adv data is not good idea. Maybe we can have
>> different mechanism that decide what gets advertised ? I.e.
>> application that's in foreground is deciding what gets advertised. Or
>> applications register their advertisements, and user can pick from
>> system menu what is currently being advertised ?
>>
>
> I think you're overthinking what this API does. At the mgmt layer we
> don't have a concept of a "foreground app". We simply have a way for
> userspace to enter new advertising instances. If there's some special
> magic in hardware this code can take advantage of that in the future
> using some driver interface, otherwise it just reprograms the
> controller in software, so the round robin is managed in the kernel.
> That's all there is to this API. How the userspace wants to manage
> this is up to the daemon.
>
Ok, I probably shouldn't even mention 'foreground' app solution, or
picking app. My main concern was that if you advertise in round ribbon
right now, it will just not work, because of the way scanning is done.
And that's pretty serious.
>>
>>
>>>
>>> Regards
>>>
>>> Marcel
>>>
>>> --
>>> To unsubscribe from this list: send the line "unsubscribe linux-bluetoo=
th" in
>>> the body of a message to [email protected]
>>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
> Thanks,
> Arman
Hi Jakub,
> On Mon, Mar 30, 2015 at 10:23 AM, Jakub Pawlowski <[email protected]>=
wrote:
> On Sun, Mar 29, 2015 at 5:48 PM, Marcel Holtmann <[email protected]> wr=
ote:
>> Hi Florian,
>>
>>> > Now that most of the logic for a single instance is in place it shoul=
d
>>>> be straightforward to extend it for multiple instances. I would start
>>>> by turning the adv_instance field of hci_dev into a list of
>>>> adv_instances and a way to determine and get a pointer to the
>>>> currently active instance.
>>>
>>> Yes, agreed. That's exactly where I started. Happy to hear that you got=
the same procedure in mind. I experimented with a dynamically extended arr=
ay and a linked list. The latter seems to be the better choice as it allows=
us to easily remove entries in the middle of the list.
>>>
>>>> You would then modify the code in
>>>> net/bluetooth/mgmt.c that accesses the instance 1 parameters to use
>>>> the new getter instead. Once all of that is done, the second step
>>>> would be a matter of inserting new elements into the advertising list
>>>> and handling the round-robin logic and the duration parameter.
>>>
>>> Agreed. That's what I had in mind, too.
>>>
>>>> If it makes things easier I can start tackling the first step which is
>>>> mostly refactoring my recent code to enable multiple instances. You
>>>> can then cleanly build the multiple instance logic on top of that.
>>>
>>> It's up to you. Just let me know so that I don't interfere with your wo=
rk. I don't want to block you as I'll certainly take much longer to get it =
right (newbie + evenings/weekends only). Today I just set up my dev env and=
made the build + e2e-tests run on a vm with a minimal kernel. So not much =
done in the code, yet.
>>>
>>> Apart from that I got a few thoughts while familiarizing myself with th=
e source that you might be able to comment on:
>>>
>>> - Why do we have two flags to distinguish between multi- and single-ins=
tance advertising (HCI_ADVERTISING[_INSTANCE])? Doesn't that allow for inco=
nsistencies (=3Dboth true)? Wouldn't it be better to interpret one as "adve=
rtising generally en-/disabled" and the other as a switch between single an=
d multi adv mode? That would also allow us to keep track of the adv mode wh=
en advertising is temporarily disabled and then re-enabled. As Marcel comme=
nted this might be necessary for some controllers in multi-adv mode when ad=
v data cannot be changed on-the-fly.
>>
>> the HCI_ADVERTISING maps to the advertising setting. And it always takes=
precedence. It is essentially instance 0. This fact is actually documented=
. So if both flags are true, then instance 0 is used and all the other ones=
will be disabled.
>>
>>> - What do you think of the idea to handle "set adv" and multi-adv more =
uniformly? I have the following in mind:
>>> 1) whenever an adv mode switch occurs, all current adv instances will b=
e canceled and destroyed
>>> 2) "set adv" will add/replace a single instance to the list
>>> 3) "add adv" will add instances up to max_instances
>>> This would probably dry up the code and duplicate memory structures qui=
te a bit and also remove some logic quirks.
>>
>> See comment above, we can not really change legacy API. It has to stay a=
round for backwards compatibility. And that is why set advertising takes pr=
ecedence over anything added by add advertising.
>>
>>> - Instances are currently being identified by an integer "adv_info.inst=
ance". When we add instances more dynamically would it not be better to pas=
s pointers around and get rid of that integer? That would remove the necess=
ity to keep track of, synchronize and verify instance ids.
>>
>> What are you planning to verify here. The instance id is coming from use=
rspace.
>>
>>> - The mgmt_rp_read_adv_features structure contains an unused instance[0=
]. Seems to be redundant and could be removed, right?
>>
>> Read up on what instance[0] actually does in a struct. We have used thes=
e constructs before. I am sensing that you misunderstood what this is for.
>
> Sorry for my late response, but I wanted to raise a concern about how
> you want to rotate advertisement data.
>
> When you advertise, you probably want someone to scan and find your
> device. That might be hard, because filtered LE scan is widely used,
> i.e. BlueZ uses filtered LE scan, that's restarted every 10 seconds.
> That means, that during those 10 seconds your remote device will be
> reported once, and changes you're making to advertised data will not
> be visible. I think same is true for Windows (you can currently scan
> only from control panel), and Mac (you can configure it to do
> non-filtered scan in your app)
>
> When you just modify advertisement data, device that's doing filtered
> LE scan will report one MAC address only once during this scan (except
> for CSR, which reports RSSI changes).
> I recently wrote MGMT_OP_START_SERVICE_DISCOVERY, but it also uses
> filtered scan, and restarts the scan, but only if device with proper
> UUID was found. It assumes that UUID was there when device started
> advertising.
>
>
> There are two propertiary solutions I know:
> - one is used in iOS devices, they have special 'overflow' data, that
> only other iOS device can see (not even MAC), so they can advertise
> more in one MAC address. I think it's described here but I'm not 100%
> sure, only for members:
> https://www.bluetooth.org/DocMan/handlers/DownloadDoc.ashx?doc_id=3D28445=
1
> . To use that you need a special chip that would properly handle this
> data.
> - second is used in Android phones (currently only Nexus 6) that can
> advertise as multiple MAC addresses, each having different adv data at
> the same time (it might be same thing that broadcom propertiary
> solution you were discussing). It uses multiple MAC addresses to
> advertise more, so filtered scan will find those devices and report
> them properly.
>
>
> There's command that rotates mac address:
> HCI_LE_Set_Resolvable_Private_Address_Timeout, but there's no way to
> go back to 'previous' mac in order to have something like 'round
> ribbon'. I'm also not sure whether that would have any effect on
> currently estabilished connections, I think all devices connected to
> private address get disconnected when it rotates, but I'm not 100%
> sure. Also when you rotate MAC, controller will not respond to connect
> event to old address.
>
> The other problem is that rotating advertisement will cause slow discover=
y.
>
> So I think rotating only adv data is not good idea. Maybe we can have
> different mechanism that decide what gets advertised ? I.e.
> application that's in foreground is deciding what gets advertised. Or
> applications register their advertisements, and user can pick from
> system menu what is currently being advertised ?
>
I think you're overthinking what this API does. At the mgmt layer we
don't have a concept of a "foreground app". We simply have a way for
userspace to enter new advertising instances. If there's some special
magic in hardware this code can take advantage of that in the future
using some driver interface, otherwise it just reprograms the
controller in software, so the round robin is managed in the kernel.
That's all there is to this API. How the userspace wants to manage
this is up to the daemon.
>
>
>>
>> Regards
>>
>> Marcel
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-bluetoot=
h" in
>> the body of a message to [email protected]
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
Thanks,
Arman
On Sun, Mar 29, 2015 at 5:48 PM, Marcel Holtmann <[email protected]> wrot=
e:
> Hi Florian,
>
>> > Now that most of the logic for a single instance is in place it should
>>> be straightforward to extend it for multiple instances. I would start
>>> by turning the adv_instance field of hci_dev into a list of
>>> adv_instances and a way to determine and get a pointer to the
>>> currently active instance.
>>
>> Yes, agreed. That's exactly where I started. Happy to hear that you got =
the same procedure in mind. I experimented with a dynamically extended arra=
y and a linked list. The latter seems to be the better choice as it allows =
us to easily remove entries in the middle of the list.
>>
>>> You would then modify the code in
>>> net/bluetooth/mgmt.c that accesses the instance 1 parameters to use
>>> the new getter instead. Once all of that is done, the second step
>>> would be a matter of inserting new elements into the advertising list
>>> and handling the round-robin logic and the duration parameter.
>>
>> Agreed. That's what I had in mind, too.
>>
>>> If it makes things easier I can start tackling the first step which is
>>> mostly refactoring my recent code to enable multiple instances. You
>>> can then cleanly build the multiple instance logic on top of that.
>>
>> It's up to you. Just let me know so that I don't interfere with your wor=
k. I don't want to block you as I'll certainly take much longer to get it r=
ight (newbie + evenings/weekends only). Today I just set up my dev env and =
made the build + e2e-tests run on a vm with a minimal kernel. So not much d=
one in the code, yet.
>>
>> Apart from that I got a few thoughts while familiarizing myself with the=
source that you might be able to comment on:
>>
>> - Why do we have two flags to distinguish between multi- and single-inst=
ance advertising (HCI_ADVERTISING[_INSTANCE])? Doesn't that allow for incon=
sistencies (=3Dboth true)? Wouldn't it be better to interpret one as "adver=
tising generally en-/disabled" and the other as a switch between single and=
multi adv mode? That would also allow us to keep track of the adv mode whe=
n advertising is temporarily disabled and then re-enabled. As Marcel commen=
ted this might be necessary for some controllers in multi-adv mode when adv=
data cannot be changed on-the-fly.
>
> the HCI_ADVERTISING maps to the advertising setting. And it always takes =
precedence. It is essentially instance 0. This fact is actually documented.=
So if both flags are true, then instance 0 is used and all the other ones =
will be disabled.
>
>> - What do you think of the idea to handle "set adv" and multi-adv more u=
niformly? I have the following in mind:
>> 1) whenever an adv mode switch occurs, all current adv instances will be=
canceled and destroyed
>> 2) "set adv" will add/replace a single instance to the list
>> 3) "add adv" will add instances up to max_instances
>> This would probably dry up the code and duplicate memory structures quit=
e a bit and also remove some logic quirks.
>
> See comment above, we can not really change legacy API. It has to stay ar=
ound for backwards compatibility. And that is why set advertising takes pre=
cedence over anything added by add advertising.
>
>> - Instances are currently being identified by an integer "adv_info.insta=
nce". When we add instances more dynamically would it not be better to pass=
pointers around and get rid of that integer? That would remove the necessi=
ty to keep track of, synchronize and verify instance ids.
>
> What are you planning to verify here. The instance id is coming from user=
space.
>
>> - The mgmt_rp_read_adv_features structure contains an unused instance[0]=
. Seems to be redundant and could be removed, right?
>
> Read up on what instance[0] actually does in a struct. We have used these=
constructs before. I am sensing that you misunderstood what this is for.
Sorry for my late response, but I wanted to raise a concern about how
you want to rotate advertisement data.
When you advertise, you probably want someone to scan and find your
device. That might be hard, because filtered LE scan is widely used,
i.e. BlueZ uses filtered LE scan, that's restarted every 10 seconds.
That means, that during those 10 seconds your remote device will be
reported once, and changes you're making to advertised data will not
be visible. I think same is true for Windows (you can currently scan
only from control panel), and Mac (you can configure it to do
non-filtered scan in your app)
When you just modify advertisement data, device that's doing filtered
LE scan will report one MAC address only once during this scan (except
for CSR, which reports RSSI changes).
I recently wrote MGMT_OP_START_SERVICE_DISCOVERY, but it also uses
filtered scan, and restarts the scan, but only if device with proper
UUID was found. It assumes that UUID was there when device started
advertising.
There are two propertiary solutions I know:
- one is used in iOS devices, they have special 'overflow' data, that
only other iOS device can see (not even MAC), so they can advertise
more in one MAC address. I think it's described here but I'm not 100%
sure, only for members:
https://www.bluetooth.org/DocMan/handlers/DownloadDoc.ashx?doc_id=3D284451
. To use that you need a special chip that would properly handle this
data.
- second is used in Android phones (currently only Nexus 6) that can
advertise as multiple MAC addresses, each having different adv data at
the same time (it might be same thing that broadcom propertiary
solution you were discussing). It uses multiple MAC addresses to
advertise more, so filtered scan will find those devices and report
them properly.
There's command that rotates mac address:
HCI_LE_Set_Resolvable_Private_Address_Timeout, but there's no way to
go back to 'previous' mac in order to have something like 'round
ribbon'. I'm also not sure whether that would have any effect on
currently estabilished connections, I think all devices connected to
private address get disconnected when it rotates, but I'm not 100%
sure. Also when you rotate MAC, controller will not respond to connect
event to old address.
The other problem is that rotating advertisement will cause slow discovery.
So I think rotating only adv data is not good idea. Maybe we can have
different mechanism that decide what gets advertised ? I.e.
application that's in foreground is deciding what gets advertised. Or
applications register their advertisements, and user can pick from
system menu what is currently being advertised ?
>
> Regards
>
> Marcel
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth=
" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
Hi Florian,
> > Now that most of the logic for a single instance is in place it should
>> be straightforward to extend it for multiple instances. I would start
>> by turning the adv_instance field of hci_dev into a list of
>> adv_instances and a way to determine and get a pointer to the
>> currently active instance.
>
> Yes, agreed. That's exactly where I started. Happy to hear that you got the same procedure in mind. I experimented with a dynamically extended array and a linked list. The latter seems to be the better choice as it allows us to easily remove entries in the middle of the list.
>
>> You would then modify the code in
>> net/bluetooth/mgmt.c that accesses the instance 1 parameters to use
>> the new getter instead. Once all of that is done, the second step
>> would be a matter of inserting new elements into the advertising list
>> and handling the round-robin logic and the duration parameter.
>
> Agreed. That's what I had in mind, too.
>
>> If it makes things easier I can start tackling the first step which is
>> mostly refactoring my recent code to enable multiple instances. You
>> can then cleanly build the multiple instance logic on top of that.
>
> It's up to you. Just let me know so that I don't interfere with your work. I don't want to block you as I'll certainly take much longer to get it right (newbie + evenings/weekends only). Today I just set up my dev env and made the build + e2e-tests run on a vm with a minimal kernel. So not much done in the code, yet.
>
> Apart from that I got a few thoughts while familiarizing myself with the source that you might be able to comment on:
>
> - Why do we have two flags to distinguish between multi- and single-instance advertising (HCI_ADVERTISING[_INSTANCE])? Doesn't that allow for inconsistencies (=both true)? Wouldn't it be better to interpret one as "advertising generally en-/disabled" and the other as a switch between single and multi adv mode? That would also allow us to keep track of the adv mode when advertising is temporarily disabled and then re-enabled. As Marcel commented this might be necessary for some controllers in multi-adv mode when adv data cannot be changed on-the-fly.
the HCI_ADVERTISING maps to the advertising setting. And it always takes precedence. It is essentially instance 0. This fact is actually documented. So if both flags are true, then instance 0 is used and all the other ones will be disabled.
> - What do you think of the idea to handle "set adv" and multi-adv more uniformly? I have the following in mind:
> 1) whenever an adv mode switch occurs, all current adv instances will be canceled and destroyed
> 2) "set adv" will add/replace a single instance to the list
> 3) "add adv" will add instances up to max_instances
> This would probably dry up the code and duplicate memory structures quite a bit and also remove some logic quirks.
See comment above, we can not really change legacy API. It has to stay around for backwards compatibility. And that is why set advertising takes precedence over anything added by add advertising.
> - Instances are currently being identified by an integer "adv_info.instance". When we add instances more dynamically would it not be better to pass pointers around and get rid of that integer? That would remove the necessity to keep track of, synchronize and verify instance ids.
What are you planning to verify here. The instance id is coming from userspace.
> - The mgmt_rp_read_adv_features structure contains an unused instance[0]. Seems to be redundant and could be removed, right?
Read up on what instance[0] actually does in a struct. We have used these constructs before. I am sensing that you misunderstood what this is for.
Regards
Marcel
Hi Arman,
> Now that most of the logic for a single instance is in place it should
> be straightforward to extend it for multiple instances. I would start
> by turning the adv_instance field of hci_dev into a list of
> adv_instances and a way to determine and get a pointer to the
> currently active instance.
Yes, agreed. That's exactly where I started. Happy to hear that you got
the same procedure in mind. I experimented with a dynamically extended
array and a linked list. The latter seems to be the better choice as it
allows us to easily remove entries in the middle of the list.
> You would then modify the code in
> net/bluetooth/mgmt.c that accesses the instance 1 parameters to use
> the new getter instead. Once all of that is done, the second step
> would be a matter of inserting new elements into the advertising list
> and handling the round-robin logic and the duration parameter.
Agreed. That's what I had in mind, too.
> If it makes things easier I can start tackling the first step which is
> mostly refactoring my recent code to enable multiple instances. You
> can then cleanly build the multiple instance logic on top of that.
It's up to you. Just let me know so that I don't interfere with your
work. I don't want to block you as I'll certainly take much longer to
get it right (newbie + evenings/weekends only). Today I just set up my
dev env and made the build + e2e-tests run on a vm with a minimal
kernel. So not much done in the code, yet.
Apart from that I got a few thoughts while familiarizing myself with the
source that you might be able to comment on:
- Why do we have two flags to distinguish between multi- and
single-instance advertising (HCI_ADVERTISING[_INSTANCE])? Doesn't that
allow for inconsistencies (=both true)? Wouldn't it be better to
interpret one as "advertising generally en-/disabled" and the other as a
switch between single and multi adv mode? That would also allow us to
keep track of the adv mode when advertising is temporarily disabled and
then re-enabled. As Marcel commented this might be necessary for some
controllers in multi-adv mode when adv data cannot be changed on-the-fly.
- What do you think of the idea to handle "set adv" and multi-adv more
uniformly? I have the following in mind:
1) whenever an adv mode switch occurs, all current adv instances will be
canceled and destroyed
2) "set adv" will add/replace a single instance to the list
3) "add adv" will add instances up to max_instances
This would probably dry up the code and duplicate memory structures
quite a bit and also remove some logic quirks.
- Instances are currently being identified by an integer
"adv_info.instance". When we add instances more dynamically would it not
be better to pass pointers around and get rid of that integer? That
would remove the necessity to keep track of, synchronize and verify
instance ids.
- The mgmt_rp_read_adv_features structure contains an unused
instance[0]. Seems to be redundant and could be removed, right?
Well, that's it for the moment. Thanks for being so friendly to a newcomer.
Florian
Hi Florian,
> On Sat, Mar 28, 2015 at 6:32 AM, Florian Grandel <[email protected]> wrote:
>>
>>
>> Whatever you read in the link layer section is something you can forget
>> about right now. That is why the mgmt API actually does not mention
>> advertising delay or internal or alike. It is a bit higher level API with
>> the same affect. It is just less efficient to do that in kernel, then in the
>> controller.
>>
>> So here is how it is suppose to be done. The duration parameter controls
>> the length an advertising instance stays active. Let say you have two
>> instances, both with 5 seconds each as duration parameter. All instances
>> will be scheduled in round robin fashion.
>>
>> instance 1 -> 5 seconds, instance 2 -> 5 seconds, instance 1 -> 5
>> seconds and so on
>>
>> One thing we need to figure out if controllers let us change the
>> advertising data and scan response data on the fly without disabling
>> advertising or if we have to disable it first. Maybe this needs quirking if
>> different controllers behave differently.
>>
>> This is as close as we get towards multi-advertising that we just emulate
>> in the host. If there is a controller with offload capabilities, we can at
>> some point just start using it. However that is not the main concern. It has
>> to work on standard hardware as well. Even if it is less efficient.
>>
>
> Got it. Makes all sense to me.
>
> I also found the documentation for the command in mgmt-api.txt in the
> meantime.
>
> I'll see how far I get from here then...
>
Now that most of the logic for a single instance is in place it should
be straightforward to extend it for multiple instances. I would start
by turning the adv_instance field of hci_dev into a list of
adv_instances and a way to determine and get a pointer to the
currently active instance. You would then modify the code in
net/bluetooth/mgmt.c that accesses the instance 1 parameters to use
the new getter instead. Once all of that is done, the second step
would be a matter of inserting new elements into the advertising list
and handling the round-robin logic and the duration parameter.
If it makes things easier I can start tackling the first step which is
mostly refactoring my recent code to enable multiple instances. You
can then cleanly build the multiple instance logic on top of that.
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth"
> in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
Thanks,
Arman
>
> Whatever you read in the link layer section is something you can forget about right now. That is why the mgmt API actually does not mention advertising delay or internal or alike. It is a bit higher level API with the same affect. It is just less efficient to do that in kernel, then in the controller.
>
> So here is how it is suppose to be done. The duration parameter controls the length an advertising instance stays active. Let say you have two instances, both with 5 seconds each as duration parameter. All instances will be scheduled in round robin fashion.
>
> instance 1 -> 5 seconds, instance 2 -> 5 seconds, instance 1 -> 5 seconds and so on
>
> One thing we need to figure out if controllers let us change the advertising data and scan response data on the fly without disabling advertising or if we have to disable it first. Maybe this needs quirking if different controllers behave differently.
>
> This is as close as we get towards multi-advertising that we just emulate in the host. If there is a controller with offload capabilities, we can at some point just start using it. However that is not the main concern. It has to work on standard hardware as well. Even if it is less efficient.
>
Got it. Makes all sense to me.
I also found the documentation for the command in mgmt-api.txt in the
meantime.
I'll see how far I get from here then...
Hi Florian,
>> the kernel side has currently only support for 1 advertising
>> instance. That needs to be fixed or you need to do the rotation in
>> the HAL and fake it that way. Ideally you do that in the kernel since
>> it has better control over the hardware than userspace ever will be.
>> However it would work by faking it in the HAL.
>
> If I'm not mistaken then bluez kernel drivers rely exclusively on standard HCI commands in communicating with bluetooth hardware.
>
> Multi-advertising doesn't seem to be a standard HCI procedure, though. It rather seems to be a (broadcom?) vendor-specific addition we cannot rely on in general. I didn't find any good documentation on vendor specific HCI command sets either. Do you have something there?
>
> Please correct me if I'm on the wrong track, but doesn't that mean that we have to emulate multi-advertising in any case, even if it was in the kernel?
yes, you have to emulate it. However want to do that in the kernel since it has less overhead and lets the userspace being undisturbed.
> As the new advertising mgmt api already has been designed with multiple advertising instances in mind it seems a natural choice to implement the multi-advertising emulation in the mgmt layer. But as I'm a complete bluetooth/bluez newbie, I might be completely mistaken here.
>
> What I'm wondering about are the implementation options we have for the emulation, especially when it comes to timing. How would we schedule advertisement data updates wrt min/max advertising intervals?
>
> If we maintain the current advertising instance data structure with separate advertising interval settings per instance then I'd expect advertisement events to interleave somehow like this:
>
> advEvt1
> |xxx|................|---|xxx|................|---|xxx|...
> advInt1 advDelay
>
> advEvt2
> ....|---|xxx|................|---|xxx|................|---
> advInt2
>
> advEvt3
> ............|---|xxx|....................................|---|xxx|..
> advInt3
>
> Advertisement intervals would have to be multiples of a common factor to avoid event collisions. And the interval would have to be long enough to fit all instances into one cycle.
>
> Alternatively we could schedule adv evts with a common adv interval like this:
>
> advEvt1 advEvt2 advEvt3
> |xxx|................|---|xxx|................|---|xxx|...
> advInt advDelay
>
> I'd be in favor of the first solution which more closely emulates the existence of independent peripheral devices sharing a common physical adv channel.
>
> (compare BT Core Spec 4.x, Vol 6, Part B, 4.4.2.2)
>
> What I really wonder about, though, is how we'd be able to implement such a timing scheme with nothing but the standard HCI API. How quickly and reliably does the hardware respond to a large number of HCI calls as would be required here? Does it really make sense to implement such a low-level aspect of the protocol in the mgmt api code? What other options do we have? I'm probably making things too complicated...
Whatever you read in the link layer section is something you can forget about right now. That is why the mgmt API actually does not mention advertising delay or internal or alike. It is a bit higher level API with the same affect. It is just less efficient to do that in kernel, then in the controller.
So here is how it is suppose to be done. The duration parameter controls the length an advertising instance stays active. Let say you have two instances, both with 5 seconds each as duration parameter. All instances will be scheduled in round robin fashion.
instance 1 -> 5 seconds, instance 2 -> 5 seconds, instance 1 -> 5 seconds and so on
One thing we need to figure out if controllers let us change the advertising data and scan response data on the fly without disabling advertising or if we have to disable it first. Maybe this needs quirking if different controllers behave differently.
This is as close as we get towards multi-advertising that we just emulate in the host. If there is a controller with offload capabilities, we can at some point just start using it. However that is not the main concern. It has to work on standard hardware as well. Even if it is less efficient.
Regards
Marcel
On 03/28/2015 01:01 AM, Marcel Holtmann wrote:
> the kernel side has currently only support for 1 advertising
> instance. That needs to be fixed or you need to do the rotation in
> the HAL and fake it that way. Ideally you do that in the kernel since
> it has better control over the hardware than userspace ever will be.
> However it would work by faking it in the HAL.
If I'm not mistaken then bluez kernel drivers rely exclusively on
standard HCI commands in communicating with bluetooth hardware.
Multi-advertising doesn't seem to be a standard HCI procedure, though.
It rather seems to be a (broadcom?) vendor-specific addition we cannot
rely on in general. I didn't find any good documentation on vendor
specific HCI command sets either. Do you have something there?
Please correct me if I'm on the wrong track, but doesn't that mean that
we have to emulate multi-advertising in any case, even if it was in the
kernel?
As the new advertising mgmt api already has been designed with multiple
advertising instances in mind it seems a natural choice to implement the
multi-advertising emulation in the mgmt layer. But as I'm a complete
bluetooth/bluez newbie, I might be completely mistaken here.
What I'm wondering about are the implementation options we have for the
emulation, especially when it comes to timing. How would we schedule
advertisement data updates wrt min/max advertising intervals?
If we maintain the current advertising instance data structure with
separate advertising interval settings per instance then I'd expect
advertisement events to interleave somehow like this:
advEvt1
|xxx|................|---|xxx|................|---|xxx|...
advInt1 advDelay
advEvt2
....|---|xxx|................|---|xxx|................|---
advInt2
advEvt3
............|---|xxx|....................................|---|xxx|..
advInt3
Advertisement intervals would have to be multiples of a common factor to
avoid event collisions. And the interval would have to be long enough to
fit all instances into one cycle.
Alternatively we could schedule adv evts with a common adv interval like
this:
advEvt1 advEvt2 advEvt3
|xxx|................|---|xxx|................|---|xxx|...
advInt advDelay
I'd be in favor of the first solution which more closely emulates the
existence of independent peripheral devices sharing a common physical
adv channel.
(compare BT Core Spec 4.x, Vol 6, Part B, 4.4.2.2)
What I really wonder about, though, is how we'd be able to implement
such a timing scheme with nothing but the standard HCI API. How quickly
and reliably does the hardware respond to a large number of HCI calls as
would be required here? Does it really make sense to implement such a
low-level aspect of the protocol in the mgmt api code? What other
options do we have? I'm probably making things too complicated...
Florian
Hi Florian,
> I recently built an autonomous bluetooth LE network (based on Nordic nRF51822 central/nRF8001 peripheral µC) which I use for basic home automation tasks.
>
> To access this network from my Nexus 4 I need to put the phone in a peripheral role so it can connect to the nRF51822 central.
>
> As bluedroid won't support older Nexus phones in a peripheral role anytime soon and is difficult to hack I was looking into bluez as an alternative. I looked through the bluez source over the last few days, watched your latest commits and list conversations, read up all kind of README's and API docs.
>
> I'm pleased to see that you're actively working on the kernel-side LE advertising mgmt API and that you already implemented HAL stubs on the Android side for the Lollipop 5.0 peripheral role enhancements.
>
> It seems that the min requirement for peripheral role support in Android would be at least 5 concurrent multi-advertising instances.
>
> What is your schedule for the implementation of the multi-advertising stubs in the Android bluetoothd HAL daemon? Is someone working on it already? Would you welcome patches? (I never contributed to bluez, though, and would require a bit of initial 1:1 support...)
>
> Is there still something else missing on the kernel side or in userland to make multi-advertisement work? Or is it all just about HAL support now?
the kernel side has currently only support for 1 advertising instance. That needs to be fixed or you need to do the rotation in the HAL and fake it that way. Ideally you do that in the kernel since it has better control over the hardware than userspace ever will be. However it would work by faking it in the HAL.
The HAL also needs to be adapted to actually use the new mgmt advertising API. However that should be pretty trivial and straight forward. Patches are always welcome.
Regards
Marcel
Hi Marcel,
> See comment above, we can not really change legacy API.
Sure. I hoped that my proposal was just a change in implementation, not
in behavior. But it doesn't seem to be an obvious improvement.
> It has to stay around for backwards compatibility. And that is why set advertising takes precedence over anything added by add advertising.
Yes, I understood that from the documentation of the mgmt api.
> What are you planning to verify here. The instance id is coming from userspace.
Oups. Seems so obvious but I overlooked it.
> Read up on what instance[0] actually does in a struct. We have used these constructs before. I am sensing that you misunderstood what this is for.
I think I understood what it does (struct hack?). I just didn't
understand the intent of that field as it wasn't (yet) used anywhere in
code. But I found it out in the meantime: You intend it to hold the
currently occupied instance identifiers. I'll make sure it will be
filled accordingly.
Thanks for your quick response!
Florian