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; }