bluetooth: host: Allow concurrent advertising with multiple ids
The HCI specification creates additional complexity to allow this configuration: - When a connection gets established, we need to know which identity the HCI_LE_Connection_Complete event corresponds to. - The identity is a property of the advertising set. Therefore we need the advertising handle. - The advertising handle is part of the HCI_LE_Advertising_Set_Terminated event and is not part of the HCI_LE_Connection_Complete event. Therefore the information of both events needs to be combined. By spec the LE_Connection_Complete comes first. Therefore we cache this event until the identity is available. The event is only cached when a connection gets established as that is the only case where we need to resolve the identity. As the caching requires more resources, it is only enabled if the application requires multiple advertising sets and multiple identities. The host maps the HCI_LE_Advertising_Set_Terminated event with the HCI_LE_Connection_Complete event by comparing the connection handles. Signed-off-by: Rubin Gerritsen <rubin.gerritsen@nordicsemi.no>
This commit is contained in:
parent
6b15ad1fd5
commit
98321c61fb
4 changed files with 70 additions and 3 deletions
|
@ -540,9 +540,6 @@ struct bt_le_adv_param {
|
||||||
* enabled or not supported by the controller it is not possible
|
* enabled or not supported by the controller it is not possible
|
||||||
* to scan and advertise simultaneously using two different
|
* to scan and advertise simultaneously using two different
|
||||||
* random addresses.
|
* random addresses.
|
||||||
*
|
|
||||||
* @note It is not possible to have multiple connectable advertising
|
|
||||||
* sets advertising simultaneously using different identities.
|
|
||||||
*/
|
*/
|
||||||
uint8_t id;
|
uint8_t id;
|
||||||
|
|
||||||
|
|
|
@ -1553,6 +1553,26 @@ void bt_hci_le_adv_set_terminated(struct net_buf *buf)
|
||||||
adv = bt_adv_lookup_handle(evt->adv_handle);
|
adv = bt_adv_lookup_handle(evt->adv_handle);
|
||||||
conn_handle = sys_le16_to_cpu(evt->conn_handle);
|
conn_handle = sys_le16_to_cpu(evt->conn_handle);
|
||||||
|
|
||||||
|
#if (CONFIG_BT_ID_MAX > 1) && (CONFIG_BT_EXT_ADV_MAX_ADV_SET > 1)
|
||||||
|
bt_dev.adv_conn_id = adv->id;
|
||||||
|
for (int i = 0; i < ARRAY_SIZE(bt_dev.cached_conn_complete); i++) {
|
||||||
|
if (bt_dev.cached_conn_complete[i].valid &&
|
||||||
|
bt_dev.cached_conn_complete[i].evt.handle == evt->conn_handle) {
|
||||||
|
if (atomic_test_bit(adv->flags, BT_ADV_ENABLED)) {
|
||||||
|
/* Process the cached connection complete event
|
||||||
|
* now that the corresponding advertising set is known.
|
||||||
|
*
|
||||||
|
* If the advertiser has been stopped before the connection
|
||||||
|
* complete event has been raised to the application, we
|
||||||
|
* discard the event.
|
||||||
|
*/
|
||||||
|
bt_hci_le_enh_conn_complete(&bt_dev.cached_conn_complete[i].evt);
|
||||||
|
}
|
||||||
|
bt_dev.cached_conn_complete[i].valid = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
BT_DBG("status 0x%02x adv_handle %u conn_handle 0x%02x num %u",
|
BT_DBG("status 0x%02x adv_handle %u conn_handle 0x%02x num %u",
|
||||||
evt->status, evt->adv_handle, conn_handle,
|
evt->status, evt->adv_handle, conn_handle,
|
||||||
evt->num_completed_ext_adv_evts);
|
evt->num_completed_ext_adv_evts);
|
||||||
|
|
|
@ -1043,6 +1043,37 @@ static void le_conn_complete_adv_timeout(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void enh_conn_complete(struct bt_hci_evt_le_enh_conn_complete *evt)
|
static void enh_conn_complete(struct bt_hci_evt_le_enh_conn_complete *evt)
|
||||||
|
{
|
||||||
|
#if (CONFIG_BT_ID_MAX > 1) && (CONFIG_BT_EXT_ADV_MAX_ADV_SET > 1)
|
||||||
|
if (IS_ENABLED(CONFIG_BT_PERIPHERAL) &&
|
||||||
|
evt->role == BT_HCI_ROLE_SLAVE &&
|
||||||
|
evt->status == BT_HCI_ERR_SUCCESS &&
|
||||||
|
(IS_ENABLED(CONFIG_BT_EXT_ADV) &&
|
||||||
|
BT_FEAT_LE_EXT_ADV(bt_dev.le.features))) {
|
||||||
|
|
||||||
|
/* Cache the connection complete event. Process it later.
|
||||||
|
* See bt_dev.cached_conn_complete.
|
||||||
|
*/
|
||||||
|
for (int i = 0; i < ARRAY_SIZE(bt_dev.cached_conn_complete); i++) {
|
||||||
|
if (!bt_dev.cached_conn_complete[i].valid) {
|
||||||
|
(void)memcpy(&bt_dev.cached_conn_complete[i].evt,
|
||||||
|
evt,
|
||||||
|
sizeof(struct bt_hci_evt_le_enh_conn_complete));
|
||||||
|
bt_dev.cached_conn_complete[i].valid = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__ASSERT(false, "No more cache entries available."
|
||||||
|
"This should not happen by design");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
bt_hci_le_enh_conn_complete(evt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bt_hci_le_enh_conn_complete(struct bt_hci_evt_le_enh_conn_complete *evt)
|
||||||
{
|
{
|
||||||
uint16_t handle = sys_le16_to_cpu(evt->handle);
|
uint16_t handle = sys_le16_to_cpu(evt->handle);
|
||||||
bt_addr_le_t peer_addr, id_addr;
|
bt_addr_le_t peer_addr, id_addr;
|
||||||
|
|
|
@ -252,6 +252,22 @@ struct bt_dev {
|
||||||
#else
|
#else
|
||||||
/* Pointer to reserved advertising set */
|
/* Pointer to reserved advertising set */
|
||||||
struct bt_le_ext_adv *adv;
|
struct bt_le_ext_adv *adv;
|
||||||
|
#if (CONFIG_BT_ID_MAX > 1) && (CONFIG_BT_EXT_ADV_MAX_ADV_SET > 1)
|
||||||
|
/* When supporting multiple concurrent connectable advertising sets
|
||||||
|
* with multiple identities, we need to know the identity of
|
||||||
|
* the terminating advertising set to identify the connection object.
|
||||||
|
* The identity of the advertising set is determined by its
|
||||||
|
* advertising handle, which is part of the
|
||||||
|
* LE Set Advertising Set Terminated event which is always sent
|
||||||
|
* _after_ the LE Enhanced Connection complete event.
|
||||||
|
* Therefore we need cache this event until its identity is known.
|
||||||
|
*/
|
||||||
|
struct {
|
||||||
|
bool valid;
|
||||||
|
struct bt_hci_evt_le_enh_conn_complete evt;
|
||||||
|
} cached_conn_complete[MIN(CONFIG_BT_MAX_CONN,
|
||||||
|
CONFIG_BT_EXT_ADV_MAX_ADV_SET)];
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
/* Current local Random Address */
|
/* Current local Random Address */
|
||||||
bt_addr_le_t random_addr;
|
bt_addr_le_t random_addr;
|
||||||
|
@ -394,6 +410,9 @@ void bt_hci_auth_complete(struct net_buf *buf);
|
||||||
void bt_hci_evt_le_pkey_complete(struct net_buf *buf);
|
void bt_hci_evt_le_pkey_complete(struct net_buf *buf);
|
||||||
void bt_hci_evt_le_dhkey_complete(struct net_buf *buf);
|
void bt_hci_evt_le_dhkey_complete(struct net_buf *buf);
|
||||||
|
|
||||||
|
/* Common HCI event handlers */
|
||||||
|
void bt_hci_le_enh_conn_complete(struct bt_hci_evt_le_enh_conn_complete *evt);
|
||||||
|
|
||||||
/* Scan HCI event handlers */
|
/* Scan HCI event handlers */
|
||||||
void bt_hci_le_adv_report(struct net_buf *buf);
|
void bt_hci_le_adv_report(struct net_buf *buf);
|
||||||
void bt_hci_le_scan_timeout(struct net_buf *buf);
|
void bt_hci_le_scan_timeout(struct net_buf *buf);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue