From 4876a8f39af934aad3d6567f17193c7f1654d7d5 Mon Sep 17 00:00:00 2001 From: Joakim Andersson Date: Mon, 6 Jan 2020 08:05:46 +0100 Subject: [PATCH] Bluetooth: host: Handle scanner active at RPA timeout Fix RPA timeout handling when the scanner is active. An active scanner must be restarted at RPA timeout otherwise the Set Random Address command will fail. Signed-off-by: Joakim Andersson --- subsys/bluetooth/host/hci_core.c | 54 ++++++++++++++++++++++---------- 1 file changed, 37 insertions(+), 17 deletions(-) diff --git a/subsys/bluetooth/host/hci_core.c b/subsys/bluetooth/host/hci_core.c index 6cb9ccf0d3c..6a08e39274b 100644 --- a/subsys/bluetooth/host/hci_core.c +++ b/subsys/bluetooth/host/hci_core.c @@ -84,6 +84,7 @@ static bt_ready_cb_t ready_cb; static bt_le_scan_cb_t *scan_dev_found_cb; #if defined(CONFIG_BT_OBSERVER) +static int set_le_scan_enable(u8_t enable); static sys_slist_t scan_cbs = SYS_SLIST_STATIC_INIT(&scan_cbs); #endif @@ -538,39 +539,58 @@ static int le_set_private_addr(u8_t id) static void rpa_timeout(struct k_work *work) { - int err_adv = 0, err_scan = 0; + bool adv_enabled = false; + int err; BT_DBG(""); /* Invalidate RPA */ atomic_clear_bit(bt_dev.flags, BT_DEV_RPA_VALID); + /* 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_SCANNING) && + atomic_test_bit(bt_dev.flags, BT_DEV_ACTIVE_SCAN)))) { + return; + } + /* * we need to update rpa only if advertising is ongoing, with * BT_DEV_KEEP_ADVERTISING flag is handled in disconnected event */ if (atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING)) { - /* make sure new address is used */ set_advertise_enable(false); - err_adv = le_set_private_addr(bt_dev.adv_id); + adv_enabled = true; + } + +#if defined(CONFIG_BT_OBSERVER) + bool scan_enabled = false; + + if (atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING) && + atomic_test_bit(bt_dev.flags, BT_DEV_ACTIVE_SCAN)) { + set_le_scan_enable(BT_HCI_LE_SCAN_DISABLE); + scan_enabled = true; + } +#endif + + /* 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(bt_dev.adv_id); + if (err) { + BT_WARN("Failed to update RPA address (%d)", err); + return; + } + + if (adv_enabled) { set_advertise_enable(true); } - if (atomic_test_bit(bt_dev.flags, BT_DEV_ACTIVE_SCAN)) { - /* TODO do we need to toggle scan? */ - err_scan = le_set_private_addr(BT_ID_DEFAULT); - } - - /* If both advertising and scanning is active, le_set_private_addr - * will fail. In this case, set back RPA_VALID so that if either of - * advertising or scanning was restarted by application then - * le_set_private_addr in the public API call path will not retry - * set_random_address. This is needed so as to be able to stop and - * restart either of the role by the application after rpa_timeout. - */ - if (err_adv || err_scan) { - atomic_set_bit(bt_dev.flags, BT_DEV_RPA_VALID); +#if defined(CONFIG_BT_OBSERVER) + if (scan_enabled) { + set_le_scan_enable(BT_HCI_LE_SCAN_ENABLE); } +#endif } #else static int le_set_private_addr(u8_t id)