From 51d510adc60f6bb70c58384328e3661e86d0b13c Mon Sep 17 00:00:00 2001 From: Joakim Andersson Date: Fri, 11 Nov 2022 12:15:27 +0100 Subject: [PATCH] Bluetooth: host: Call RPA expired on disabled advertising sets Call the RPA expired callback on advertising sets even when they are not enabled. The RPA expired callback will now be called on advertising sets when the BT_ADV_RPA_VALID flag is cleared for the set. Signed-off-by: Joakim Andersson --- subsys/bluetooth/host/adv.c | 4 +- subsys/bluetooth/host/id.c | 106 +++++++++++++++++++++--------------- subsys/bluetooth/host/id.h | 2 + 3 files changed, 65 insertions(+), 47 deletions(-) diff --git a/subsys/bluetooth/host/adv.c b/subsys/bluetooth/host/adv.c index ec120383fa3..bed4b2cdb8d 100644 --- a/subsys/bluetooth/host/adv.c +++ b/subsys/bluetooth/host/adv.c @@ -1639,7 +1639,7 @@ int bt_le_ext_adv_stop(struct bt_le_ext_adv *adv) } if (atomic_test_and_clear_bit(adv->flags, BT_ADV_LIMITED)) { - atomic_clear_bit(adv->flags, BT_ADV_RPA_VALID); + bt_id_adv_limited_stopped(adv); #if defined(CONFIG_BT_SMP) bt_id_pending_keys_update(); @@ -2015,7 +2015,7 @@ void bt_hci_le_adv_set_terminated(struct net_buf *buf) } if (atomic_test_and_clear_bit(adv->flags, BT_ADV_LIMITED)) { - atomic_clear_bit(adv->flags, BT_ADV_RPA_VALID); + bt_id_adv_limited_stopped(adv); #if defined(CONFIG_BT_SMP) bt_id_pending_keys_update(); diff --git a/subsys/bluetooth/host/id.c b/subsys/bluetooth/host/id.c index d695e055f83..a6fc343137f 100644 --- a/subsys/bluetooth/host/id.c +++ b/subsys/bluetooth/host/id.c @@ -81,7 +81,6 @@ static void adv_id_check_func(struct bt_le_ext_adv *adv, void *data) } } -#if defined(CONFIG_BT_PRIVACY) static void adv_is_private_enabled(struct bt_le_ext_adv *adv, void *data) { bool *adv_enabled = data; @@ -91,7 +90,6 @@ static void adv_is_private_enabled(struct bt_le_ext_adv *adv, void *data) *adv_enabled = true; } } -#endif /* defined(CONFIG_BT_PRIVACY) */ #if defined(CONFIG_BT_SMP) static void adv_is_limited_enabled(struct bt_le_ext_adv *adv, void *data) @@ -198,14 +196,33 @@ int bt_id_set_adv_random_addr(struct bt_le_ext_adv *adv, return 0; } -static void adv_disabled_rpa_invalidate(struct bt_le_ext_adv *adv, void *data) +static void adv_rpa_expired(struct bt_le_ext_adv *adv) { - /* Don't invalidate RPA of enabled advertising set. */ - if (!atomic_test_bit(adv->flags, BT_ADV_ENABLED)) { + bool rpa_invalid = true; + +#if defined(CONFIG_BT_EXT_ADV) && defined(CONFIG_BT_PRIVACY) + /* Notify the user about the RPA timeout and set the RPA validity. */ + if (atomic_test_bit(adv->flags, BT_ADV_RPA_VALID) && + adv->cb && adv->cb->rpa_expired) { + rpa_invalid = adv->cb->rpa_expired(adv); + } +#endif + if (rpa_invalid) { atomic_clear_bit(adv->flags, BT_ADV_RPA_VALID); } } +static void adv_rpa_invalidate(struct bt_le_ext_adv *adv, void *data) +{ + /* RPA of Advertisers limited by timeot or number of packets only expire + * when they are stopped. + */ + if (!atomic_test_bit(adv->flags, BT_ADV_LIMITED) && + !atomic_test_bit(adv->flags, BT_ADV_USE_IDENTITY)) { + adv_rpa_expired(adv); + } +} + static void le_rpa_invalidate(void) { /* Invalidate RPA */ @@ -214,13 +231,8 @@ static void le_rpa_invalidate(void) atomic_clear_bit(bt_dev.flags, BT_DEV_RPA_VALID); } - /* Invalidate RPA of advertising sets that are disabled. - * - * Enabled advertising set have to call rpa_expired callback first to - * determine if the RPA of the advertising set should be rotated. - */ if (IS_ENABLED(CONFIG_BT_BROADCASTER)) { - bt_le_ext_adv_foreach(adv_disabled_rpa_invalidate, NULL); + bt_le_ext_adv_foreach(adv_rpa_invalidate, NULL); } } @@ -320,6 +332,13 @@ int bt_id_set_adv_private_addr(struct bt_le_ext_adv *adv) /* check if RPA is valid */ if (atomic_test_bit(adv->flags, BT_ADV_RPA_VALID)) { + /* Schedule the RPA timer if it is not running. + * The RPA may be valid without the timer running. + */ + if (!atomic_test_bit(adv->flags, BT_ADV_LIMITED)) { + le_rpa_timeout_submit(); + } + return 0; } @@ -420,10 +439,9 @@ int bt_id_set_adv_private_addr(struct bt_le_ext_adv *adv) } #endif /* defined(CONFIG_BT_PRIVACY) */ -#if defined(CONFIG_BT_EXT_ADV) && defined(CONFIG_BT_PRIVACY) -static void adv_disable_rpa(struct bt_le_ext_adv *adv, void *data) +static void adv_pause_rpa(struct bt_le_ext_adv *adv, void *data) { - bool rpa_invalid = true; + bool *adv_enabled = data; /* Disable advertising sets to prepare them for RPA update. */ if (atomic_test_bit(adv->flags, BT_ADV_ENABLED) && @@ -437,21 +455,26 @@ static void adv_disable_rpa(struct bt_le_ext_adv *adv, void *data) } atomic_set_bit(adv->flags, BT_ADV_RPA_UPDATE); + *adv_enabled = true; + } +} - /* Notify the user about the RPA timeout and set the RPA validity. */ - if (adv->cb && adv->cb->rpa_expired) { - rpa_invalid = adv->cb->rpa_expired(adv); - } +static bool le_adv_rpa_timeout(void) +{ + bool adv_enabled = false; - if (rpa_invalid) { - atomic_clear_bit(adv->flags, BT_ADV_RPA_VALID); + if (IS_ENABLED(CONFIG_BT_BROADCASTER)) { + if (IS_ENABLED(CONFIG_BT_EXT_ADV) && + BT_DEV_FEAT_LE_EXT_ADV(bt_dev.le.features)) { + /* Pause all advertising sets using RPAs */ + bt_le_ext_adv_foreach(adv_pause_rpa, &adv_enabled); } else { - /* Submit the timeout in case no advertising set updates their RPA - * in the current period. This makes sure that the RPA timer is running. - */ - le_rpa_timeout_submit(); + /* Check if advertising set is enabled */ + bt_le_ext_adv_foreach(adv_is_private_enabled, &adv_enabled); } } + + return adv_enabled; } static void adv_enable_rpa(struct bt_le_ext_adv *adv, void *data) @@ -471,16 +494,6 @@ static void adv_enable_rpa(struct bt_le_ext_adv *adv, void *data) } } } -#endif /* defined(CONFIG_BT_EXT_ADV) && defined(CONFIG_BT_PRIVACY) */ - -static void adv_update_rpa_foreach(void) -{ -#if defined(CONFIG_BT_EXT_ADV) && defined(CONFIG_BT_PRIVACY) - bt_le_ext_adv_foreach(adv_disable_rpa, NULL); - - bt_le_ext_adv_foreach(adv_enable_rpa, NULL); -#endif -} static void le_update_private_addr(void) { @@ -489,12 +502,6 @@ static void le_update_private_addr(void) uint8_t id = BT_ID_DEFAULT; int err; - if (IS_ENABLED(CONFIG_BT_BROADCASTER) && - IS_ENABLED(CONFIG_BT_EXT_ADV) && - BT_DEV_FEAT_LE_EXT_ADV(bt_dev.le.features)) { - adv_update_rpa_foreach(); - } - #if defined(CONFIG_BT_OBSERVER) bool scan_enabled = false; @@ -538,6 +545,12 @@ static void le_update_private_addr(void) return; } + if (IS_ENABLED(CONFIG_BT_BROADCASTER) && + IS_ENABLED(CONFIG_BT_EXT_ADV) && + BT_DEV_FEAT_LE_EXT_ADV(bt_dev.le.features)) { + bt_le_ext_adv_foreach(adv_enable_rpa, NULL); + } + if (IS_ENABLED(CONFIG_BT_BROADCASTER) && adv && adv_enabled) { bt_le_adv_set_enable_legacy(adv, true); @@ -557,6 +570,7 @@ static void le_force_rpa_timeout(void) k_work_cancel_delayable_sync(&bt_dev.rpa_update, &sync); #endif + (void)le_adv_rpa_timeout(); le_rpa_invalidate(); le_update_private_addr(); } @@ -564,7 +578,7 @@ static void le_force_rpa_timeout(void) #if defined(CONFIG_BT_PRIVACY) static void rpa_timeout(struct k_work *work) { - bool adv_enabled = false; + bool adv_enabled; BT_DBG(""); @@ -579,12 +593,9 @@ static void rpa_timeout(struct k_work *work) } } + adv_enabled = le_adv_rpa_timeout(); le_rpa_invalidate(); - if (IS_ENABLED(CONFIG_BT_BROADCASTER)) { - bt_le_ext_adv_foreach(adv_is_private_enabled, &adv_enabled); - } - /* IF no roles using the RPA is running we can stop the RPA timer */ if (!(adv_enabled || atomic_test_bit(bt_dev.flags, BT_DEV_INITIATING) || @@ -711,6 +722,11 @@ bool bt_id_adv_random_addr_check(const struct bt_le_adv_param *param) return true; } +void bt_id_adv_limited_stopped(struct bt_le_ext_adv *adv) +{ + adv_rpa_expired(adv); +} + #if defined(CONFIG_BT_SMP) static int le_set_privacy_mode(const bt_addr_le_t *addr, uint8_t mode) { diff --git a/subsys/bluetooth/host/id.h b/subsys/bluetooth/host/id.h index 659bc22d623..55a25d93400 100644 --- a/subsys/bluetooth/host/id.h +++ b/subsys/bluetooth/host/id.h @@ -43,3 +43,5 @@ int bt_id_set_adv_private_addr(struct bt_le_ext_adv *adv); int bt_id_set_private_addr(uint8_t id); void bt_id_pending_keys_update(void); + +void bt_id_adv_limited_stopped(struct bt_le_ext_adv *adv);