From d4f22a82160cd88ea066cbea4e25273d6239bd40 Mon Sep 17 00:00:00 2001 From: Joakim Andersson Date: Sat, 18 Apr 2020 18:30:12 +0200 Subject: [PATCH] Bluetooth: host: Add support for multiple advertising set Add support for multiple advertising set. Move the advertising state flags to be per advertising set and loop over advertising sets instead of looking up legacy advertiser set or handle 0. Since it is not certain that the advertising set terminated event can arrive directly after the connection complete event there is currently a limitation that there can only be one local identity used by connectable advertisers at a time. This guarantees that we know the local identity being used in the connection complete event. Signed-off-by: Joakim Andersson --- include/bluetooth/bluetooth.h | 13 +- include/bluetooth/conn.h | 4 +- subsys/bluetooth/Kconfig | 2 +- subsys/bluetooth/host/conn.c | 6 +- subsys/bluetooth/host/hci_core.c | 666 +++++++++++++++++-------------- subsys/bluetooth/host/hci_core.h | 24 +- subsys/bluetooth/shell/bt.c | 5 +- 7 files changed, 403 insertions(+), 317 deletions(-) diff --git a/include/bluetooth/bluetooth.h b/include/bluetooth/bluetooth.h index 10e93676ad4..b65ae68ae52 100644 --- a/include/bluetooth/bluetooth.h +++ b/include/bluetooth/bluetooth.h @@ -434,7 +434,16 @@ enum { /** LE Advertising Parameters. */ struct bt_le_adv_param { - /** Local identity */ + /** Local identity. + * + * @note When extended advertising :option:`CONFIG_BT_EXT_ADV` is not + * 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. + */ u8_t id; /** Advertising Set Identifier, valid range 0x00 - 0x0f. @@ -1038,7 +1047,7 @@ struct bt_le_oob { * cases: * - Creating a connection in progress, wait for the connected callback. * In addition when extended advertising :option:`CONFIG_BT_EXT_ADV` is - * not enabled or supported by the controller: + * not enabled or not supported by the controller: * - Advertiser is enabled using a Random Static Identity Address for a * different local identity. * - The local identity conflicts with the local identity used by other diff --git a/include/bluetooth/conn.h b/include/bluetooth/conn.h index d599f4aca7a..c3c166c83ce 100644 --- a/include/bluetooth/conn.h +++ b/include/bluetooth/conn.h @@ -622,8 +622,8 @@ struct bt_conn_cb { * @ref bt_conn_le_create_param timeout parameter, which defaults to * :option:`CONFIG_BT_CREATE_CONN_TIMEOUT` seconds. * - @p BT_HCI_ERR_ADV_TIMEOUT High duty cycle directed connectable - * advertiser started by @ref bt_le_adv_start or bt_le_ext_adv_start - * failed to be connected within the timeout. + * advertiser started by @ref bt_le_adv_start failed to be connected + * within the timeout. */ void (*connected)(struct bt_conn *conn, u8_t err); diff --git a/subsys/bluetooth/Kconfig b/subsys/bluetooth/Kconfig index ca283de9d16..7057372e9eb 100644 --- a/subsys/bluetooth/Kconfig +++ b/subsys/bluetooth/Kconfig @@ -126,7 +126,7 @@ config BT_EXT_ADV_LEGACY_SUPPORT config BT_EXT_ADV_MAX_ADV_SET int "Maximum number of simultaneous advertising sets" - range 1 1 + range 1 64 default 1 help Maximum number of simultaneous Bluetooth advertising sets diff --git a/subsys/bluetooth/host/conn.c b/subsys/bluetooth/host/conn.c index 405c3715f53..d34ab1c68df 100644 --- a/subsys/bluetooth/host/conn.c +++ b/subsys/bluetooth/host/conn.c @@ -340,9 +340,7 @@ static void conn_update_timeout(struct k_work *work) /* A new reference likely to have been released here, * Resume advertising. */ - if (IS_ENABLED(CONFIG_BT_PERIPHERAL) && - atomic_test_bit(bt_dev.flags, BT_DEV_KEEP_ADVERTISING) && - !atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING)) { + if (IS_ENABLED(CONFIG_BT_PERIPHERAL)) { bt_le_adv_resume(); } @@ -1639,7 +1637,7 @@ void bt_conn_set_state(struct bt_conn *conn, bt_conn_state_t state) BT_DBG("%s -> %s", state2str(conn->state), state2str(state)); if (conn->state == state) { - BT_WARN("no transition"); + BT_WARN("no transition %s", state2str(state)); return; } diff --git a/subsys/bluetooth/host/hci_core.c b/subsys/bluetooth/host/hci_core.c index de4f42be640..35bb25e858d 100644 --- a/subsys/bluetooth/host/hci_core.c +++ b/subsys/bluetooth/host/hci_core.c @@ -456,8 +456,23 @@ static struct bt_le_ext_adv *bt_adv_lookup_handle(u8_t handle) return NULL; } + #endif /* defined(CONFIG_BT_EXT_ADV) */ +static void bt_adv_foreach(void (*func)(struct bt_le_ext_adv *adv, void *data), + void *data) +{ +#if defined(CONFIG_BT_EXT_ADV) + for (size_t i = 0; i < ARRAY_SIZE(adv_pool); i++) { + if (atomic_test_bit(adv_pool[i].flags, BT_ADV_CREATED)) { + func(&adv_pool[i], data); + } + } +#else + func(&bt_dev.adv, data); +#endif /* defined(CONFIG_BT_EXT_ADV) */ +} + static struct bt_le_ext_adv *adv_new_legacy(void) { #if defined(CONFIG_BT_EXT_ADV) @@ -491,7 +506,7 @@ struct bt_le_ext_adv *bt_adv_lookup_legacy(void) #endif } -static int set_le_adv_enable_legacy(bool enable) +static int set_le_adv_enable_legacy(struct bt_le_ext_adv *adv, bool enable) { struct net_buf *buf; struct cmd_state_set state; @@ -508,7 +523,7 @@ static int set_le_adv_enable_legacy(bool enable) net_buf_add_u8(buf, BT_HCI_LE_ADV_DISABLE); } - cmd_state_set_init(&state, bt_dev.flags, BT_DEV_ADVERTISING, enable); + cmd_state_set_init(&state, adv->flags, BT_ADV_ENABLED, enable); cmd(buf)->state = &state; err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_ADV_ENABLE, buf, NULL); @@ -548,7 +563,7 @@ static int set_random_address(const bt_addr_t *addr) return 0; } -static int set_le_adv_enable_ext(const struct bt_le_ext_adv *adv, +static int set_le_adv_enable_ext(struct bt_le_ext_adv *adv, bool enable, const struct bt_le_ext_adv_start_param *param) { @@ -573,8 +588,7 @@ static int set_le_adv_enable_ext(const struct bt_le_ext_adv *adv, net_buf_add_le16(buf, param ? sys_cpu_to_le16(param->timeout) : 0); net_buf_add_u8(buf, param ? param->num_events : 0); - /* Update advertising flag */ - cmd_state_set_init(&state, bt_dev.flags, BT_DEV_ADVERTISING, enable); + cmd_state_set_init(&state, adv->flags, BT_ADV_ENABLED, enable); cmd(buf)->state = &state; err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_EXT_ADV_ENABLE, buf, NULL); @@ -592,7 +606,7 @@ static int set_le_adv_enable(struct bt_le_ext_adv *adv, bool enable) return set_le_adv_enable_ext(adv, enable, NULL); } - return set_le_adv_enable_legacy(enable); + return set_le_adv_enable_legacy(adv, enable); } static int set_adv_random_address(struct bt_le_ext_adv *adv, @@ -691,6 +705,13 @@ int bt_addr_le_from_str(const char *str, const char *type, bt_addr_le_t *addr) return 0; } +static void adv_rpa_invalidate(struct bt_le_ext_adv *adv, void *data) +{ + if (!atomic_test_bit(adv->flags, BT_ADV_LIMITED)) { + atomic_clear_bit(adv->flags, BT_ADV_RPA_VALID); + } +} + static void le_rpa_invalidate(void) { /* RPA must be submitted */ @@ -702,15 +723,7 @@ static void le_rpa_invalidate(void) atomic_clear_bit(bt_dev.flags, BT_DEV_RPA_VALID); } -#if defined(CONFIG_BT_EXT_ADV) - struct bt_le_ext_adv *adv; - - /* TODO: handle multiple advertising set */ - adv = bt_adv_lookup_handle(0); - if (adv && !atomic_test_bit(adv->flags, BT_ADV_LIMITED)) { - atomic_clear_bit(adv->flags, BT_ADV_RPA_VALID); - } -#endif /* defined(CONFIG_BT_EXT_ADV) */ + bt_adv_foreach(adv_rpa_invalidate, NULL); } #if defined(CONFIG_BT_PRIVACY) @@ -830,10 +843,37 @@ static int le_adv_set_private_addr(struct bt_le_ext_adv *adv) } #endif /* defined(CONFIG_BT_PRIVACY) */ +static void adv_update_rpa(struct bt_le_ext_adv *adv, void *data) +{ + if (atomic_test_bit(adv->flags, BT_ADV_ENABLED) && + !atomic_test_bit(adv->flags, BT_ADV_LIMITED) && + !atomic_test_bit(adv->flags, BT_ADV_USE_IDENTITY)) { + int err; + + set_le_adv_enable_ext(adv, false, NULL); + + err = le_adv_set_private_addr(adv); + if (err) { + BT_WARN("Failed to update advertiser RPA address (%d)", + err); + } + + set_le_adv_enable_ext(adv, true, NULL); + } +} + static void le_update_private_addr(void) { + struct bt_le_ext_adv *adv; + bool adv_enabled = false; + u8_t id = BT_ID_DEFAULT; int err; + if (IS_ENABLED(CONFIG_BT_EXT_ADV) && + BT_FEAT_LE_EXT_ADV(bt_dev.le.features)) { + bt_adv_foreach(adv_update_rpa, NULL); + } + #if defined(CONFIG_BT_OBSERVER) bool scan_enabled = false; @@ -854,67 +894,32 @@ static void le_update_private_addr(void) bt_le_create_conn_cancel(); } -#if defined(CONFIG_BT_EXT_ADV) - struct bt_le_ext_adv *adv; + if (!(IS_ENABLED(CONFIG_BT_EXT_ADV) && + BT_FEAT_LE_EXT_ADV(bt_dev.le.features))) { + adv = bt_adv_lookup_legacy(); - if (IS_ENABLED(CONFIG_BT_OBSERVER) && - !atomic_test_bit(bt_dev.flags, BT_DEV_SCAN_LIMITED)) { - err = le_set_private_addr(BT_ID_DEFAULT); - if (err) { - BT_WARN("Failed to update RPA address (%d)", err); - return; - } - } - - /* TODO: Foreach adv set */ - adv = bt_adv_lookup_handle(0); - - if (adv && !atomic_test_bit(adv->flags, BT_ADV_LIMITED) && - !atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING_IDENTITY)) { - bool adv_enabled = false; - - if (atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING)) { - set_le_adv_enable_ext(adv, false, NULL); + if (adv && + atomic_test_bit(adv->flags, BT_ADV_ENABLED) && + !atomic_test_bit(adv->flags, BT_ADV_USE_IDENTITY)) { adv_enabled = true; - } - - err = le_adv_set_private_addr(adv); - if (err) { - BT_WARN("Failed to update advertiser RPA address (%d)", - err); - } - - if (adv_enabled) { - set_le_adv_enable_ext(adv, true, NULL); + id = adv->id; + set_le_adv_enable_legacy(adv, false); } } -#else /* defined(CONFIG_BT_EXT_ADV) */ - bool adv_enabled = false; - /* - * we need to update rpa only if advertising is ongoing, with - * BT_DEV_KEEP_ADVERTISING flag is handled in disconnected event + /* If both advertiser and scanner is running then the advertiser + * ID must be BT_ID_DEFAULT, this will update the RPA address + * for both roles. */ - if (atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING) && - !atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING_IDENTITY)) { - set_le_adv_enable_legacy(false); - adv_enabled = true; - } - /* If both advertiser and scanner is running then the advertiser ID must - * be BT_ID_DEFAULT, this will update the RPA address for both roles. - */ - err = le_set_private_addr(adv_enabled ? bt_dev.adv.id : BT_ID_DEFAULT); + err = le_set_private_addr(id); if (err) { BT_WARN("Failed to update RPA address (%d)", err); return; } -#endif /* defined(CONFIG_BT_EXT_ADV) */ -#if !defined(CONFIG_BT_EXT_ADV) if (adv_enabled) { - set_le_adv_enable_legacy(true); + set_le_adv_enable_legacy(adv, true); } -#endif /* defined(CONFIG_BT_EXT_ADV) */ #if defined(CONFIG_BT_OBSERVER) if (scan_enabled) { @@ -923,9 +928,83 @@ static void le_update_private_addr(void) #endif } +struct adv_id_check_data { + u8_t id; + bool adv_enabled; +}; + +static void adv_id_check_func(struct bt_le_ext_adv *adv, void *data) +{ + struct adv_id_check_data *check_data = data; + + if (IS_ENABLED(CONFIG_BT_EXT_ADV)) { + /* Only check if the ID is in use, as the advertiser can be + * started and stopped without reconfiguring parameters. + */ + if (check_data->id == adv->id) { + check_data->adv_enabled = true; + } + } else { + if (check_data->id == adv->id && + atomic_test_bit(adv->flags, BT_ADV_ENABLED)) { + check_data->adv_enabled = true; + } + } +} + +static void adv_id_check_connectable_func(struct bt_le_ext_adv *adv, void *data) +{ + struct adv_id_check_data *check_data = data; + + if (atomic_test_bit(adv->flags, BT_ADV_ENABLED) && + atomic_test_bit(adv->flags, BT_ADV_CONNECTABLE) && + check_data->id != adv->id) { + check_data->adv_enabled = true; + } +} + +#if defined(CONFIG_BT_SMP) +static void adv_is_limited_enabled(struct bt_le_ext_adv *adv, void *data) +{ + bool *adv_enabled = data; + + if (atomic_test_bit(adv->flags, BT_ADV_ENABLED) && + atomic_test_bit(adv->flags, BT_ADV_LIMITED)) { + *adv_enabled = true; + } +} + +static void adv_pause_enabled(struct bt_le_ext_adv *adv, void *data) +{ + if (atomic_test_bit(adv->flags, BT_ADV_ENABLED)) { + atomic_set_bit(adv->flags, BT_ADV_PAUSED); + set_le_adv_enable(adv, false); + } +} + +static void adv_unpause_enabled(struct bt_le_ext_adv *adv, void *data) +{ + if (atomic_test_and_clear_bit(adv->flags, BT_ADV_PAUSED)) { + set_le_adv_enable(adv, true); + } +} +#endif /* defined(CONFIG_BT_SMP) */ + #if defined(CONFIG_BT_PRIVACY) +static void adv_is_private_enabled(struct bt_le_ext_adv *adv, void *data) +{ + bool *adv_enabled = data; + + if (atomic_test_bit(adv->flags, BT_ADV_ENABLED) && + !atomic_test_bit(adv->flags, BT_ADV_USE_IDENTITY)) { + *adv_enabled = true; + } +} + static void rpa_timeout(struct k_work *work) { + bool adv_enabled = false; + BT_DBG(""); if (IS_ENABLED(CONFIG_BT_CENTRAL)) { @@ -941,9 +1020,10 @@ static void rpa_timeout(struct k_work *work) le_rpa_invalidate(); + bt_adv_foreach(adv_is_private_enabled, &adv_enabled); + /* IF no roles using the RPA is running we can stop the RPA timer */ - if (!((atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING) && - !atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING_IDENTITY)) || + if (!(adv_enabled || atomic_test_bit(bt_dev.flags, BT_DEV_INITIATING) || (atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING) && atomic_test_bit(bt_dev.flags, BT_DEV_ACTIVE_SCAN)))) { @@ -956,15 +1036,22 @@ static void rpa_timeout(struct k_work *work) bool bt_le_scan_random_addr_check(void) { + struct bt_le_ext_adv *adv; + if (IS_ENABLED(CONFIG_BT_EXT_ADV) && BT_FEAT_LE_EXT_ADV(bt_dev.le.features)) { - /* Advertiser and scanner using differend random address */ + /* Advertiser and scanner using different random address */ + return true; + } + + adv = bt_adv_lookup_legacy(); + if (!adv) { return true; } /* If the advertiser is not enabled or not active there is no issue */ if (!IS_ENABLED(CONFIG_BT_BROADCASTER) || - !atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING)) { + !atomic_test_bit(adv->flags, BT_ADV_ENABLED)) { return true; } @@ -973,15 +1060,13 @@ bool bt_le_scan_random_addr_check(void) * valid and only updated on RPA timeout. */ if (IS_ENABLED(CONFIG_BT_PRIVACY)) { - struct bt_le_ext_adv *adv = bt_adv_lookup_legacy(); /* Cannot start scannor or initiator if the random address is * used by the advertiser for an RPA with a different identity * or for a random static identity address. */ - if ((atomic_test_bit(bt_dev.flags, - BT_DEV_ADVERTISING_IDENTITY) && + if ((atomic_test_bit(adv->flags, BT_ADV_USE_IDENTITY) && bt_dev.id_addr[adv->id].type == BT_ADDR_LE_RANDOM) || - adv->id != BT_ID_DEFAULT) { + adv->id != BT_ID_DEFAULT) { return false; } } @@ -998,7 +1083,7 @@ static bool bt_le_adv_random_addr_check(const struct bt_le_adv_param *param) { if (IS_ENABLED(CONFIG_BT_EXT_ADV) && BT_FEAT_LE_EXT_ADV(bt_dev.le.features)) { - /* Advertiser and scanner using differend random address */ + /* Advertiser and scanner using different random address */ return true; } @@ -1585,9 +1670,7 @@ static void hci_disconn_complete(struct net_buf *buf) bt_conn_unref(conn); advertise: - if (IS_ENABLED(CONFIG_BT_PERIPHERAL) && - atomic_test_bit(bt_dev.flags, BT_DEV_KEEP_ADVERTISING) && - !atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING)) { + if (IS_ENABLED(CONFIG_BT_PERIPHERAL)) { bt_le_adv_resume(); } } @@ -1771,16 +1854,10 @@ static struct bt_conn *find_pending_connect(u8_t role, bt_addr_le_t *peer_addr) } if (IS_ENABLED(CONFIG_BT_PERIPHERAL) && role == BT_HCI_ROLE_SLAVE) { -#if defined(CONFIG_BT_EXT_ADV) - /* TODO: handle multiple advertising set */ - struct bt_le_ext_adv *adv = bt_adv_lookup_handle(0); -#else - struct bt_le_ext_adv *adv = bt_adv_lookup_legacy(); -#endif - conn = bt_conn_lookup_state_le(adv->id, peer_addr, + conn = bt_conn_lookup_state_le(bt_dev.adv_conn_id, peer_addr, BT_CONN_CONNECT_DIR_ADV); if (!conn) { - conn = bt_conn_lookup_state_le(adv->id, + conn = bt_conn_lookup_state_le(bt_dev.adv_conn_id, BT_ADDR_LE_NONE, BT_CONN_CONNECT_ADV); } @@ -1883,6 +1960,35 @@ static void le_conn_complete_cancel(void) bt_conn_unref(conn); } +static void le_conn_complete_adv_timeout(void) +{ + if (!(IS_ENABLED(CONFIG_BT_EXT_ADV) && + BT_FEAT_LE_EXT_ADV(bt_dev.le.features))) { + struct bt_le_ext_adv *adv = bt_adv_lookup_legacy(); + struct bt_conn *conn; + + /* Handle advertising timeout after high duty cycle directed + * advertising. + */ + + atomic_clear_bit(adv->flags, BT_ADV_ENABLED); + + /* There is no need to check ID address as only one + * connection in slave role can be in pending state. + */ + conn = find_pending_connect(BT_HCI_ROLE_SLAVE, NULL); + if (!conn) { + BT_ERR("No pending slave connection"); + return; + } + + conn->err = BT_HCI_ERR_ADV_TIMEOUT; + bt_conn_set_state(conn, BT_CONN_DISCONNECTED); + + bt_conn_unref(conn); + } +} + static void enh_conn_complete(struct bt_hci_evt_le_enh_conn_complete *evt) { u16_t handle = sys_le16_to_cpu(evt->handle); @@ -1897,32 +2003,9 @@ static void enh_conn_complete(struct bt_hci_evt_le_enh_conn_complete *evt) #endif if (evt->status) { - /* - * Here we are only interested in pending connection. - */ - if (IS_ENABLED(CONFIG_BT_PERIPHERAL) && evt->status == BT_HCI_ERR_ADV_TIMEOUT) { - /* - * Handle advertising timeout after high duty cycle - * directed advertising. - */ - - atomic_clear_bit(bt_dev.flags, BT_DEV_ADVERTISING); - - /* - * There is no need to check ID address as only one - * connection in slave role can be in pending state. - */ - conn = find_pending_connect(BT_HCI_ROLE_SLAVE, NULL); - if (!conn) { - BT_ERR("No pending slave connection"); - return; - } - - conn->err = evt->status; - - bt_conn_set_state(conn, BT_CONN_DISCONNECTED); + le_conn_complete_adv_timeout(); return; } @@ -1947,16 +2030,8 @@ static void enh_conn_complete(struct bt_hci_evt_le_enh_conn_complete *evt) bt_addr_copy(&peer_addr.a, &evt->peer_rpa); peer_addr.type = BT_ADDR_LE_RANDOM; } else { -#if !defined(CONFIG_BT_EXT_ADV) - u8_t id = evt->role == BT_HCI_ROLE_SLAVE ? bt_dev.adv.id : + u8_t id = evt->role == BT_HCI_ROLE_SLAVE ? bt_dev.adv_conn_id : BT_ID_DEFAULT; -#else - /* TODO: handle multiple advertising set */ - struct bt_le_ext_adv *adv = bt_adv_lookup_handle(0); - - u8_t id = evt->role == BT_HCI_ROLE_SLAVE ? adv->id : - BT_ID_DEFAULT; -#endif bt_addr_le_copy(&id_addr, bt_lookup_id_addr(id, &evt->peer_addr)); @@ -1966,11 +2041,14 @@ static void enh_conn_complete(struct bt_hci_evt_le_enh_conn_complete *evt) conn = find_pending_connect(evt->role, &id_addr); if (IS_ENABLED(CONFIG_BT_PERIPHERAL) && - evt->role == BT_HCI_ROLE_SLAVE) { + evt->role == BT_HCI_ROLE_SLAVE && + !(IS_ENABLED(CONFIG_BT_EXT_ADV) && + BT_FEAT_LE_EXT_ADV(bt_dev.le.features))) { + struct bt_le_ext_adv *adv = bt_adv_lookup_legacy(); /* Clear advertising even if we are not able to add connection - * object to keep host in sync with controller state + * object to keep host in sync with controller state. */ - atomic_clear_bit(bt_dev.flags, BT_DEV_ADVERTISING); + atomic_clear_bit(adv->flags, BT_ADV_ENABLED); } if (IS_ENABLED(CONFIG_BT_CENTRAL) && @@ -2018,18 +2096,19 @@ static void enh_conn_complete(struct bt_hci_evt_le_enh_conn_complete *evt) * check for connectable advertising state is sufficient as * this is how this le connection complete for slave occurred. */ - if (atomic_test_bit(bt_dev.flags, BT_DEV_KEEP_ADVERTISING) && - BT_LE_STATES_SLAVE_CONN_ADV(bt_dev.le.states)) { + if (BT_LE_STATES_SLAVE_CONN_ADV(bt_dev.le.states)) { bt_le_adv_resume(); } if (IS_ENABLED(CONFIG_BT_EXT_ADV) && - !atomic_test_bit(bt_dev.flags, BT_DEV_KEEP_ADVERTISING) && !BT_FEAT_LE_EXT_ADV(bt_dev.le.features)) { + struct bt_le_ext_adv *adv = bt_adv_lookup_legacy(); /* No advertising set terminated event, must be a * legacy advertiser set. */ - adv_delete_legacy(); + if (!atomic_test_bit(adv->flags, BT_ADV_PERSIST)) { + adv_delete_legacy(); + } } } @@ -3643,9 +3722,7 @@ static int hci_id_add(u8_t id, const bt_addr_le_t *addr, u8_t peer_irk[16]) void bt_id_add(struct bt_keys *keys) { - struct bt_le_ext_adv *adv; struct bt_conn *conn; - bool adv_enabled; int err; BT_DBG("addr %s", bt_addr_le_str(&keys->addr)); @@ -3664,19 +3741,16 @@ void bt_id_add(struct bt_keys *keys) return; } - adv_enabled = atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING); + if (IS_ENABLED(CONFIG_BT_EXT_ADV)) { + bool adv_enabled = false; -#if defined(CONFIG_BT_EXT_ADV) - /* TODO: Foreach adv set */ - adv = bt_adv_lookup_handle(0); - if (adv && adv_enabled && - atomic_test_bit(adv->flags, BT_ADV_LIMITED)) { - pending_id_keys_update_set(keys, BT_KEYS_ID_PENDING_ADD); - return; + bt_adv_foreach(adv_is_limited_enabled, &adv_enabled); + if (adv_enabled) { + pending_id_keys_update_set(keys, + BT_KEYS_ID_PENDING_ADD); + return; + } } -#else - adv = bt_adv_lookup_legacy(); -#endif #if defined(CONFIG_BT_OBSERVER) bool scan_enabled = atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING); @@ -3686,9 +3760,8 @@ void bt_id_add(struct bt_keys *keys) pending_id_keys_update_set(keys, BT_KEYS_ID_PENDING_ADD); } #endif - if (adv_enabled) { - set_le_adv_enable(adv, false); - } + + bt_adv_foreach(adv_pause_enabled, NULL); #if defined(CONFIG_BT_OBSERVER) if (scan_enabled) { @@ -3756,9 +3829,7 @@ done: } #endif /* CONFIG_BT_OBSERVER */ - if (adv_enabled) { - set_le_adv_enable(adv, true); - } + bt_adv_foreach(adv_unpause_enabled, NULL); } static void keys_add_id(struct bt_keys *keys, void *data) @@ -3788,9 +3859,7 @@ static int hci_id_del(const bt_addr_le_t *addr) void bt_id_del(struct bt_keys *keys) { - struct bt_le_ext_adv *adv; struct bt_conn *conn; - bool adv_enabled; int err; BT_DBG("addr %s", bt_addr_le_str(&keys->addr)); @@ -3809,19 +3878,16 @@ void bt_id_del(struct bt_keys *keys) return; } - adv_enabled = atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING); + if (IS_ENABLED(CONFIG_BT_EXT_ADV)) { + bool adv_enabled = false; -#if defined(CONFIG_BT_EXT_ADV) - /* TODO: Foreach adv set */ - adv = bt_adv_lookup_handle(0); - if (adv && adv_enabled && - atomic_test_bit(adv->flags, BT_ADV_LIMITED)) { - pending_id_keys_update_set(keys, BT_KEYS_ID_PENDING_DEL); - return; + bt_adv_foreach(adv_is_limited_enabled, &adv_enabled); + if (adv_enabled) { + pending_id_keys_update_set(keys, + BT_KEYS_ID_PENDING_ADD); + return; + } } -#else - adv = bt_adv_lookup_legacy(); -#endif #if defined(CONFIG_BT_OBSERVER) bool scan_enabled = atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING); @@ -3832,9 +3898,7 @@ void bt_id_del(struct bt_keys *keys) } #endif /* CONFIG_BT_OBSERVER */ - if (adv_enabled) { - set_le_adv_enable(adv, false); - } + bt_adv_foreach(adv_pause_enabled, NULL); #if defined(CONFIG_BT_OBSERVER) if (scan_enabled) { @@ -3882,9 +3946,7 @@ done: } #endif /* CONFIG_BT_OBSERVER */ - if (adv_enabled) { - set_le_adv_enable(adv, true); - } + bt_adv_foreach(adv_unpause_enabled, NULL); } static void update_sec_level(struct bt_conn *conn) @@ -4280,13 +4342,18 @@ static int le_scan_set_random_addr(bool active_scan, u8_t *own_addr_type) *own_addr_type = BT_ADDR_LE_RANDOM; } } else { + struct bt_le_ext_adv *adv = bt_adv_lookup_legacy(); + *own_addr_type = bt_dev.id_addr[0].type; /* Use NRPA unless identity has been explicitly requested - * (through Kconfig), or if there is no advertising ongoing. + * (through Kconfig). + * Use same RPA as legacy advertiser if advertising. */ if (!IS_ENABLED(CONFIG_BT_SCAN_WITH_IDENTITY) && - !atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING)) { + !(IS_ENABLED(CONFIG_BT_EXT_ADV) && + BT_FEAT_LE_EXT_ADV(bt_dev.le.features)) && + adv && !atomic_test_bit(adv->flags, BT_ADV_ENABLED)) { err = le_set_private_addr(BT_ID_DEFAULT); if (err) { return err; @@ -4759,6 +4826,26 @@ static void le_adv_report(struct net_buf *buf) } #endif /* CONFIG_BT_OBSERVER */ +static void le_adv_stop_free_conn(const struct bt_le_ext_adv *adv, u8_t status) +{ + struct bt_conn *conn; + + if (!bt_addr_le_cmp(&adv->target_addr, BT_ADDR_LE_ANY)) { + conn = bt_conn_lookup_state_le(adv->id, BT_ADDR_LE_NONE, + BT_CONN_CONNECT_ADV); + } else { + conn = bt_conn_lookup_state_le(adv->id, &adv->target_addr, + BT_CONN_CONNECT_DIR_ADV); + } + + if (conn) { + conn->err = status; + bt_conn_set_state(conn, BT_CONN_DISCONNECTED); + bt_conn_unref(conn); + } +} + + #if defined(CONFIG_BT_EXT_ADV) #if defined(CONFIG_BT_BROADCASTER) static void le_adv_set_terminated(struct net_buf *buf) @@ -4773,33 +4860,36 @@ static void le_adv_set_terminated(struct net_buf *buf) evt->status, evt->adv_handle, evt->conn_handle, evt->num_completed_ext_adv_evts); - atomic_clear_bit(bt_dev.flags, BT_DEV_ADVERTISING); - - if (evt->status && - IS_ENABLED(CONFIG_BT_PERIPHERAL) && - atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING_NAME)) { - struct bt_conn *conn; - - conn = bt_conn_lookup_state_le(adv->id, BT_ADDR_LE_NONE, - BT_CONN_CONNECT_ADV); - if (conn) { - bt_conn_set_state(conn, BT_CONN_DISCONNECTED); - bt_conn_unref(conn); - } - - conn = bt_conn_lookup_state_le(adv->id, NULL, - BT_CONN_CONNECT_DIR_ADV); - if (conn) { - bt_conn_set_state(conn, BT_CONN_DISCONNECTED); - bt_conn_unref(conn); - } - } - if (!adv) { BT_ERR("No valid adv"); return; } + atomic_clear_bit(adv->flags, BT_ADV_ENABLED); + + if (evt->status && IS_ENABLED(CONFIG_BT_PERIPHERAL) && + atomic_test_bit(adv->flags, BT_ADV_CONNECTABLE)) { + /* Only set status for legacy advertising API. + * This will call connected callback for high duty cycle + * directed advertiser timeout. + */ + le_adv_stop_free_conn(adv, adv == bt_dev.adv ? evt->status : 0); + } + + if (!evt->status && adv->cb && adv->cb->connected) { + struct bt_conn *conn = bt_conn_lookup_handle(evt->conn_handle); + + if (conn) { + struct bt_le_ext_adv_connected_info info = { + .conn = conn, + }; + + adv->cb->connected(adv, &info); + } + + bt_conn_unref(conn); + } + if (atomic_test_and_clear_bit(adv->flags, BT_ADV_LIMITED)) { atomic_clear_bit(adv->flags, BT_ADV_RPA_VALID); @@ -4816,22 +4906,7 @@ static void le_adv_set_terminated(struct net_buf *buf) } } - if (!evt->status && adv->cb && adv->cb->connected) { - struct bt_conn *conn = bt_conn_lookup_handle(evt->conn_handle); - - if (conn) { - struct bt_le_ext_adv_connected_info info = { - .conn = conn, - }; - - adv->cb->connected(adv, &info); - - bt_conn_unref(conn); - } - } - - if (!atomic_test_bit(bt_dev.flags, BT_DEV_KEEP_ADVERTISING) && - adv == bt_dev.adv) { + if (!atomic_test_bit(adv->flags, BT_ADV_PERSIST) && adv == bt_dev.adv) { adv_delete_legacy(); } } @@ -5499,6 +5574,7 @@ static int le_init(void) if (err) { return err; } + le_read_supp_states_complete(rsp); net_buf_unref(rsp); } @@ -6537,7 +6613,7 @@ int bt_set_name(const char *name) strncpy(bt_dev.name, name, sizeof(bt_dev.name)); /* Update advertising name if in use */ - if (adv && atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING_NAME)) { + if (adv && atomic_test_bit(adv->flags, BT_ADV_INCLUDE_NAME)) { struct bt_data data[] = { BT_DATA(BT_DATA_NAME_COMPLETE, name, strlen(name)) }; struct bt_ad sd = { data, ARRAY_SIZE(data) }; @@ -6677,6 +6753,11 @@ int bt_id_create(bt_addr_le_t *addr, u8_t *irk) int bt_id_reset(u8_t id, bt_addr_le_t *addr, u8_t *irk) { + struct adv_id_check_data check_data = { + .id = id, + .adv_enabled = false, + }; + if (addr && bt_addr_le_cmp(addr, BT_ADDR_LE_ANY)) { if (addr->type != BT_ADDR_LE_RANDOM || !BT_ADDR_IS_STATIC(&addr->a)) { @@ -6697,20 +6778,10 @@ int bt_id_reset(u8_t id, bt_addr_le_t *addr, u8_t *irk) return -EINVAL; } -#if !defined(CONFIG_BT_EXT_ADV) - if (id == bt_dev.adv.id && atomic_test_bit(bt_dev.flags, - BT_DEV_ADVERTISING)) { + bt_adv_foreach(adv_id_check_func, &check_data); + if (check_data.adv_enabled) { return -EBUSY; } -#else - /* TODO: handle multiple advertising set */ - struct bt_le_ext_adv *adv = bt_adv_lookup_handle(0); - - if (adv && adv->id == id && atomic_test_bit(bt_dev.flags, - BT_DEV_ADVERTISING)) { - return -EBUSY; - } -#endif if (IS_ENABLED(CONFIG_BT_CONN) && bt_addr_le_cmp(&bt_dev.id_addr[id], BT_ADDR_LE_ANY)) { @@ -6729,6 +6800,11 @@ int bt_id_reset(u8_t id, bt_addr_le_t *addr, u8_t *irk) int bt_id_delete(u8_t id) { + struct adv_id_check_data check_data = { + .id = id, + .adv_enabled = false, + }; + if (id == BT_ID_DEFAULT || id >= bt_dev.id_count) { return -EINVAL; } @@ -6737,20 +6813,10 @@ int bt_id_delete(u8_t id) return -EALREADY; } -#if !defined(CONFIG_BT_EXT_ADV) - if (id == bt_dev.adv.id && atomic_test_bit(bt_dev.flags, - BT_DEV_ADVERTISING)) { + bt_adv_foreach(adv_id_check_func, &check_data); + if (check_data.adv_enabled) { return -EBUSY; } -#else - /* TODO: handle multiple advertising set */ - struct bt_le_ext_adv *adv = bt_adv_lookup_handle(0); - - if (adv && adv->id == id && atomic_test_bit(bt_dev.flags, - BT_DEV_ADVERTISING)) { - return -EBUSY; - } -#endif if (IS_ENABLED(CONFIG_BT_CONN)) { int err; @@ -7100,13 +7166,12 @@ int bt_le_adv_update_data(const struct bt_data *ad, size_t ad_len, return -EINVAL; } - if (!atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING)) { + if (!atomic_test_bit(adv->flags, BT_ADV_ENABLED)) { return -EAGAIN; } - connectable = atomic_test_bit(bt_dev.flags, - BT_DEV_ADVERTISING_CONNECTABLE); - use_name = atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING_NAME); + connectable = atomic_test_bit(adv->flags, BT_ADV_CONNECTABLE); + use_name = atomic_test_bit(adv->flags, BT_ADV_INCLUDE_NAME); return le_adv_update(adv, ad, ad_len, sd, sd_len, connectable, use_name); @@ -7227,8 +7292,19 @@ static int le_adv_set_random_addr(struct bt_le_ext_adv *adv, u32_t options, static int le_adv_start_add_conn(const struct bt_le_ext_adv *adv, struct bt_conn **out_conn) { + struct adv_id_check_data check_data = { + .id = adv->id, + .adv_enabled = false + }; struct bt_conn *conn; + bt_adv_foreach(adv_id_check_connectable_func, &check_data); + if (check_data.adv_enabled) { + return -ENOTSUP; + } + + bt_dev.adv_conn_id = adv->id; + if (!bt_addr_le_cmp(&adv->target_addr, BT_ADDR_LE_ANY)) { /* Undirected advertising */ conn = bt_conn_add_le(adv->id, BT_ADDR_LE_NONE); @@ -7255,24 +7331,6 @@ static int le_adv_start_add_conn(const struct bt_le_ext_adv *adv, return 0; } -static void le_adv_stop_free_conn(const struct bt_le_ext_adv *adv) -{ - struct bt_conn *conn; - - if (!bt_addr_le_cmp(&adv->target_addr, BT_ADDR_LE_ANY)) { - conn = bt_conn_lookup_state_le(adv->id, BT_ADDR_LE_NONE, - BT_CONN_CONNECT_ADV); - } else { - conn = bt_conn_lookup_state_le(adv->id, &adv->target_addr, - BT_CONN_CONNECT_DIR_ADV); - } - - if (conn) { - bt_conn_set_state(conn, BT_CONN_DISCONNECTED); - bt_conn_unref(conn); - } -} - int bt_le_adv_start_legacy(const struct bt_le_adv_param *param, const struct bt_data *ad, size_t ad_len, const struct bt_data *sd, size_t sd_len) @@ -7292,10 +7350,6 @@ int bt_le_adv_start_legacy(const struct bt_le_adv_param *param, return -EINVAL; } - if (atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING)) { - return -EALREADY; - } - if (!bt_le_adv_random_addr_check(param)) { return -EINVAL; } @@ -7308,9 +7362,8 @@ int bt_le_adv_start_legacy(const struct bt_le_adv_param *param, set_param.filter_policy = get_filter_policy(param->options); adv = adv_new_legacy(); - if (!adv) { - BT_ERR("Legacy advertiser has no adv context"); - return -ENOMEM; + if (!adv || atomic_test_bit(adv->flags, BT_ADV_ENABLED)) { + return -EALREADY; } if (adv->id != param->id) { @@ -7318,6 +7371,8 @@ int bt_le_adv_start_legacy(const struct bt_le_adv_param *param, } adv->id = param->id; + bt_dev.adv_conn_id = adv->id; + err = le_adv_set_random_addr(adv, param->options, dir_adv, &set_param.own_addr_type); if (err) { @@ -7399,16 +7454,16 @@ int bt_le_adv_start_legacy(const struct bt_le_adv_param *param, bt_conn_unref(conn); } - atomic_set_bit_to(bt_dev.flags, BT_DEV_KEEP_ADVERTISING, !dir_adv && + atomic_set_bit_to(adv->flags, BT_ADV_PERSIST, !dir_adv && !(param->options & BT_LE_ADV_OPT_ONE_TIME)); - atomic_set_bit_to(bt_dev.flags, BT_DEV_ADVERTISING_NAME, + atomic_set_bit_to(adv->flags, BT_ADV_INCLUDE_NAME, param->options & BT_LE_ADV_OPT_USE_NAME); - atomic_set_bit_to(bt_dev.flags, BT_DEV_ADVERTISING_CONNECTABLE, + atomic_set_bit_to(adv->flags, BT_ADV_CONNECTABLE, param->options & BT_LE_ADV_OPT_CONNECTABLE); - atomic_set_bit_to(bt_dev.flags, BT_DEV_ADVERTISING_IDENTITY, + atomic_set_bit_to(adv->flags, BT_ADV_USE_IDENTITY, param->options & BT_LE_ADV_OPT_USE_IDENTITY); return 0; @@ -7443,6 +7498,7 @@ static int le_ext_adv_param_set(struct bt_le_ext_adv *adv, bt_addr_le_copy(&adv->target_addr, BT_ADDR_LE_ANY); } + cp->handle = adv->handle; sys_put_le24(param->interval_min, cp->prim_min_interval); sys_put_le24(param->interval_max, cp->prim_max_interval); cp->prim_channel_map = 0x07; @@ -7529,15 +7585,15 @@ static int le_ext_adv_param_set(struct bt_le_ext_adv *adv, } /* Todo: Figure out how keep advertising works with multiple adv sets */ - atomic_set_bit_to(bt_dev.flags, BT_DEV_KEEP_ADVERTISING, false); + atomic_set_bit_to(adv->flags, BT_ADV_PERSIST, false); /* Todo: need to handle setting advertising name in correct adv/scan */ - atomic_set_bit_to(bt_dev.flags, BT_DEV_ADVERTISING_NAME, false); + atomic_set_bit_to(adv->flags, BT_ADV_INCLUDE_NAME, false); - atomic_set_bit_to(bt_dev.flags, BT_DEV_ADVERTISING_CONNECTABLE, + atomic_set_bit_to(adv->flags, BT_ADV_CONNECTABLE, param->options & BT_LE_ADV_OPT_CONNECTABLE); - atomic_set_bit_to(bt_dev.flags, BT_DEV_ADVERTISING_IDENTITY, + atomic_set_bit_to(adv->flags, BT_ADV_USE_IDENTITY, param->options & BT_LE_ADV_OPT_USE_IDENTITY); return 0; @@ -7564,12 +7620,11 @@ int bt_le_adv_start_ext(struct bt_le_ext_adv *adv, return -EINVAL; } - if (atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING)) { + if (atomic_test_bit(adv->flags, BT_ADV_ENABLED)) { return -EALREADY; } adv->id = param->id; - err = le_ext_adv_param_set(adv, param, sd || (param->options & BT_LE_ADV_OPT_USE_NAME)); if (err) { @@ -7619,12 +7674,18 @@ int bt_le_adv_start_ext(struct bt_le_ext_adv *adv, bt_conn_unref(conn); } - atomic_set_bit_to(bt_dev.flags, BT_DEV_KEEP_ADVERTISING, + atomic_set_bit_to(adv->flags, BT_ADV_PERSIST, !dir_adv && !(param->options & BT_LE_ADV_OPT_ONE_TIME)); - atomic_set_bit_to(bt_dev.flags, BT_DEV_ADVERTISING_NAME, + atomic_set_bit_to(adv->flags, BT_ADV_INCLUDE_NAME, param->options & BT_LE_ADV_OPT_USE_NAME); + atomic_set_bit_to(adv->flags, BT_ADV_CONNECTABLE, + param->options & BT_LE_ADV_OPT_CONNECTABLE); + + atomic_set_bit_to(adv->flags, BT_ADV_USE_IDENTITY, + param->options & BT_LE_ADV_OPT_USE_IDENTITY); + return 0; } @@ -7654,14 +7715,20 @@ int bt_le_adv_start(const struct bt_le_adv_param *param, int bt_le_adv_stop(void) { + struct bt_le_ext_adv *adv = bt_adv_lookup_legacy(); int err; + if (!adv) { + BT_ERR("No valid legacy adv"); + return 0; + } + /* Make sure advertising is not re-enabled later even if it's not * currently enabled (i.e. BT_DEV_ADVERTISING is not set). */ - atomic_clear_bit(bt_dev.flags, BT_DEV_KEEP_ADVERTISING); + atomic_clear_bit(adv->flags, BT_ADV_PERSIST); - if (!atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING)) { + if (!atomic_test_bit(adv->flags, BT_ADV_ENABLED)) { /* Legacy advertiser exists, but is not currently advertising. * This happens when keep advertising behavior is active but * no conn object is available to do connectable advertising. @@ -7671,27 +7738,18 @@ int bt_le_adv_stop(void) } if (IS_ENABLED(CONFIG_BT_PERIPHERAL) && - atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING_CONNECTABLE)) { - struct bt_le_ext_adv *adv = bt_adv_lookup_legacy(); - - le_adv_stop_free_conn(adv); + atomic_test_bit(adv->flags, BT_ADV_CONNECTABLE)) { + le_adv_stop_free_conn(adv, 0); } if (IS_ENABLED(CONFIG_BT_EXT_ADV) && BT_FEAT_LE_EXT_ADV(bt_dev.le.features)) { - struct bt_le_ext_adv *adv = bt_adv_lookup_legacy(); - - if (!adv) { - BT_ERR("Advertising but no adv context"); - return 0; - } - err = set_le_adv_enable_ext(adv, false, NULL); if (err) { return err; } } else { - err = set_le_adv_enable_legacy(false); + err = set_le_adv_enable_legacy(adv, false); if (err) { return err; } @@ -7724,12 +7782,19 @@ void bt_le_adv_resume(void) int err; if (!adv) { - BT_WARN("Not legacy advertiser"); + BT_DBG("No valid legacy adv"); + return; + } + + if (!(atomic_test_bit(adv->flags, BT_ADV_PERSIST) && + !atomic_test_bit(adv->flags, BT_ADV_ENABLED))) { + return; + } + + if (!atomic_test_bit(adv->flags, BT_ADV_CONNECTABLE)) { return; } - BT_ASSERT(atomic_test_bit(bt_dev.flags, - BT_DEV_ADVERTISING_CONNECTABLE)); err = le_adv_start_add_conn(adv, &conn); if (err) { BT_DBG("Cannot resume connectable advertising (%d)", err); @@ -7739,7 +7804,7 @@ void bt_le_adv_resume(void) BT_DBG("Resuming connectable advertising"); if (IS_ENABLED(CONFIG_BT_PRIVACY) && - !atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING_IDENTITY)) { + !atomic_test_bit(adv->flags, BT_ADV_USE_IDENTITY)) { le_adv_set_private_addr(adv); } @@ -7805,7 +7870,7 @@ int bt_le_ext_adv_update_param(struct bt_le_ext_adv *adv, return -EINVAL; } - if (atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING)) { + if (atomic_test_bit(adv->flags, BT_ADV_ENABLED)) { return -EINVAL; } @@ -7823,7 +7888,7 @@ int bt_le_ext_adv_start(struct bt_le_ext_adv *adv, int err; if (IS_ENABLED(CONFIG_BT_PERIPHERAL) && - atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING_CONNECTABLE)) { + atomic_test_bit(adv->flags, BT_ADV_CONNECTABLE)) { err = le_adv_start_add_conn(adv, &conn); if (err) { return err; @@ -7860,9 +7925,9 @@ int bt_le_ext_adv_start(struct bt_le_ext_adv *adv, int bt_le_ext_adv_stop(struct bt_le_ext_adv *adv) { - atomic_clear_bit(bt_dev.flags, BT_DEV_KEEP_ADVERTISING); + atomic_clear_bit(adv->flags, BT_ADV_PERSIST); - if (!atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING)) { + if (!atomic_test_bit(adv->flags, BT_ADV_ENABLED)) { return 0; } @@ -7875,8 +7940,8 @@ int bt_le_ext_adv_stop(struct bt_le_ext_adv *adv) } if (IS_ENABLED(CONFIG_BT_PERIPHERAL) && - atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING_CONNECTABLE)) { - le_adv_stop_free_conn(adv); + atomic_test_bit(adv->flags, BT_ADV_CONNECTABLE)) { + le_adv_stop_free_conn(adv, 0); } return set_le_adv_enable_ext(adv, false, NULL); @@ -7888,9 +7953,8 @@ int bt_le_ext_adv_set_data(struct bt_le_ext_adv *adv, { bool connectable, use_name; - connectable = atomic_test_bit(bt_dev.flags, - BT_DEV_ADVERTISING_CONNECTABLE); - use_name = atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING_NAME); + connectable = atomic_test_bit(adv->flags, BT_ADV_CONNECTABLE); + use_name = atomic_test_bit(adv->flags, BT_ADV_INCLUDE_NAME); return le_adv_update(adv, ad, ad_len, sd, sd_len, connectable, use_name); @@ -7907,7 +7971,7 @@ int bt_le_ext_adv_delete(struct bt_le_ext_adv *adv) } /* Advertising set should be stopped first */ - if (atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING)) { + if (atomic_test_bit(adv->flags, BT_ADV_ENABLED)) { return -EINVAL; } @@ -8561,8 +8625,8 @@ int bt_le_oob_get_local(u8_t id, struct bt_le_oob *oob) if (IS_ENABLED(CONFIG_BT_PRIVACY) && !(adv && adv->id == id && - atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING) && - atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING_IDENTITY) && + atomic_test_bit(adv->flags, BT_ADV_ENABLED) && + atomic_test_bit(adv->flags, BT_ADV_USE_IDENTITY) && bt_dev.id_addr[id].type == BT_ADDR_LE_RANDOM)) { if (IS_ENABLED(CONFIG_BT_CENTRAL) && atomic_test_bit(bt_dev.flags, BT_DEV_INITIATING)) { @@ -8579,9 +8643,9 @@ int bt_le_oob_get_local(u8_t id, struct bt_le_oob *oob) } } - if (atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING) && - atomic_test_bit(bt_dev.flags, - BT_DEV_ADVERTISING_IDENTITY) && + if (adv && + atomic_test_bit(adv->flags, BT_ADV_ENABLED) && + atomic_test_bit(adv->flags, BT_ADV_USE_IDENTITY) && (bt_dev.id_addr[id].type == BT_ADDR_LE_RANDOM)) { /* Cannot set a new RPA address while advertising with * random static identity address for a different @@ -8627,7 +8691,7 @@ int bt_le_ext_adv_oob_get_local(struct bt_le_ext_adv *adv, } if (IS_ENABLED(CONFIG_BT_PRIVACY) && - !atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING_IDENTITY)) { + !atomic_test_bit(adv->flags, BT_ADV_USE_IDENTITY)) { /* Don't refresh RPA addresses if the RPA is new. * This allows back to back calls to this function or * bt_le_oob_get_local to not invalidate the previously set diff --git a/subsys/bluetooth/host/hci_core.h b/subsys/bluetooth/host/hci_core.h index 0354e4386ac..76123b53fc6 100644 --- a/subsys/bluetooth/host/hci_core.h +++ b/subsys/bluetooth/host/hci_core.h @@ -33,11 +33,6 @@ enum { BT_DEV_HAS_PUB_KEY, BT_DEV_PUB_KEY_BUSY, - BT_DEV_ADVERTISING, - BT_DEV_ADVERTISING_NAME, - BT_DEV_ADVERTISING_CONNECTABLE, - BT_DEV_ADVERTISING_IDENTITY, - BT_DEV_KEEP_ADVERTISING, BT_DEV_SCANNING, BT_DEV_EXPLICIT_SCAN, BT_DEV_ACTIVE_SCAN, @@ -84,6 +79,22 @@ enum { * events, or both. */ BT_ADV_LIMITED, + /* Advertiser set is currently advertising in the controller. */ + BT_ADV_ENABLED, + /* Advertiser should include name in advertising data */ + BT_ADV_INCLUDE_NAME, + /* Advertiser set is connectable */ + BT_ADV_CONNECTABLE, + /* Advertiser set has disabled the use of private addresses and is using + * the identity address instead. + */ + BT_ADV_USE_IDENTITY, + /* Advertiser has been configured to keep advertising after a connection + * has been established as long as there are connections available. + */ + BT_ADV_PERSIST, + /* Advertiser has been temporarily disabled. */ + BT_ADV_PAUSED, BT_ADV_NUM_FLAGS, }; @@ -153,7 +164,7 @@ struct bt_dev_br { /* State tracking for the local Bluetooth controller */ struct bt_dev { /* Local Identity Address(es) */ - bt_addr_le_t id_addr[CONFIG_BT_ID_MAX]; + bt_addr_le_t id_addr[CONFIG_BT_ID_MAX]; u8_t id_count; struct bt_conn_le_create_param create_param; @@ -167,6 +178,7 @@ struct bt_dev { #endif /* Current local Random Address */ bt_addr_le_t random_addr; + u8_t adv_conn_id; /* Controller version & manufacturer information */ u8_t hci_version; diff --git a/subsys/bluetooth/shell/bt.c b/subsys/bluetooth/shell/bt.c index 4506d65dd0d..df181adb96a 100644 --- a/subsys/bluetooth/shell/bt.c +++ b/subsys/bluetooth/shell/bt.c @@ -1045,6 +1045,7 @@ static int cmd_adv_start(const struct shell *shell, size_t argc, char *argv[]) int err; if (!adv) { + shell_print(shell, "Advertiser[%d] not created", selected_adv); return -EINVAL; } @@ -1091,6 +1092,7 @@ static int cmd_adv_stop(const struct shell *shell, size_t argc, char *argv[]) int err; if (!adv) { + shell_print(shell, "Advertiser[%d] not created", selected_adv); return -EINVAL; } @@ -1110,6 +1112,7 @@ static int cmd_adv_delete(const struct shell *shell, size_t argc, char *argv[]) int err; if (!adv) { + shell_print(shell, "Advertiser[%d] not created", selected_adv); return -EINVAL; } @@ -2296,7 +2299,7 @@ SHELL_STATIC_SUBCMD_SET_CREATE(bt_cmds, "", cmd_adv_data, 1, 16), SHELL_CMD_ARG(adv-start, NULL, "[timeout] [num_events]", cmd_adv_start, - 1, 2), + 1, 4), SHELL_CMD_ARG(adv-stop, NULL, "", cmd_adv_stop, 1, 0), SHELL_CMD_ARG(adv-delete, NULL, "", cmd_adv_delete, 1, 0), SHELL_CMD_ARG(adv-select, NULL, "[adv]", cmd_adv_select, 1, 1),