From 9533fbcfe13918ca8e30d60255efa03ef4b6c522 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sat, 5 Dec 2015 21:39:44 +0200 Subject: [PATCH] Bluetooth: Add latency & timeout to LE conn param API Change-Id: Icd6122b9056dd686d70a2d213a18dcab34f5e80a Signed-off-by: Johan Hedberg --- include/bluetooth/bluetooth.h | 58 ++++++++++++++++++++++------------- include/bluetooth/conn.h | 29 +++++++++++++++--- net/bluetooth/conn.c | 6 ++-- net/bluetooth/conn_internal.h | 6 ++++ net/bluetooth/hci_core.c | 21 ++++++++++--- net/bluetooth/l2cap.c | 4 +-- 6 files changed, 87 insertions(+), 37 deletions(-) diff --git a/include/bluetooth/bluetooth.h b/include/bluetooth/bluetooth.h index 0917fdc0099..ad5bbd910c0 100644 --- a/include/bluetooth/bluetooth.h +++ b/include/bluetooth/bluetooth.h @@ -99,33 +99,47 @@ typedef void bt_le_scan_cb_t(const bt_addr_le_t *addr, int8_t rssi, uint8_t adv_type, const uint8_t *adv_data, uint8_t len); +/** LE scan parameters */ +struct bt_le_scan_param { + /** Scan type (BT_HCI_LE_SCAN_ACTIVE or BT_HCI_LE_SCAN_PASSIVE) */ + uint8_t type; + + /** Duplicate filtering (BT_HCI_LE_SCAN_FILTER_DUP_ENABLE or + * BT_HCI_LE_SCAN_FILTER_DUP_DISABLE) + */ + uint8_t filter_dup; + + /** Scan interval (N * 0.625 ms) */ + uint16_t interval; + + /** Scan window (N * 0.625 ms) */ + uint16_t window; +}; + +/** Helper to declare scan parameters inline + * + * @param _type Scan Type (BT_HCI_LE_SCAN_ACTIVE/BT_HCI_LE_SCAN_PASSIVE) + * @param _filter Filter Duplicates + * @param _interval Scan Interval (N * 0.625 ms) + * @param _window Scan Window (N * 0.625 ms) + */ +#define BT_LE_SCAN_PARAM(_type, _filter, _interval, _window) \ + (&(struct bt_le_scan_param) { \ + .type = (_type), \ + .filter_dup = (_filter), \ + .interval = (_interval), \ + .window = (_window), \ + }) + /** Helper macro to enable active scanning to discover new devices. * * The interval and window are intentionally set to the same value to * perform continuous scanning. */ -#define BT_LE_SCAN_ACTIVE \ - (&(struct bt_le_scan_param) { \ - .type = BT_HCI_LE_SCAN_ACTIVE, \ - .filter_dup = BT_HCI_LE_SCAN_FILTER_DUP_ENABLE, \ - .interval = BT_GAP_SCAN_FAST_INTERVAL, \ - .window = BT_GAP_SCAN_FAST_INTERVAL, \ - }) - -/** LE scan parameters */ -struct bt_le_scan_param { - /** Type of scanning (active/passive) */ - uint8_t type; - - /** Enable duplicate filtering */ - uint8_t filter_dup; - - /** Scan interval */ - uint16_t interval; - - /** Scan window */ - uint16_t window; -}; +#define BT_LE_SCAN_ACTIVE BT_LE_SCAN_PARAM(BT_HCI_LE_SCAN_ACTIVE, \ + BT_HCI_LE_SCAN_FILTER_DUP_ENABLE, \ + BT_GAP_SCAN_FAST_INTERVAL, \ + BT_GAP_SCAN_FAST_INTERVAL) /** @brief Start (LE) scanning * diff --git a/include/bluetooth/conn.h b/include/bluetooth/conn.h index 013a23288e3..33875d3524f 100644 --- a/include/bluetooth/conn.h +++ b/include/bluetooth/conn.h @@ -32,12 +32,33 @@ struct bt_conn; struct bt_le_conn_param { uint16_t interval_min; uint16_t interval_max; + uint16_t latency; + uint16_t timeout; }; -#define BT_LE_CONN_PARAM_DEFAULT (&(struct bt_le_conn_param) { \ - .interval_min = BT_GAP_INIT_CONN_INT_MIN, \ - .interval_max = BT_GAP_INIT_CONN_INT_MAX, \ - }) +/** Helper to declare connection parameters inline + * + * @param int_min Minimum Connection Interval (N * 1.25 ms) + * @param int_max Maximum Connection Interval (N * 1.25 ms) + * @param lat Connection Latency + * @param timeout Supervision Timeout (N * 10 ms) + */ +#define BT_LE_CONN_PARAM(int_min, int_max, lat, to) \ + (&(struct bt_le_conn_param) { \ + .interval_min = (int_min), \ + .interval_max = (int_max), \ + .latency = (lat), \ + .timeout = (to), \ + }) + +/** Default LE connection parameters: + * Connection Interval: 30-50 ms + * Latency: 0 + * Timeout: 4 s + */ +#define BT_LE_CONN_PARAM_DEFAULT BT_LE_CONN_PARAM(BT_GAP_INIT_CONN_INT_MIN, \ + BT_GAP_INIT_CONN_INT_MAX, \ + 0, 400) /** @brief Increment a connection's reference count. * diff --git a/net/bluetooth/conn.c b/net/bluetooth/conn.c index be3b4248d27..e848c65411e 100644 --- a/net/bluetooth/conn.c +++ b/net/bluetooth/conn.c @@ -839,8 +839,7 @@ struct bt_conn *bt_conn_create_le(const bt_addr_le_t *peer, if (conn) { switch (conn->state) { case BT_CONN_CONNECT_SCAN: - conn->le.interval_min = param->interval_min; - conn->le.interval_max = param->interval_max; + bt_conn_set_param_le(conn, param); return conn; case BT_CONN_CONNECT: case BT_CONN_CONNECTED: @@ -856,8 +855,7 @@ struct bt_conn *bt_conn_create_le(const bt_addr_le_t *peer, return NULL; } - conn->le.interval_min = param->interval_min; - conn->le.interval_max = param->interval_max; + bt_conn_set_param_le(conn, param); bt_conn_set_state(conn, BT_CONN_CONNECT_SCAN); diff --git a/net/bluetooth/conn_internal.h b/net/bluetooth/conn_internal.h index ba1082c219d..86cc4d22101 100644 --- a/net/bluetooth/conn_internal.h +++ b/net/bluetooth/conn_internal.h @@ -42,6 +42,9 @@ struct bt_conn_le { uint16_t interval_min; uint16_t interval_max; + uint16_t latency; + uint16_t timeout; + uint8_t features[8]; }; @@ -123,6 +126,9 @@ struct bt_conn *bt_conn_lookup_state(const bt_addr_le_t *peer, /* Set connection object in certain state and perform action related to state */ void bt_conn_set_state(struct bt_conn *conn, bt_conn_state_t state); +void bt_conn_set_param_le(struct bt_conn *conn, + const struct bt_le_conn_param *param); + int bt_conn_le_conn_update(struct bt_conn *conn, uint16_t min, uint16_t max, uint16_t latency, uint16_t timeout); diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index f33f19c16a8..7918304e0df 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -412,7 +412,8 @@ static int hci_le_create_conn(const struct bt_conn *conn) bt_addr_le_copy(&cp->peer_addr, &conn->le.resp_addr); cp->conn_interval_min = sys_cpu_to_le16(conn->le.interval_min); cp->conn_interval_max = sys_cpu_to_le16(conn->le.interval_max); - cp->supervision_timeout = sys_cpu_to_le16(0x07D0); + cp->conn_latency = sys_cpu_to_le16(conn->le.latency); + cp->supervision_timeout = sys_cpu_to_le16(conn->le.timeout); return bt_hci_cmd_send_sync(BT_HCI_OP_LE_CREATE_CONN, buf, NULL); } @@ -503,8 +504,8 @@ static int update_conn_params(struct bt_conn *conn) (bt_dev.le.features[0] & BT_HCI_LE_CONN_PARAM_REQ_PROC)) { return bt_conn_le_conn_update(conn, conn->le.interval_min, conn->le.interval_max, - LE_CONN_LATENCY, - LE_CONN_TIMEOUT); + conn->le.latency, + conn->le.timeout); } return -EBUSY; @@ -557,6 +558,8 @@ static void le_conn_complete(struct net_buf *buf) conn->handle = handle; bt_addr_le_copy(&conn->le.dst, id_addr); conn->le.interval = sys_le16_to_cpu(evt->interval); + conn->le.latency = sys_le16_to_cpu(evt->latency); + conn->le.timeout = sys_le16_to_cpu(evt->supv_timeout); conn->role = evt->role; src.type = BT_ADDR_LE_PUBLIC; @@ -777,6 +780,15 @@ static int set_flow_control(void) *enable = 0x01; return bt_hci_cmd_send_sync(BT_HCI_OP_SET_CTL_TO_HOST_FLOW, buf, NULL); } + +void bt_conn_set_param_le(struct bt_conn *conn, + const struct bt_le_conn_param *param) +{ + conn->le.interval_min = param->interval_min; + conn->le.interval_max = param->interval_max; + conn->le.latency = param->latency; + conn->le.timeout = param->timeout; +} #endif /* CONFIG_BLUETOOTH_CONN */ #if defined(CONFIG_BLUETOOTH_SMP) @@ -1231,8 +1243,7 @@ int bt_le_set_auto_conn(bt_addr_le_t *addr, } if (param) { - conn->le.interval_min = param->interval_min; - conn->le.interval_max = param->interval_max; + bt_conn_set_param_le(conn, param); if (!atomic_test_and_set_bit(conn->flags, BT_CONN_AUTO_CONNECT)) { diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 1bd89b5f0d0..85e24773a48 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -976,8 +976,8 @@ int bt_l2cap_update_conn_param(struct bt_conn *conn) req = net_buf_add(buf, sizeof(*req)); req->min_interval = sys_cpu_to_le16(conn->le.interval_min); req->max_interval = sys_cpu_to_le16(conn->le.interval_max); - req->latency = sys_cpu_to_le16(LE_CONN_LATENCY); - req->timeout = sys_cpu_to_le16(LE_CONN_TIMEOUT); + req->latency = sys_cpu_to_le16(conn->le.latency); + req->timeout = sys_cpu_to_le16(conn->le.timeout); bt_l2cap_send(conn, BT_L2CAP_CID_LE_SIG, buf);