From 405ce842ab7da9b49a82c6e8af0f21f481738b0f Mon Sep 17 00:00:00 2001 From: Joakim Andersson Date: Sat, 1 Feb 2020 18:13:05 +0100 Subject: [PATCH] Bluetooth: host: Add new argument and return code to bt_create_conn_le Deprecate bt_create_conn_le and rename it to in order to add return code, new arguments and to follow the established naming convention. Add API for the application to control the scan parameters of the initiator role. This allows the application more scheduling control of the initiator in multi-role scenarios. Also provides options to configure the initiator for LE Coded PHY for long range support. We deprecate the old way of creating connection to make the name more consistent with the rest of the API. Signed-off-by: Joakim Andersson --- include/bluetooth/conn.h | 122 +++++++++++++++++- samples/bluetooth/central/src/main.c | 7 +- samples/bluetooth/central_hr/src/main.c | 10 +- samples/boards/bbc_microbit/pong/src/ble.c | 7 +- subsys/bluetooth/host/conn.c | 44 ++++--- subsys/bluetooth/shell/bt.c | 11 +- subsys/net/l2/bluetooth/bluetooth.c | 5 +- .../bsim_bt/bsim_test_app/src/test_connect1.c | 10 +- tests/bluetooth/tester/src/gap.c | 9 +- 9 files changed, 182 insertions(+), 43 deletions(-) diff --git a/include/bluetooth/conn.h b/include/bluetooth/conn.h index ab3c3d3781d..64116d09304 100644 --- a/include/bluetooth/conn.h +++ b/include/bluetooth/conn.h @@ -22,6 +22,7 @@ #include #include #include +#include #ifdef __cplusplus extern "C" { @@ -278,6 +279,89 @@ int bt_conn_le_param_update(struct bt_conn *conn, */ int bt_conn_disconnect(struct bt_conn *conn, u8_t reason); +enum { + /** Convenience value when no options are specified. */ + BT_LE_CONN_OPT_NONE = 0, + + /** Enable LE Coded PHY. + * + * Enable scanning on the LE Coded PHY. + * Enable connection initiation on the LE Coded PHY. + */ + BT_LE_CONN_OPT_CODED = BIT(0), + + /** Enable LE 2M PHY. + * + * Enable connection initiaton on the LE 2M PHY. + */ + BT_LE_CONN_OPT_2M = BIT(1), + + /** Disable LE 1M PHY. + * + * Disable scanning on the LE 1M PHY. + * Disable connection initiation on the LE 1M PHY. + * + * @note Requires @ref BT_LE_CONN_OPT_CODED. + */ + BT_LE_CONN_OPT_NO_1M = BIT(2), +}; + +struct bt_conn_le_create_param { + + /** Bit-field of create connection options. */ + u32_t options; + + /** Scan interval (N * 0.625 ms) */ + u16_t interval; + + /** Scan window (N * 0.625 ms) */ + u16_t window; + + /** Scan interval LE Coded PHY (N * 0.625 MS) + * + * Set zero to use same as LE 1M PHY scan interval + */ + u16_t interval_coded; + + /** Scan window LE Coded PHY (N * 0.625 MS) + * + * Set zero to use same as LE 1M PHY scan window. + */ + u16_t window_coded; +}; + +/** Helper to declare create connection parameters inline + * + * @param _options Create connection options. + * @param _interval Create connection scan interval (N * 0.625 ms). + * @param _window Create connection scan window (N * 0.625 ms). + */ +#define BT_CONN_LE_CREATE_PARAM(_options, _interval, _window) \ + ((struct bt_conn_le_create_param[]) { { \ + .options = (_options), \ + .interval = (_interval), \ + .window = (_window), \ + .interval_coded = 0, \ + .window_coded = 0, \ + } }) + +/** Default LE create connection parameters. + * Scan continuously by setting scan interval equal to scan window. + */ +#define BT_CONN_LE_CREATE_CONN \ + BT_CONN_LE_CREATE_PARAM(BT_LE_CONN_OPT_NONE, \ + BT_GAP_SCAN_FAST_INTERVAL, \ + BT_GAP_SCAN_FAST_INTERVAL) + +/** Default LE create connection using whitelist parameters. + * Scan window: 30 ms. + * Scan interval: 60 ms. + */ +#define BT_CONN_LE_CREATE_CONN_AUTO \ + BT_CONN_LE_CREATE_PARAM(BT_LE_CONN_OPT_NONE, \ + BT_GAP_SCAN_FAST_INTERVAL, \ + BT_GAP_SCAN_FAST_WINDOW) + /** @brief Initiate an LE connection to a remote device. * * Allows initiate new LE link to remote peer using its address. @@ -287,13 +371,31 @@ int bt_conn_disconnect(struct bt_conn *conn, u8_t reason); * * This uses the General Connection Establishment procedure. * - * @param peer Remote address. - * @param param Initial connection parameters. + * @param[in] peer Remote address. + * @param[in] create_param Create connection parameters. + * @param[in] conn_param Initial connection parameters. + * @param[out] conn Valid connection object on success. * - * @return Valid connection object on success or NULL otherwise. + * @return Zero on success or (negative) error code on failure. */ +int bt_conn_le_create(const bt_addr_le_t *peer, + const struct bt_conn_le_create_param *create_param, + const struct bt_le_conn_param *conn_param, + struct bt_conn **conn); + +__deprecated static inline struct bt_conn *bt_conn_create_le(const bt_addr_le_t *peer, - const struct bt_le_conn_param *param); + const struct bt_le_conn_param *conn_param) +{ + struct bt_conn *conn; + + if (bt_conn_le_create(peer, BT_CONN_LE_CREATE_CONN, conn_param, + &conn)) { + return NULL; + } + + return conn; +} /** @brief Automatically connect to remote devices in whitelist. * @@ -304,12 +406,20 @@ struct bt_conn *bt_conn_create_le(const bt_addr_le_t *peer, * should be started again in the connected callback after a new connection has * been established. * - * @param param Initial connection parameters. + * @param create_param Create connection parameters + * @param conn_param Initial connection parameters. * * @return Zero on success or (negative) error code on failure. * @return -ENOMEM No free connection object available. */ -int bt_conn_create_auto_le(const struct bt_le_conn_param *param); +int bt_conn_le_create_auto(const struct bt_conn_le_create_param *create_param, + const struct bt_le_conn_param *conn_param); + +__deprecated static inline +int bt_conn_create_auto_le(const struct bt_le_conn_param *conn_param) +{ + return bt_conn_le_create_auto(BT_CONN_LE_CREATE_CONN_AUTO, conn_param); +} /** @brief Stop automatic connect creation. * diff --git a/samples/bluetooth/central/src/main.c b/samples/bluetooth/central/src/main.c index f3086b4701e..282bb0617bc 100644 --- a/samples/bluetooth/central/src/main.c +++ b/samples/bluetooth/central/src/main.c @@ -25,6 +25,7 @@ static void device_found(const bt_addr_le_t *addr, s8_t rssi, u8_t type, struct net_buf_simple *ad) { char addr_str[BT_ADDR_LE_STR_LEN]; + int err; if (default_conn) { return; @@ -47,7 +48,11 @@ static void device_found(const bt_addr_le_t *addr, s8_t rssi, u8_t type, return; } - default_conn = bt_conn_create_le(addr, BT_LE_CONN_PARAM_DEFAULT); + err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN, + BT_LE_CONN_PARAM_DEFAULT, &default_conn); + if (err) { + printk("Create conn to %s failed (%u)\n", addr_str, err); + } } static void start_scan(void) diff --git a/samples/bluetooth/central_hr/src/main.c b/samples/bluetooth/central_hr/src/main.c index f3e056f6007..90b309927d6 100644 --- a/samples/bluetooth/central_hr/src/main.c +++ b/samples/bluetooth/central_hr/src/main.c @@ -110,6 +110,7 @@ static bool eir_found(struct bt_data *data, void *user_data) } for (i = 0; i < data->data_len; i += sizeof(u16_t)) { + struct bt_le_conn_param *param; struct bt_uuid *uuid; u16_t u16; int err; @@ -126,8 +127,13 @@ static bool eir_found(struct bt_data *data, void *user_data) continue; } - default_conn = bt_conn_create_le(addr, - BT_LE_CONN_PARAM_DEFAULT); + param = BT_LE_CONN_PARAM_DEFAULT; + err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN, + param, &default_conn); + if (err) { + printk("Create conn failed (err %d)\n", err); + } + return false; } } diff --git a/samples/boards/bbc_microbit/pong/src/ble.c b/samples/boards/bbc_microbit/pong/src/ble.c index f3334b8ebc7..cc232cbfc0c 100644 --- a/samples/boards/bbc_microbit/pong/src/ble.c +++ b/samples/boards/bbc_microbit/pong/src/ble.c @@ -338,14 +338,17 @@ static bool pong_uuid_match(const u8_t *data, u8_t len) static void create_conn(const bt_addr_le_t *addr) { + int err; + if (default_conn) { return; } printk("Found matching device, initiating connection...\n"); - default_conn = bt_conn_create_le(addr, BT_LE_CONN_PARAM_DEFAULT); - if (!default_conn) { + err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN, + BT_LE_CONN_PARAM_DEFAULT, &default_conn); + if (err) { printk("Failed to initiate connection"); return; } diff --git a/subsys/bluetooth/host/conn.c b/subsys/bluetooth/host/conn.c index 8eefd058ba2..0db98c5f11a 100644 --- a/subsys/bluetooth/host/conn.c +++ b/subsys/bluetooth/host/conn.c @@ -2121,7 +2121,8 @@ static void bt_conn_set_param_le(struct bt_conn *conn, } #if defined(CONFIG_BT_WHITELIST) -int bt_conn_create_auto_le(const struct bt_le_conn_param *param) +int bt_conn_le_create_auto(const struct bt_conn_le_create_param *create_param, + const struct bt_le_conn_param *param) { struct bt_conn *conn; int err; @@ -2213,30 +2214,33 @@ int bt_conn_create_auto_stop(void) } #endif /* defined(CONFIG_BT_WHITELIST) */ -struct bt_conn *bt_conn_create_le(const bt_addr_le_t *peer, - const struct bt_le_conn_param *param) +int bt_conn_le_create(const bt_addr_le_t *peer, + const struct bt_conn_le_create_param *create_param, + const struct bt_le_conn_param *conn_param, + struct bt_conn **ret_conn) { struct bt_conn *conn; bt_addr_le_t dst; + int err; if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) { - return NULL; + return -EAGAIN; } - if (!bt_le_conn_params_valid(param)) { - return NULL; + if (!bt_le_conn_params_valid(conn_param)) { + return -EINVAL; } if (atomic_test_bit(bt_dev.flags, BT_DEV_EXPLICIT_SCAN)) { - return NULL; + return -EINVAL; } if (atomic_test_bit(bt_dev.flags, BT_DEV_INITIATING)) { - return NULL; + return -EALREADY; } if (!bt_le_scan_random_addr_check()) { - return NULL; + return -EINVAL; } conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, peer); @@ -2252,7 +2256,7 @@ struct bt_conn *bt_conn_create_le(const bt_addr_le_t *peer, BT_WARN("Found valid connection in %s state", state2str(conn->state)); bt_conn_unref(conn); - return NULL; + return -EINVAL; } if (peer->type == BT_ADDR_LE_PUBLIC_ID || @@ -2266,38 +2270,42 @@ struct bt_conn *bt_conn_create_le(const bt_addr_le_t *peer, /* Only default identity supported for now */ conn = bt_conn_add_le(BT_ID_DEFAULT, &dst); if (!conn) { - return NULL; + return -ENOMEM; } - bt_conn_set_param_le(conn, param); + bt_conn_set_param_le(conn, conn_param); #if defined(CONFIG_BT_SMP) if (!bt_dev.le.rl_size || bt_dev.le.rl_entries > bt_dev.le.rl_size) { bt_conn_set_state(conn, BT_CONN_CONNECT_SCAN); - if (bt_le_scan_update(true)) { + err = bt_le_scan_update(true); + if (err) { bt_conn_set_state(conn, BT_CONN_DISCONNECTED); bt_conn_unref(conn); - return NULL; + return err; } - return conn; + *ret_conn = conn; + return 0; } #endif bt_conn_set_state(conn, BT_CONN_CONNECT); - if (bt_le_create_conn(conn)) { + err = bt_le_create_conn(conn); + if (err) { conn->err = 0; bt_conn_set_state(conn, BT_CONN_DISCONNECTED); bt_conn_unref(conn); bt_le_scan_update(false); - return NULL; + return err; } - return conn; + *ret_conn = conn; + return 0; } #if !defined(CONFIG_BT_WHITELIST) diff --git a/subsys/bluetooth/shell/bt.c b/subsys/bluetooth/shell/bt.c index da50089c2fe..9953b8ae9be 100644 --- a/subsys/bluetooth/shell/bt.c +++ b/subsys/bluetooth/shell/bt.c @@ -738,10 +738,10 @@ static int cmd_connect_le(const struct shell *shell, size_t argc, char *argv[]) return err; } - conn = bt_conn_create_le(&addr, BT_LE_CONN_PARAM_DEFAULT); - - if (!conn) { - shell_error(shell, "Connection failed"); + err = bt_conn_le_create(&addr, BT_CONN_LE_CREATE_CONN, + BT_LE_CONN_PARAM_DEFAULT, &conn); + if (err) { + shell_error(shell, "Connection failed (%d)", err); return -ENOEXEC; } else { @@ -1649,7 +1649,8 @@ static int cmd_wl_connect(const struct shell *shell, size_t argc, char *argv[]) const char *action = argv[1]; if (!strcmp(action, "on")) { - err = bt_conn_create_auto_le(BT_LE_CONN_PARAM_DEFAULT); + err = bt_conn_le_create_auto(BT_CONN_LE_CREATE_CONN_AUTO, + BT_LE_CONN_PARAM_DEFAULT); if (err) { shell_error(shell, "Auto connect failed (err %d)", err); diff --git a/subsys/net/l2/bluetooth/bluetooth.c b/subsys/net/l2/bluetooth/bluetooth.c index 401a17eee1c..cd7cd7c30ab 100644 --- a/subsys/net/l2/bluetooth/bluetooth.c +++ b/subsys/net/l2/bluetooth/bluetooth.c @@ -392,9 +392,8 @@ static int bt_connect(u32_t mgmt_request, struct net_if *iface, void *data, L2CAP_IPSP_PSM); } - default_conn = bt_conn_create_le(addr, BT_LE_CONN_PARAM_DEFAULT); - - return 0; + return bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN, + BT_LE_CONN_PARAM_DEFAULT, &default_conn); } static bool eir_found(u8_t type, const u8_t *data, u8_t data_len, diff --git a/tests/bluetooth/bsim_bt/bsim_test_app/src/test_connect1.c b/tests/bluetooth/bsim_bt/bsim_test_app/src/test_connect1.c index 7fa7785fd5b..27eaad0f2e8 100644 --- a/tests/bluetooth/bsim_bt/bsim_test_app/src/test_connect1.c +++ b/tests/bluetooth/bsim_bt/bsim_test_app/src/test_connect1.c @@ -291,6 +291,7 @@ static bool eir_found(struct bt_data *data, void *user_data) for (i = 0; i < data->data_len; i += sizeof(u16_t)) { struct bt_uuid *uuid; + struct bt_le_conn_param *param; u16_t u16; int err; @@ -306,8 +307,13 @@ static bool eir_found(struct bt_data *data, void *user_data) continue; } - default_conn = bt_conn_create_le(addr, - BT_LE_CONN_PARAM_DEFAULT); + param = BT_LE_CONN_PARAM_DEFAULT; + err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN, + param, &default_conn); + if (err) { + printk("Create conn failed (err %d)\n", err); + } + return false; } } diff --git a/tests/bluetooth/tester/src/gap.c b/tests/bluetooth/tester/src/gap.c index 4ad1474ca8a..1b289ebc186 100644 --- a/tests/bluetooth/tester/src/gap.c +++ b/tests/bluetooth/tester/src/gap.c @@ -506,11 +506,12 @@ static void connect(const u8_t *data, u16_t len) { struct bt_conn *conn; u8_t status; + int err; - conn = bt_conn_create_le((bt_addr_le_t *) data, - BT_LE_CONN_PARAM_DEFAULT); - if (!conn) { - LOG_ERR("Failed to create connection"); + err = bt_conn_le_create((bt_addr_le_t *) data, BT_CONN_LE_CREATE_CONN, + BT_LE_CONN_PARAM_DEFAULT, &conn); + if (err) { + LOG_ERR("Failed to create connection (%d)", err); status = BTP_STATUS_FAILED; goto rsp; }