From a038dc76f117dd1a637e60c2413d71008fc9a908 Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Mon, 30 Mar 2020 19:23:16 +1000 Subject: [PATCH] bluetooth: host: Dynamic bt_conn_le_create timeout Extends the bt_conn_le_create_param struct to provide the option to set a custom timeout for the initiation of the connection. The logic for the default values of window_coded and interval_coded were moved to conn.c in order to resolve all defaults for the create_param struct at a single location. Timeout is not added as a parameter to the BT_CONN_LE_CREATE_PARAM macro due to the expectation that CONFIG_BT_CREATE_CONN_TIMEOUT will be the typical value that users will expect. Fixes #23468 Signed-off-by: Jordan Yates --- include/bluetooth/conn.h | 13 ++++++++- subsys/bluetooth/host/Kconfig | 4 +-- subsys/bluetooth/host/conn.c | 50 +++++++++++++++++++++++++++----- subsys/bluetooth/host/hci_core.c | 15 ++++------ 4 files changed, 62 insertions(+), 20 deletions(-) diff --git a/include/bluetooth/conn.h b/include/bluetooth/conn.h index afa23629648..92b036da01a 100644 --- a/include/bluetooth/conn.h +++ b/include/bluetooth/conn.h @@ -328,6 +328,15 @@ struct bt_conn_le_create_param { * Set zero to use same as LE 1M PHY scan window. */ u16_t window_coded; + + /** Connection initiation timeout (N * 10 MS) + * + * Set zero to use the default :option:`CONFIG_BT_CREATE_CONN_TIMEOUT` + * timeout. + * + * @note Unused in @ref bt_conn_create_auto_le + */ + u16_t timeout; }; /** Helper to declare create connection parameters inline @@ -343,6 +352,7 @@ struct bt_conn_le_create_param { .window = (_window), \ .interval_coded = 0, \ .window_coded = 0, \ + .timeout = 0, \ } }) /** Default LE create connection parameters. @@ -610,7 +620,8 @@ struct bt_conn_cb { * - @ref BT_HCI_ERR_UNKNOWN_CONN_ID Creating the connection started by * @ref bt_conn_create_le was canceled either by the user through * @ref bt_conn_disconnect or by the timeout in the host through - * :option:`CONFIG_BT_CREATE_CONN_TIMEOUT`. + * @ref bt_conn_le_create_param timeout parameter, which defaults to + * :option:`CONFIG_BT_CREATE_CONN_TIMEOUT` seconds. * - @p BT_HCI_ERR_ADV_TIMEOUT Directed advertiser started by @ref * bt_conn_create_slave_le with high duty cycle timed out after 1.28 * seconds. diff --git a/subsys/bluetooth/host/Kconfig b/subsys/bluetooth/host/Kconfig index 88e6c62125e..f310d15ae26 100644 --- a/subsys/bluetooth/host/Kconfig +++ b/subsys/bluetooth/host/Kconfig @@ -477,8 +477,8 @@ 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 + range 1 BT_RPA_TIMEOUT if BT_PRIVACY && (BT_RPA_TIMEOUT < 655) + range 1 655 config BT_CONN_PARAM_UPDATE_TIMEOUT int "Peripheral connection parameter update timeout in milliseconds" diff --git a/subsys/bluetooth/host/conn.c b/subsys/bluetooth/host/conn.c index f14a14a6736..a4cd3e56133 100644 --- a/subsys/bluetooth/host/conn.c +++ b/subsys/bluetooth/host/conn.c @@ -64,9 +64,6 @@ NET_BUF_POOL_FIXED_DEFINE(frag_pool, CONFIG_BT_L2CAP_TX_FRAG_COUNT, FRAG_SIZE, #endif /* CONFIG_BT_L2CAP_TX_FRAG_COUNT > 0 */ -/* How long until we cancel HCI_LE_Create_Connection */ -#define CONN_TIMEOUT K_SECONDS(CONFIG_BT_CREATE_CONN_TIMEOUT) - #if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR) const struct bt_conn_auth_cb *bt_auth; #endif /* CONFIG_BT_SMP || CONFIG_BT_BREDR */ @@ -1713,7 +1710,7 @@ void bt_conn_set_state(struct bt_conn *conn, bt_conn_state_t state) /* this indicate LE Create Connection with peer address * has been stopped. This could either be triggered by * the application through bt_conn_disconnect or by - * timeout set by CONFIG_BT_CREATE_CONN_TIMEOUT. + * timeout set by bt_conn_le_create_param.timeout. */ if (conn->err) { notify_connected(conn); @@ -1765,7 +1762,8 @@ void bt_conn_set_state(struct bt_conn *conn, bt_conn_state_t state) */ if (IS_ENABLED(CONFIG_BT_CENTRAL) && conn->type == BT_CONN_TYPE_LE) { - k_delayed_work_submit(&conn->update_work, CONN_TIMEOUT); + k_delayed_work_submit(&conn->update_work, + K_MSEC(10 * bt_dev.create_param.timeout)); } break; @@ -2122,6 +2120,40 @@ static void bt_conn_set_param_le(struct bt_conn *conn, conn->le.timeout = param->timeout; } +static bool create_param_validate(const struct bt_conn_le_create_param *param) +{ +#if defined(CONFIG_BT_PRIVACY) + /* Initiation timeout cannot be greater than the RPA timeout */ + const u32_t timeout_max = (MSEC_PER_SEC / 10) * CONFIG_BT_RPA_TIMEOUT; + + if (param->timeout > timeout_max) { + return false; + } +#endif + + return true; +} + +static void create_param_setup(const struct bt_conn_le_create_param *param) +{ + bt_dev.create_param = *param; + + bt_dev.create_param.timeout = + (bt_dev.create_param.timeout != 0) ? + bt_dev.create_param.timeout : + (MSEC_PER_SEC / 10) * CONFIG_BT_CREATE_CONN_TIMEOUT; + + bt_dev.create_param.interval_coded = + (bt_dev.create_param.interval_coded != 0) ? + bt_dev.create_param.interval_coded : + bt_dev.create_param.interval; + + bt_dev.create_param.window_coded = + (bt_dev.create_param.window_coded != 0) ? + bt_dev.create_param.window_coded : + bt_dev.create_param.window; +} + #if defined(CONFIG_BT_WHITELIST) int bt_conn_le_create_auto(const struct bt_conn_le_create_param *create_param, const struct bt_le_conn_param *param) @@ -2165,7 +2197,7 @@ int bt_conn_le_create_auto(const struct bt_conn_le_create_param *create_param, } bt_conn_set_param_le(conn, param); - bt_dev.create_param = *create_param; + create_param_setup(create_param); atomic_set_bit(conn->flags, BT_CONN_AUTO_CONNECT); bt_conn_set_state(conn, BT_CONN_CONNECT_AUTO); @@ -2235,6 +2267,10 @@ int bt_conn_le_create(const bt_addr_le_t *peer, return -EINVAL; } + if (!create_param_validate(create_param)) { + return -EINVAL; + } + if (atomic_test_bit(bt_dev.flags, BT_DEV_EXPLICIT_SCAN)) { return -EINVAL; } @@ -2278,7 +2314,7 @@ int bt_conn_le_create(const bt_addr_le_t *peer, } bt_conn_set_param_le(conn, conn_param); - bt_dev.create_param = *create_param; + create_param_setup(create_param); #if defined(CONFIG_BT_SMP) if (!bt_dev.le.rl_size || bt_dev.le.rl_entries > bt_dev.le.rl_size) { diff --git a/subsys/bluetooth/host/hci_core.c b/subsys/bluetooth/host/hci_core.c index c18cd82ef4e..d3bba1f3e5f 100644 --- a/subsys/bluetooth/host/hci_core.c +++ b/subsys/bluetooth/host/hci_core.c @@ -1261,7 +1261,7 @@ static inline bool rpa_timeout_valid_check(void) #if defined(CONFIG_BT_PRIVACY) /* Check if create conn timeout will happen before RPA timeout. */ return k_delayed_work_remaining_get(&bt_dev.rpa_update) > - K_SECONDS(CONFIG_BT_CREATE_CONN_TIMEOUT); + (10 * bt_dev.create_param.timeout); #else return true; #endif @@ -1401,17 +1401,12 @@ int bt_le_create_conn_ext(const struct bt_conn *conn) } if (bt_dev.create_param.options & BT_LE_CONN_OPT_CODED) { - u16_t interval = bt_dev.create_param.interval_coded ? - bt_dev.create_param.interval_coded : - bt_dev.create_param.interval; - u16_t window = bt_dev.create_param.window_coded ? - bt_dev.create_param.window_coded : - bt_dev.create_param.window; - cp->phys |= BT_HCI_LE_EXT_SCAN_PHY_CODED; phy = net_buf_add(buf, sizeof(*phy)); - phy->scan_interval = sys_cpu_to_le16(interval); - phy->scan_window = sys_cpu_to_le16(window); + phy->scan_interval = sys_cpu_to_le16( + bt_dev.create_param.interval_coded); + phy->scan_window = sys_cpu_to_le16( + bt_dev.create_param.window_coded); set_phy_conn_param(conn, phy); }