Bluetooth: Add delay before sending Connection Update
BLUETOOTH SPECIFICATION Version 4.2 [Vol 3, Part C] page 368: "The Peripheral device should not perform a Connection Parameter Update procedure within T GAP (conn_pause_peripheral) after establishing a connection." > HCI Event: LE Meta Event (0x3e) plen 19 [hci1] 11:14:22.496358 LE Connection Complete (0x01) Status: Success (0x00) Handle: 74 Role: Slave (0x01) Peer address type: Public (0x00) Peer address: 7C:7A:91:18:82:46 (Intel Corporate) Connection interval: 70.00 msec (0x0038) Connection latency: 0.00 msec (0x0000) Supervision timeout: 420 msec (0x002a) Master clock accuracy: 0x01 ...[5 seconds interval]... < ACL Data TX: Handle 74 flags 0x00 dlen 16 [hci1] 11:14:27.493541 LE L2CAP: Connection Parameter Update Request (0x12) ident 1 len 8 Min interval: 24 Max interval: 40 Slave latency: 0 Timeout multiplier: 42 Change-Id: Ibb301ea00c127542ba299ad0b94825ad1ed05c5c Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
parent
372a8905d5
commit
562b491182
3 changed files with 41 additions and 10 deletions
|
@ -136,6 +136,21 @@ void notify_le_param_updated(struct bt_conn *conn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void le_conn_update(struct nano_work *work)
|
||||||
|
{
|
||||||
|
struct bt_conn_le *le = CONTAINER_OF(work, struct bt_conn_le,
|
||||||
|
update_work);
|
||||||
|
struct bt_conn *conn = CONTAINER_OF(le, struct bt_conn, le);
|
||||||
|
const struct bt_le_conn_param *param;
|
||||||
|
|
||||||
|
param = BT_LE_CONN_PARAM(conn->le.interval_min,
|
||||||
|
conn->le.interval_max,
|
||||||
|
conn->le.latency,
|
||||||
|
conn->le.timeout);
|
||||||
|
|
||||||
|
bt_conn_le_param_update(conn, param);
|
||||||
|
}
|
||||||
|
|
||||||
static struct bt_conn *conn_new(void)
|
static struct bt_conn *conn_new(void)
|
||||||
{
|
{
|
||||||
struct bt_conn *conn = NULL;
|
struct bt_conn *conn = NULL;
|
||||||
|
@ -1005,6 +1020,7 @@ struct bt_conn *bt_conn_add_le(const bt_addr_le_t *peer)
|
||||||
conn->type = BT_CONN_TYPE_LE;
|
conn->type = BT_CONN_TYPE_LE;
|
||||||
conn->le.interval_min = BT_GAP_INIT_CONN_INT_MIN;
|
conn->le.interval_min = BT_GAP_INIT_CONN_INT_MIN;
|
||||||
conn->le.interval_max = BT_GAP_INIT_CONN_INT_MAX;
|
conn->le.interval_max = BT_GAP_INIT_CONN_INT_MAX;
|
||||||
|
nano_delayed_work_init(&conn->le.update_work, le_conn_update);
|
||||||
|
|
||||||
return conn;
|
return conn;
|
||||||
}
|
}
|
||||||
|
@ -1086,6 +1102,10 @@ void bt_conn_set_state(struct bt_conn *conn, bt_conn_state_t state)
|
||||||
notify_connected(conn);
|
notify_connected(conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Cancel Connection Update if it is pending */
|
||||||
|
if (conn->type == BT_CONN_TYPE_LE)
|
||||||
|
nano_delayed_work_cancel(&conn->le.update_work);
|
||||||
|
|
||||||
/* Release the reference we took for the very first
|
/* Release the reference we took for the very first
|
||||||
* state transition.
|
* state transition.
|
||||||
*/
|
*/
|
||||||
|
@ -1289,6 +1309,9 @@ int bt_conn_le_param_update(struct bt_conn *conn,
|
||||||
return -EALREADY;
|
return -EALREADY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Cancel any pending update */
|
||||||
|
nano_delayed_work_cancel(&conn->le.update_work);
|
||||||
|
|
||||||
if ((conn->role == BT_HCI_ROLE_SLAVE) &&
|
if ((conn->role == BT_HCI_ROLE_SLAVE) &&
|
||||||
!(bt_dev.le.features[0] & BT_HCI_LE_CONN_PARAM_REQ_PROC)) {
|
!(bt_dev.le.features[0] & BT_HCI_LE_CONN_PARAM_REQ_PROC)) {
|
||||||
return bt_l2cap_update_conn_param(conn, param);
|
return bt_l2cap_update_conn_param(conn, param);
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015-2016 Intel Corporation
|
* Copyright (c) 2015 Intel Corporation
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -17,6 +17,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
#include <misc/nano_work.h>
|
||||||
|
|
||||||
typedef enum __packed {
|
typedef enum __packed {
|
||||||
BT_CONN_DISCONNECTED,
|
BT_CONN_DISCONNECTED,
|
||||||
|
@ -50,6 +51,9 @@ struct bt_conn_le {
|
||||||
uint16_t timeout;
|
uint16_t timeout;
|
||||||
|
|
||||||
uint8_t features[8];
|
uint8_t features[8];
|
||||||
|
|
||||||
|
/* Delayed work for connection update handling */
|
||||||
|
struct nano_delayed_work update_work;
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(CONFIG_BLUETOOTH_BREDR)
|
#if defined(CONFIG_BLUETOOTH_BREDR)
|
||||||
|
@ -135,7 +139,7 @@ void bt_conn_ssp_auth(struct bt_conn *conn, uint32_t passkey);
|
||||||
/* Look up an existing connection */
|
/* Look up an existing connection */
|
||||||
struct bt_conn *bt_conn_lookup_handle(uint16_t handle);
|
struct bt_conn *bt_conn_lookup_handle(uint16_t handle);
|
||||||
|
|
||||||
/* Look up a connection state. For NULL peer, returns the first connection
|
/* Look up a connection state. For BT_ADDR_LE_ANY, returns the first connection
|
||||||
* with the specific state
|
* with the specific state
|
||||||
*/
|
*/
|
||||||
struct bt_conn *bt_conn_lookup_state_le(const bt_addr_le_t *peer,
|
struct bt_conn *bt_conn_lookup_state_le(const bt_addr_le_t *peer,
|
||||||
|
|
|
@ -58,6 +58,9 @@
|
||||||
#define BT_DBG(fmt, ...)
|
#define BT_DBG(fmt, ...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Peripheral timeout to initialize Connection Parameter Update procedure */
|
||||||
|
#define CONN_UPDATE_TIMEOUT (5 * sys_clock_ticks_per_sec)
|
||||||
|
|
||||||
/* Stacks for the fibers */
|
/* Stacks for the fibers */
|
||||||
static BT_STACK_NOINIT(rx_fiber_stack, CONFIG_BLUETOOTH_RX_STACK_SIZE);
|
static BT_STACK_NOINIT(rx_fiber_stack, CONFIG_BLUETOOTH_RX_STACK_SIZE);
|
||||||
static BT_STACK_NOINIT(cmd_tx_fiber_stack, 256);
|
static BT_STACK_NOINIT(cmd_tx_fiber_stack, 256);
|
||||||
|
@ -590,15 +593,16 @@ static int hci_le_read_remote_features(struct bt_conn *conn)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int update_conn_param(struct bt_conn *conn)
|
static void update_conn_param(struct bt_conn *conn)
|
||||||
{
|
{
|
||||||
const struct bt_le_conn_param *param;
|
/*
|
||||||
|
* Core 4.2 Vol 3, Part C, 9.3.12.2
|
||||||
param = BT_LE_CONN_PARAM(conn->le.interval_min,
|
* The Peripheral device should not perform a Connection Parameter
|
||||||
conn->le.interval_max,
|
* Update procedure within 5 s after establishing a connection.
|
||||||
conn->le.latency,
|
*/
|
||||||
conn->le.timeout);
|
nano_delayed_work_submit(&conn->le.update_work,
|
||||||
return bt_conn_le_param_update(conn, param);
|
conn->role == BT_HCI_ROLE_MASTER ? TICKS_NONE :
|
||||||
|
CONN_UPDATE_TIMEOUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void le_conn_complete(struct net_buf *buf)
|
static void le_conn_complete(struct net_buf *buf)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue