-
Notifications
You must be signed in to change notification settings - Fork 6.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Bluetooth: host: Add extended advertising API #22013
Conversation
All checks are passing now. Tip: The bot edits this comment instead of posting a new one, so you can check the comment's history to see earlier messages. |
Added this as draft PR to get input on the general directions. There are many small details that we can leave for later. |
CC: @aescolar Any input from your camp? Even though periodic advertising is not included yet, we could get some perspective on how it could possibly be extended? |
include/bluetooth/bluetooth.h
Outdated
* controller, for other controllers code returned in | ||
* this case may be -EIO. | ||
*/ | ||
struct bt_adv *bt_le_adv_set_create(const struct bt_le_adv_param *param); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So the idea here is that we would do memory allocation? I rather not do this since we may have different parts trying to advertise so application would only notice the lack of memory at runtime, so I rather leave the memory allocation to the application directly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Vudentz It would allocate one of a fixed number of advertising contexts in the host. This one is quite small and mostly just has the advertising_handle and some state variables. This API would create a new advertising context in the controller. And it is not possible to give allocated memory to the controller over the HCI interface.
This is also similar to how conn objects are allocated. This would be symmetrical to bt_conn_create_le (which wraps the connection handle plus internal state).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So we are assuming we know the number of sets available in the controller? How about split builds? Either way we cannot mix legacy advertisement with extended ones over HCI as that would fail so having an API which masks this sort of detail is probably desirable, we could make the sets work even without the controller supporting it by doing the advertising set context on the host, anyway the spec don't seem to describe how the scheduling should happen so just rotating the sets should work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So we are assuming we know the number of sets available in the controller?
How about split builds?
That's a good question actually. The number of advertising sets in the controller can be read using
LE Read Number of Supported Advertising Sets command. However it has this note:
Note: The number of advertising sets that can be supported is not fixed and the
Controller can change it at any time because the memory used to store
advertising sets can also be used for other purposes.
I think we can assume in combined build that we would have a specific number of advertising sets set by Kconfig.
In the split build case, I think we should just make sure that we atleast have enough advertising set contexts in the host.
The context itself is not very large so i don't see this is a problem.
In any case the larger memory usage is in the HCI both for advertising context and advertising data.
In split build we cannot assign memory to the controller, maybe in the combined case, but that would still have to be something that is outside of HCI.
Either way we cannot mix legacy advertisement with extended ones over HCI as that would fail so having an API which masks this sort of detail is probably desirable,
We cannot mix legacy and extended, but we can support the old advertising API with the new API, limited to one set.
And the old advertising API can use the new advertising HCI commands, with the added advantage of solving the multiple identities problem, solving a structural issue with the current API.
we could make the sets work even without the controller supporting it by doing the advertising set context on the host, anyway the spec don't seem to describe how the scheduling should happen so just rotating the sets should work.
In this case we would have to rotate advertising parameters and advertising data, so then we would either have to copy them in the host, or require the application
to provide us pointers to memory that stays valid while for the lifetime of the advertising set.
In this case I think it would maybe be easier to keep with the old recommendation of cycling the advertising data of a single advertiser instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
, I think we should just make sure that we atleast have enough advertising set contexts in the host.
This is similar to what happens today with buffer counts and sizes.
include/bluetooth/bluetooth.h
Outdated
* | ||
* @return Zero on success or (negative) error code otherwise. | ||
*/ | ||
int bt_le_adv_set_data(const struct bt_adv *adv, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this suppose to copy ad and sd data over to bt_adv or just reference them? I guess we want the later which means the application will have to manage part of the adv data anyway so it would more sense to let it deal with all.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would copy the data directly to the controller. The host does not keep a copy. This function is bt_le_adv_data_update
with the adv set context as an additional argument.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, I assumed we were tracking the actual data set to not have duplicated calls but it seems we don't do that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would clear the old data, and set new data. We don't append the data to the existing. (Or did I misunderstand what you meant by duplicate calls?)
include/bluetooth/bluetooth.h
Outdated
* @param adv The advertising set object. | ||
* @param num_sent The new connection object. | ||
*/ | ||
void (*connected)(struct bt_adv *adv, struct bt_conn *conn); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
on HCI level what is here sent and connected callback is single event, why split this? eg num_sent is also valid when set was terminated by connection
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought it was a reasonable simplification. Since they are two different things.
If the application is interested in both, then both callbacks will be called.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aren't there cases where sent()
is called by not connected()
? like non-conn adv?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the application set num_sent, then sent callback will be called when adv set is terminated.
If the adv set is terminated because it was connected, then connected will be called.
So both could happen, or just one.
include/bluetooth/bluetooth.h
Outdated
* @return Zero on success or (negative) error code otherwise. | ||
*/ | ||
int bt_le_adv_set_data(const struct bt_adv *adv, | ||
const struct bt_data *ad, size_t ad_len, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm I don't think flat buffers are suitable for EA, data can be up to 1650 bytes...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Which data-structure would be better? net_buf
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not quite a flat buffer in this case though since ad
is an array (one element for each data type to be included to the advertising data (the ad_len
parameter is the array length). That said, net_buf might indeed be a more lucrative choice here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right. I keep forgetting how that works. :)
Then I don't necessarily see the downside in continuing to use the same parameters as before.
What might be more important is making is the scan callback recv
I think right now it has a net_buf_simple
. And possibly bt_data_parse
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sjanc the advantage of mbuf
-style chaining of multiple buffers are mostly evident when you have a global allocator that all clients consume memory from. This is not the case in this Host, and in general in Zephyr the Host assumes flat buffers. That said, I do support the idea of using net_buf
so that we do not have to change the signature later if we start supporting fragment chains.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice job! I've added some comments to the API, I have not reviewed the implementation.
include/bluetooth/bluetooth.h
Outdated
* @param adv The advertising set object. | ||
* @param num_sent The new connection object. | ||
*/ | ||
void (*connected)(struct bt_adv *adv, struct bt_conn *conn); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aren't there cases where sent()
is called by not connected()
? like non-conn adv?
include/bluetooth/bluetooth.h
Outdated
* controller, for other controllers code returned in | ||
* this case may be -EIO. | ||
*/ | ||
struct bt_adv *bt_le_adv_set_create(const struct bt_le_adv_param *param); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
, I think we should just make sure that we atleast have enough advertising set contexts in the host.
This is similar to what happens today with buffer counts and sizes.
subsys/bluetooth/Kconfig
Outdated
This option should be used where the capabalities of the controller | ||
is not known. | ||
|
||
config BT_ADV_EXT_LEGACY_ONLY |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this needed? Won't all controllers that support AE support the legacy commands too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was intended as an option for when using the new advertising set API was not needed, but using the new extended
HCI commands was needed. It doesn't seem like there is much to gain from this option in terms of code reduction though. So I think I will just remove this option.
I think what we might need instead however is to assume the controller supports the feature, and skip checking the feature flag. For combined builds this would make sense, and we could compile out all the legacy HCI commands.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think what we might need instead however is to assume the controller supports the feature, and skip checking the feature flag. For combined builds this would make sense, and we could compile out all the legacy HCI commands.
Agreed, for combined builds in the future (when we support AE in the controller) then BT_ADV_EXT_LEGACY_SUPPORT
should default to n
(once it's implemented).
Add support to use the extended conn create options to establish connections on LE Coded PHY or 2M. This uses the connection options set by bt_conn_set_scan_params. Signed-off-by: Joakim Andersson <joakim.andersson@nordicsemi.no>
Add support for creating and advertising with an advertising set. This has support to advertise with extended data and with long range feature on Coded PHY. Limited to only supported one advertising set. Signed-off-by: Joakim Andersson <joakim.andersson@nordicsemi.no>
Print the error codes in hex so that it is easier to lookup, error codes are usually given as hex. Signed-off-by: Joakim Andersson <joakim.andersson@nordicsemi.no>
Add scan recv callback and print extended scan information available. Add scan timeout callback to print when scanner has stopped. Signed-off-by: Joakim Andersson <joakim.andersson@nordicsemi.no>
Add shell arguments to control scanning phys for scanner and initiator. This allows to scan on coded or create connections on coded. Signed-off-by: Joakim Andersson <joakim.andersson@nordicsemi.no>
Add shell commands to create advertising sets, add advertising data, start advertising, stop advertising, and delete advertising set. Signed-off-by: Joakim Andersson <joakim.andersson@nordicsemi.no>
Add advertising sent connected and scanned callback and print the information available. Signed-off-by: Joakim Andersson <joakim.andersson@nordicsemi.no>
Add error code to API for starting directed advertiser. Also rename the API in order to follow the established naming pattern. Signed-off-by: Joakim Andersson <joakim.andersson@nordicsemi.no>
Add shell command to retrieve advertising set OOB information for the selected advertising set. Signed-off-by: Joakim Andersson <joakim.andersson@nordicsemi.no>
Add handling of anonymous advertise address type. Signed-off-by: Joakim Andersson <joakim.andersson@nordicsemi.no>
Add RPA handling for scan limited by timeout. The scan limited by timeout has no information about elapsed time when stopped. So pausing the scan at RPA timeout has no new scan timeout value to set. Signed-off-by: Joakim Andersson <joakim.andersson@nordicsemi.no>
Move HCI remove device from resolving list command out to it's own function. Signed-off-by: Joakim Andersson <joakim.andersson@nordicsemi.no>
Add shell option to set scan timeout parameter. Signed-off-by: Joakim Andersson <joakim.andersson@nordicsemi.no>
Handle updating the identity keys in the controller while a scanner limited by timeout or advertiser limited by number of events or timeout is active in the controller. For this case we mark they keys as pending and handle the update of the resolving list ones the roles are stopped. Signed-off-by: Joakim Andersson <joakim.andersson@nordicsemi.no>
Skip feature testing of controller features when legacy advertising commands are not supported. For combined builds or builds where the capability of the controller is known it is not required to have runtime check of controller extended advertising support. This gives the following size reduction for hci_core.c: Without legacy support hci_core.c 19980 7.75% total 257679 With legacy support hci_core.c 21816 8.41% total 259519 Signed-off-by: Joakim Andersson <joakim.andersson@nordicsemi.no>
Implement function to get advertising set information. Signed-off-by: Joakim Andersson <joakim.andersson@nordicsemi.no>
Add shell advertise set info get command to print advertiser set local identity and TX power selected by the controller. Signed-off-by: Joakim Andersson <joakim.andersson@nordicsemi.no>
Add a section in the 2.3 release notes for the API changes, and document the ones introduced by the Advertising Extensions support in the BLE Host. Signed-off-by: Carles Cufi <carles.cufi@nordicsemi.no>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM now, thanks!
After zephyrproject-rtos#22013, bt_le_adv_param got additional fields which were passed to the bluetooth API uninitialized in the BT Mesh module. This zero-initializes the entire structure in all usages to avoid passing uninitialized data now and in the future. Signed-off-by: Trond Einar Snekvik <Trond.Einar.Snekvik@nordicsemi.no>
After #22013, bt_le_adv_param got additional fields which were passed to the bluetooth API uninitialized in the BT Mesh module. This zero-initializes the entire structure in all usages to avoid passing uninitialized data now and in the future. Signed-off-by: Trond Einar Snekvik <Trond.Einar.Snekvik@nordicsemi.no>
This merge broken compilation c++ project. If include
We get error
Related #5695 |
After zephyrproject-rtos#22013, bt_le_adv_param got additional fields which were passed to the bluetooth API uninitialized in the BT Mesh module. This zero-initializes the entire structure in all usages to avoid passing uninitialized data now and in the future. Signed-off-by: Trond Einar Snekvik <Trond.Einar.Snekvik@nordicsemi.no>
Add extended advertising API. The use-cases that are included in this
are Extended Advertising Data, connecting using Long Range feature, and
multiple advertisers.
The new advertising API and the options for scanning and creating connections should be backwards compatible. The advertising set API is modeled to be similar to the connection API.
I intend to keep the old advertising API in addition to the new advertising set API when Extended Advertising Feature is enabled. The use-case for this is to continue with the old Advertising API while using the new Extended Advertising HCI commands. This has the advantage of enabling advertising with a different Identity while scanner/initiator uses the default Identity. In this case the stack will keep an advertising set internally and manage this without giving away the advertising set reference.
Periodic advertising has not been considered yet. But I think this feature can be made as an addition on top of the advertising set API. I'm not sure if we should include periodic advertising in this PR, but if we don't then we should atleast make sure that it can be added without requiring changes to the advertising set API.
Following changes to the existing API:
Note about privacy and OOB data.
There is only a single RPA timer, this has the implication that if one RPA address needs to be cycled by the host, then all RPA addresses are cycled and RPA timeout reset. Addresses are cycled by the host in the following cases:
bt_conn_le_create
close to the RPA timeout (3 seconds is default).To handle the case where duration and num_events are used as advertising parameters > 0, this type of advertiser is defined as a "limited" advertiser, meaning it will be stopped by controller once a limit has been reached.
A limited advertiser is not bound by the RPA timeout, instead it generates a new RPA address each time it is started, and cannot be active for longer than the RPA timeout value. In a sense it has its own RPA timer.
To get the OOB data for central role, or an advertiser started using
bt_le_adv_start
thenbt_le_oob_get_local
should be used.To get the OOB data for advertisers started using
bt_le_ext_adv_create
thenbt_le_ext_adv_oob_get_local
should be used.Currently I have decided to leave out the following features:
The use of period.
Channel MAP (also not present in old API).
Features that will be improved later:
Limited functionality to only one advertising set.
Extendend advertising data fragmentation and re-assembly.
Fixes: #18047
Fixes: #18046
Fixes: #18050
Fixes: #23247