diff --git a/include/bluetooth/bluetooth.h b/include/bluetooth/bluetooth.h index 2fe96fe1dc8..a460d98e2a5 100644 --- a/include/bluetooth/bluetooth.h +++ b/include/bluetooth/bluetooth.h @@ -540,9 +540,6 @@ struct bt_le_adv_param { * enabled or not supported by the controller it is not possible * to scan and advertise simultaneously using two different * random addresses. - * - * @note It is not possible to have multiple connectable advertising - * sets advertising simultaneously using different identities. */ uint8_t id; diff --git a/subsys/bluetooth/host/adv.c b/subsys/bluetooth/host/adv.c index d64e12c9b62..7d242149f32 100644 --- a/subsys/bluetooth/host/adv.c +++ b/subsys/bluetooth/host/adv.c @@ -1553,6 +1553,26 @@ void bt_hci_le_adv_set_terminated(struct net_buf *buf) adv = bt_adv_lookup_handle(evt->adv_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", evt->status, evt->adv_handle, conn_handle, evt->num_completed_ext_adv_evts); diff --git a/subsys/bluetooth/host/hci_core.c b/subsys/bluetooth/host/hci_core.c index 538e5ea58e6..4590a207157 100644 --- a/subsys/bluetooth/host/hci_core.c +++ b/subsys/bluetooth/host/hci_core.c @@ -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) +{ +#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); bt_addr_le_t peer_addr, id_addr; diff --git a/subsys/bluetooth/host/hci_core.h b/subsys/bluetooth/host/hci_core.h index b2b0be809ef..b14a737c499 100644 --- a/subsys/bluetooth/host/hci_core.h +++ b/subsys/bluetooth/host/hci_core.h @@ -252,6 +252,22 @@ struct bt_dev { #else /* Pointer to reserved advertising set */ 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 /* Current local Random Address */ 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_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 */ void bt_hci_le_adv_report(struct net_buf *buf); void bt_hci_le_scan_timeout(struct net_buf *buf);