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 <joakim.andersson@nordicsemi.no>
This commit is contained in:
Joakim Andersson 2020-02-01 18:13:05 +01:00 committed by Johan Hedberg
commit 405ce842ab
9 changed files with 182 additions and 43 deletions

View file

@ -22,6 +22,7 @@
#include <bluetooth/bluetooth.h> #include <bluetooth/bluetooth.h>
#include <bluetooth/hci_err.h> #include <bluetooth/hci_err.h>
#include <bluetooth/addr.h> #include <bluetooth/addr.h>
#include <bluetooth/gap.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { 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); 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. /** @brief Initiate an LE connection to a remote device.
* *
* Allows initiate new LE link to remote peer using its address. * 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. * This uses the General Connection Establishment procedure.
* *
* @param peer Remote address. * @param[in] peer Remote address.
* @param param Initial connection parameters. * @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, 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. /** @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 * should be started again in the connected callback after a new connection has
* been established. * 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 Zero on success or (negative) error code on failure.
* @return -ENOMEM No free connection object available. * @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. /** @brief Stop automatic connect creation.
* *

View file

@ -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) struct net_buf_simple *ad)
{ {
char addr_str[BT_ADDR_LE_STR_LEN]; char addr_str[BT_ADDR_LE_STR_LEN];
int err;
if (default_conn) { if (default_conn) {
return; return;
@ -47,7 +48,11 @@ static void device_found(const bt_addr_le_t *addr, s8_t rssi, u8_t type,
return; 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) static void start_scan(void)

View file

@ -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)) { for (i = 0; i < data->data_len; i += sizeof(u16_t)) {
struct bt_le_conn_param *param;
struct bt_uuid *uuid; struct bt_uuid *uuid;
u16_t u16; u16_t u16;
int err; int err;
@ -126,8 +127,13 @@ static bool eir_found(struct bt_data *data, void *user_data)
continue; continue;
} }
default_conn = bt_conn_create_le(addr, param = BT_LE_CONN_PARAM_DEFAULT;
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; return false;
} }
} }

View file

@ -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) static void create_conn(const bt_addr_le_t *addr)
{ {
int err;
if (default_conn) { if (default_conn) {
return; return;
} }
printk("Found matching device, initiating connection...\n"); printk("Found matching device, initiating connection...\n");
default_conn = bt_conn_create_le(addr, BT_LE_CONN_PARAM_DEFAULT); err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN,
if (!default_conn) { BT_LE_CONN_PARAM_DEFAULT, &default_conn);
if (err) {
printk("Failed to initiate connection"); printk("Failed to initiate connection");
return; return;
} }

View file

@ -2121,7 +2121,8 @@ static void bt_conn_set_param_le(struct bt_conn *conn,
} }
#if defined(CONFIG_BT_WHITELIST) #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; struct bt_conn *conn;
int err; int err;
@ -2213,30 +2214,33 @@ int bt_conn_create_auto_stop(void)
} }
#endif /* defined(CONFIG_BT_WHITELIST) */ #endif /* defined(CONFIG_BT_WHITELIST) */
struct bt_conn *bt_conn_create_le(const bt_addr_le_t *peer, int bt_conn_le_create(const bt_addr_le_t *peer,
const struct bt_le_conn_param *param) 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; struct bt_conn *conn;
bt_addr_le_t dst; bt_addr_le_t dst;
int err;
if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) { if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) {
return NULL; return -EAGAIN;
} }
if (!bt_le_conn_params_valid(param)) { if (!bt_le_conn_params_valid(conn_param)) {
return NULL; return -EINVAL;
} }
if (atomic_test_bit(bt_dev.flags, BT_DEV_EXPLICIT_SCAN)) { 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)) { if (atomic_test_bit(bt_dev.flags, BT_DEV_INITIATING)) {
return NULL; return -EALREADY;
} }
if (!bt_le_scan_random_addr_check()) { if (!bt_le_scan_random_addr_check()) {
return NULL; return -EINVAL;
} }
conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, peer); 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", BT_WARN("Found valid connection in %s state",
state2str(conn->state)); state2str(conn->state));
bt_conn_unref(conn); bt_conn_unref(conn);
return NULL; return -EINVAL;
} }
if (peer->type == BT_ADDR_LE_PUBLIC_ID || 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 */ /* Only default identity supported for now */
conn = bt_conn_add_le(BT_ID_DEFAULT, &dst); conn = bt_conn_add_le(BT_ID_DEFAULT, &dst);
if (!conn) { 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 defined(CONFIG_BT_SMP)
if (!bt_dev.le.rl_size || bt_dev.le.rl_entries > bt_dev.le.rl_size) { 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); 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_set_state(conn, BT_CONN_DISCONNECTED);
bt_conn_unref(conn); bt_conn_unref(conn);
return NULL; return err;
} }
return conn; *ret_conn = conn;
return 0;
} }
#endif #endif
bt_conn_set_state(conn, BT_CONN_CONNECT); 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; conn->err = 0;
bt_conn_set_state(conn, BT_CONN_DISCONNECTED); bt_conn_set_state(conn, BT_CONN_DISCONNECTED);
bt_conn_unref(conn); bt_conn_unref(conn);
bt_le_scan_update(false); bt_le_scan_update(false);
return NULL; return err;
} }
return conn; *ret_conn = conn;
return 0;
} }
#if !defined(CONFIG_BT_WHITELIST) #if !defined(CONFIG_BT_WHITELIST)

View file

@ -738,10 +738,10 @@ static int cmd_connect_le(const struct shell *shell, size_t argc, char *argv[])
return err; return err;
} }
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, &conn);
if (!conn) { if (err) {
shell_error(shell, "Connection failed"); shell_error(shell, "Connection failed (%d)", err);
return -ENOEXEC; return -ENOEXEC;
} else { } else {
@ -1649,7 +1649,8 @@ static int cmd_wl_connect(const struct shell *shell, size_t argc, char *argv[])
const char *action = argv[1]; const char *action = argv[1];
if (!strcmp(action, "on")) { 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) { if (err) {
shell_error(shell, "Auto connect failed (err %d)", err); shell_error(shell, "Auto connect failed (err %d)", err);

View file

@ -392,9 +392,8 @@ static int bt_connect(u32_t mgmt_request, struct net_if *iface, void *data,
L2CAP_IPSP_PSM); L2CAP_IPSP_PSM);
} }
default_conn = bt_conn_create_le(addr, BT_LE_CONN_PARAM_DEFAULT); return bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN,
BT_LE_CONN_PARAM_DEFAULT, &default_conn);
return 0;
} }
static bool eir_found(u8_t type, const u8_t *data, u8_t data_len, static bool eir_found(u8_t type, const u8_t *data, u8_t data_len,

View file

@ -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)) { for (i = 0; i < data->data_len; i += sizeof(u16_t)) {
struct bt_uuid *uuid; struct bt_uuid *uuid;
struct bt_le_conn_param *param;
u16_t u16; u16_t u16;
int err; int err;
@ -306,8 +307,13 @@ static bool eir_found(struct bt_data *data, void *user_data)
continue; continue;
} }
default_conn = bt_conn_create_le(addr, param = BT_LE_CONN_PARAM_DEFAULT;
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; return false;
} }
} }

View file

@ -506,11 +506,12 @@ static void connect(const u8_t *data, u16_t len)
{ {
struct bt_conn *conn; struct bt_conn *conn;
u8_t status; u8_t status;
int err;
conn = bt_conn_create_le((bt_addr_le_t *) data, err = bt_conn_le_create((bt_addr_le_t *) data, BT_CONN_LE_CREATE_CONN,
BT_LE_CONN_PARAM_DEFAULT); BT_LE_CONN_PARAM_DEFAULT, &conn);
if (!conn) { if (err) {
LOG_ERR("Failed to create connection"); LOG_ERR("Failed to create connection (%d)", err);
status = BTP_STATUS_FAILED; status = BTP_STATUS_FAILED;
goto rsp; goto rsp;
} }