From fbe3285bfae0f0d50600eb0f65a5deae83c49a5b Mon Sep 17 00:00:00 2001 From: Joakim Andersson Date: Wed, 15 Jan 2020 14:32:59 +0100 Subject: [PATCH] Bluetooth: host: Handle initiator at RPA timeout Handle initiator role when RPA timeout expires. For direct connect establishment procedure we make sure the RPA is refreshed when starting initiator and limit the timeout to the RPA timeout. For auto establishment procedure we cancel the initiator and restart it again in the connection complete event that is generated when canceling an initiator. Signed-off-by: Joakim Andersson --- subsys/bluetooth/host/Kconfig | 1 + subsys/bluetooth/host/conn.c | 1 + subsys/bluetooth/host/hci_core.c | 86 +++++++++++++++++++++++++------- 3 files changed, 70 insertions(+), 18 deletions(-) diff --git a/subsys/bluetooth/host/Kconfig b/subsys/bluetooth/host/Kconfig index 767e96400d1..4a08327f9fb 100644 --- a/subsys/bluetooth/host/Kconfig +++ b/subsys/bluetooth/host/Kconfig @@ -440,6 +440,7 @@ config BT_MAX_PAIRED config BT_CREATE_CONN_TIMEOUT int "Timeout for pending LE Create Connection command in seconds" default 3 + range 1 BT_RPA_TIMEOUT if BT_PRIVACY range 1 65535 config BT_CONN_PARAM_UPDATE_TIMEOUT diff --git a/subsys/bluetooth/host/conn.c b/subsys/bluetooth/host/conn.c index a3236ef8d4a..1359544a4a7 100644 --- a/subsys/bluetooth/host/conn.c +++ b/subsys/bluetooth/host/conn.c @@ -2253,6 +2253,7 @@ struct bt_conn *bt_conn_create_le(const bt_addr_le_t *peer, return conn; } #endif + bt_conn_set_state(conn, BT_CONN_CONNECT); if (bt_le_create_conn(conn)) { diff --git a/subsys/bluetooth/host/hci_core.c b/subsys/bluetooth/host/hci_core.c index d4a153523a8..f7f3e3fb4a6 100644 --- a/subsys/bluetooth/host/hci_core.c +++ b/subsys/bluetooth/host/hci_core.c @@ -537,23 +537,11 @@ static int le_set_private_addr(u8_t id) return err; } -static void rpa_timeout(struct k_work *work) +static void le_update_private_addr(void) { 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 @@ -572,6 +560,14 @@ static void rpa_timeout(struct k_work *work) scan_enabled = true; } #endif + if (IS_ENABLED(CONFIG_BT_CENTRAL) && + IS_ENABLED(CONFIG_BT_WHITELIST) && + atomic_test_bit(bt_dev.flags, BT_DEV_INITIATING)) { + /* Canceled initiating procedure will be restarted by + * connection complete event. + */ + bt_le_create_conn_cancel(); + } /* 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. @@ -592,6 +588,34 @@ static void rpa_timeout(struct k_work *work) } #endif } + +static void rpa_timeout(struct k_work *work) +{ + BT_DBG(""); + + if (IS_ENABLED(CONFIG_BT_CENTRAL)) { + struct bt_conn *conn = + bt_conn_lookup_state_le(NULL, BT_CONN_CONNECT_SCAN); + + if (conn) { + bt_conn_unref(conn); + bt_le_create_conn_cancel(); + } + } + + /* 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_INITIATING) || + (atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING) && + atomic_test_bit(bt_dev.flags, BT_DEV_ACTIVE_SCAN)))) { + return; + } + + le_update_private_addr(); +} #else static int le_set_private_addr(u8_t id) { @@ -607,7 +631,7 @@ static int le_set_private_addr(u8_t id) return set_random_address(&nrpa); } -#endif +#endif /* defined(CONFIG_BT_PRIVACY) */ bool bt_le_scan_random_addr_check(void) { @@ -846,10 +870,21 @@ int bt_le_create_conn(const struct bt_conn *conn) } if (IS_ENABLED(CONFIG_BT_PRIVACY)) { - err = le_set_private_addr(BT_ID_DEFAULT); - if (err) { - return err; + if (use_filter) { + err = le_set_private_addr(bt_dev.adv_id); + if (err) { + return err; + } + } else { + /* Force new RPA timeout so that RPA timeout is not + * triggered while direct initiator is active. + */ + atomic_clear_bit(bt_dev.flags, BT_DEV_RPA_VALID); +#if defined(CONFIG_BT_PRIVACY) + le_update_private_addr(); +#endif } + if (BT_FEAT_LE_PRIVACY(bt_dev.le.features)) { own_addr_type = BT_HCI_OWN_ADDR_RPA_OR_RANDOM; } else { @@ -1282,19 +1317,34 @@ static void enh_conn_complete(struct bt_hci_evt_le_enh_conn_complete *evt) * Handle cancellation of outgoing connection attempt. */ if (conn->err == BT_HCI_ERR_UNKNOWN_CONN_ID) { +#if !defined(CONFIG_BT_WHITELIST) /* We notify before checking autoconnect flag * as application may choose to change it from * callback. */ bt_conn_set_state(conn, BT_CONN_DISCONNECTED); -#if !defined(CONFIG_BT_WHITELIST) /* Check if device is marked for autoconnect. */ if (atomic_test_bit(conn->flags, BT_CONN_AUTO_CONNECT)) { + /* Restart passive scanner for device */ bt_conn_set_state(conn, BT_CONN_CONNECT_SCAN); } +#else + if (atomic_test_bit(conn->flags, + BT_CONN_AUTO_CONNECT)) { + + /* Restart whitelist initiator after + * RPA timeout. + */ + bt_le_create_conn(conn); + } else { + /* Create connection canceled by timeout + */ + bt_conn_set_state(conn, + BT_CONN_DISCONNECTED); + } #endif /* !defined(CONFIG_BT_WHITELIST) */ goto done; }