Bluetooth: host: Fix RPA timeout expiration
Fix RPA timeout expiration when BT_EXT_ADV has been enabled. Always invalidate the device RPA on RPA timeout. This RPA is used by the scan roles, and the advertiser that was started using the bt_le_adv_start API. Call the RPA expire callback only on advertising sets that are enabled and not being limited by a timeout and not using the identity address. On RPA timeout always invalidate the RPA of advertising sets that are disabled. Fixes: #51208 Fixes: #51228 Fixes: #51247 Signed-off-by: Joakim Andersson <joakim.andersson@nordicsemi.no>
This commit is contained in:
parent
0a1a32841f
commit
d63ae607cc
2 changed files with 31 additions and 36 deletions
|
@ -87,6 +87,8 @@ enum {
|
||||||
* of the RPA timeout.
|
* of the RPA timeout.
|
||||||
*/
|
*/
|
||||||
BT_ADV_RPA_VALID,
|
BT_ADV_RPA_VALID,
|
||||||
|
/* The private random address of the advertiser is being updated. */
|
||||||
|
BT_ADV_RPA_UPDATE,
|
||||||
/* The advertiser set is limited by a timeout, or number of advertising
|
/* The advertiser set is limited by a timeout, or number of advertising
|
||||||
* events, or both.
|
* events, or both.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -198,9 +198,10 @@ int bt_id_set_adv_random_addr(struct bt_le_ext_adv *adv,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void adv_rpa_invalidate(struct bt_le_ext_adv *adv, void *data)
|
static void adv_disabled_rpa_invalidate(struct bt_le_ext_adv *adv, void *data)
|
||||||
{
|
{
|
||||||
if (!atomic_test_bit(adv->flags, BT_ADV_LIMITED)) {
|
/* Don't invalidate RPA of enabled advertising set. */
|
||||||
|
if (!atomic_test_bit(adv->flags, BT_ADV_ENABLED)) {
|
||||||
atomic_clear_bit(adv->flags, BT_ADV_RPA_VALID);
|
atomic_clear_bit(adv->flags, BT_ADV_RPA_VALID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -213,8 +214,13 @@ static void le_rpa_invalidate(void)
|
||||||
atomic_clear_bit(bt_dev.flags, BT_DEV_RPA_VALID);
|
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)) {
|
if (IS_ENABLED(CONFIG_BT_BROADCASTER)) {
|
||||||
bt_le_ext_adv_foreach(adv_rpa_invalidate, NULL);
|
bt_le_ext_adv_foreach(adv_disabled_rpa_invalidate, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -417,19 +423,11 @@ int bt_id_set_adv_private_addr(struct bt_le_ext_adv *adv)
|
||||||
#if defined(CONFIG_BT_EXT_ADV) && 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_disable_rpa(struct bt_le_ext_adv *adv, void *data)
|
||||||
{
|
{
|
||||||
uint8_t adv_index = bt_le_ext_adv_get_index(adv);
|
|
||||||
bool *adv_disabled = data;
|
|
||||||
bool rpa_invalid = true;
|
bool rpa_invalid = true;
|
||||||
|
|
||||||
adv_disabled[adv_index] = false;
|
|
||||||
|
|
||||||
/* Invalidate RPA only for non-limited advertising sets. */
|
|
||||||
if (atomic_test_bit(adv->flags, BT_ADV_LIMITED)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Disable advertising sets to prepare them for RPA update. */
|
/* Disable advertising sets to prepare them for RPA update. */
|
||||||
if (atomic_test_bit(adv->flags, BT_ADV_ENABLED) &&
|
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)) {
|
!atomic_test_bit(adv->flags, BT_ADV_USE_IDENTITY)) {
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
@ -438,25 +436,27 @@ static void adv_disable_rpa(struct bt_le_ext_adv *adv, void *data)
|
||||||
BT_ERR("Failed to disable advertising (err %d)", err);
|
BT_ERR("Failed to disable advertising (err %d)", err);
|
||||||
}
|
}
|
||||||
|
|
||||||
adv_disabled[adv_index] = true;
|
atomic_set_bit(adv->flags, BT_ADV_RPA_UPDATE);
|
||||||
}
|
|
||||||
|
|
||||||
/* Notify the user about the RPA timeout and set the RPA validity. */
|
/* Notify the user about the RPA timeout and set the RPA validity. */
|
||||||
if (adv->cb && adv->cb->rpa_expired) {
|
if (adv->cb && adv->cb->rpa_expired) {
|
||||||
rpa_invalid = adv->cb->rpa_expired(adv);
|
rpa_invalid = adv->cb->rpa_expired(adv);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rpa_invalid) {
|
if (rpa_invalid) {
|
||||||
atomic_clear_bit(adv->flags, BT_ADV_RPA_VALID);
|
atomic_clear_bit(adv->flags, BT_ADV_RPA_VALID);
|
||||||
|
} 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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void adv_enable_rpa(struct bt_le_ext_adv *adv, void *data)
|
static void adv_enable_rpa(struct bt_le_ext_adv *adv, void *data)
|
||||||
{
|
{
|
||||||
uint8_t adv_index = bt_le_ext_adv_get_index(adv);
|
if (atomic_test_and_clear_bit(adv->flags, BT_ADV_RPA_UPDATE)) {
|
||||||
bool *adv_disabled = data;
|
|
||||||
|
|
||||||
if (adv_disabled[adv_index]) {
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = bt_id_set_adv_private_addr(adv);
|
err = bt_id_set_adv_private_addr(adv);
|
||||||
|
@ -476,16 +476,9 @@ static void adv_enable_rpa(struct bt_le_ext_adv *adv, void *data)
|
||||||
static void adv_update_rpa_foreach(void)
|
static void adv_update_rpa_foreach(void)
|
||||||
{
|
{
|
||||||
#if defined(CONFIG_BT_EXT_ADV) && defined(CONFIG_BT_PRIVACY)
|
#if defined(CONFIG_BT_EXT_ADV) && defined(CONFIG_BT_PRIVACY)
|
||||||
bool adv_disabled[CONFIG_BT_EXT_ADV_MAX_ADV_SET];
|
bt_le_ext_adv_foreach(adv_disable_rpa, NULL);
|
||||||
|
|
||||||
bt_le_ext_adv_foreach(adv_disable_rpa, adv_disabled);
|
bt_le_ext_adv_foreach(adv_enable_rpa, NULL);
|
||||||
|
|
||||||
/* Submit the timeout in case all sets use the same
|
|
||||||
* RPA for the next rotation period.
|
|
||||||
*/
|
|
||||||
le_rpa_timeout_submit();
|
|
||||||
|
|
||||||
bt_le_ext_adv_foreach(adv_enable_rpa, adv_disabled);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -500,8 +493,6 @@ static void le_update_private_addr(void)
|
||||||
IS_ENABLED(CONFIG_BT_EXT_ADV) &&
|
IS_ENABLED(CONFIG_BT_EXT_ADV) &&
|
||||||
BT_DEV_FEAT_LE_EXT_ADV(bt_dev.le.features)) {
|
BT_DEV_FEAT_LE_EXT_ADV(bt_dev.le.features)) {
|
||||||
adv_update_rpa_foreach();
|
adv_update_rpa_foreach();
|
||||||
} else {
|
|
||||||
le_rpa_invalidate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(CONFIG_BT_OBSERVER)
|
#if defined(CONFIG_BT_OBSERVER)
|
||||||
|
@ -566,6 +557,7 @@ static void le_force_rpa_timeout(void)
|
||||||
|
|
||||||
k_work_cancel_delayable_sync(&bt_dev.rpa_update, &sync);
|
k_work_cancel_delayable_sync(&bt_dev.rpa_update, &sync);
|
||||||
#endif
|
#endif
|
||||||
|
le_rpa_invalidate();
|
||||||
le_update_private_addr();
|
le_update_private_addr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -587,6 +579,8 @@ static void rpa_timeout(struct k_work *work)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
le_rpa_invalidate();
|
||||||
|
|
||||||
if (IS_ENABLED(CONFIG_BT_BROADCASTER)) {
|
if (IS_ENABLED(CONFIG_BT_BROADCASTER)) {
|
||||||
bt_le_ext_adv_foreach(adv_is_private_enabled, &adv_enabled);
|
bt_le_ext_adv_foreach(adv_is_private_enabled, &adv_enabled);
|
||||||
}
|
}
|
||||||
|
@ -596,7 +590,6 @@ static void rpa_timeout(struct k_work *work)
|
||||||
atomic_test_bit(bt_dev.flags, BT_DEV_INITIATING) ||
|
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_SCANNING) &&
|
||||||
atomic_test_bit(bt_dev.flags, BT_DEV_ACTIVE_SCAN)))) {
|
atomic_test_bit(bt_dev.flags, BT_DEV_ACTIVE_SCAN)))) {
|
||||||
le_rpa_invalidate();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue