Bluetooth: Introduce a new connection parameter request callback
Introduce a new callback to bt_conn_cb that allows the application to decide whether the accept or reject an incoming connection parameter request. If the request is accepted the callback allows the application to also adjust the values to what it thinks are more appropriate. The Zephyr Bluetooth API allows multiple registered connection callbacks, so in principle there may be multiple le_param_req() callbacks. It's recommended for an app to just use one (for clarity), but if there are multiple the app is responsible for managing potentially different requirements. In the case of multiple callbacks each callback will receive the modified parameters in case a previous callback modified them. Jira: ZEP-1474 Change-Id: I098db5791aac521f1edfa9fefdf847db0a27e3a5 Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
This commit is contained in:
parent
68732ef9d5
commit
1adc58fd79
5 changed files with 67 additions and 10 deletions
|
@ -318,6 +318,30 @@ struct bt_conn_cb {
|
|||
*/
|
||||
void (*disconnected)(struct bt_conn *conn, uint8_t reason);
|
||||
|
||||
/** @brief LE connection parameter update request.
|
||||
*
|
||||
* This callback notifies the application that a remote device
|
||||
* is requesting to update the connection parameters. The
|
||||
* application accepts the parameters by returning true, or
|
||||
* rejects them by returning false. Before accepting, the
|
||||
* application may also adjust the parameters to better suit
|
||||
* its needs.
|
||||
*
|
||||
* It is recommended for an application to have just one of these
|
||||
* callbacks for simplicity. However, if an application registers
|
||||
* multiple it needs to manage the potentially different
|
||||
* requirements for each callback. Each callback gets the
|
||||
* parameters as returned by previous callbacks, i.e. they are not
|
||||
* necessarily the same ones as the remote originally sent.
|
||||
*
|
||||
* @param conn Connection object.
|
||||
* @param param Proposed connection parameters.
|
||||
*
|
||||
* @return true to accept the parameters, or false to reject them.
|
||||
*/
|
||||
bool (*le_param_req)(struct bt_conn *conn,
|
||||
struct bt_le_conn_param *param);
|
||||
|
||||
/** @brief The parameters for an LE connection have been updated.
|
||||
*
|
||||
* This callback notifies the application that the connection
|
||||
|
|
|
@ -130,6 +130,35 @@ void notify_le_param_updated(struct bt_conn *conn)
|
|||
}
|
||||
}
|
||||
|
||||
bool le_param_req(struct bt_conn *conn, struct bt_le_conn_param *param)
|
||||
{
|
||||
struct bt_conn_cb *cb;
|
||||
|
||||
if (!bt_le_conn_params_valid(param)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (cb = callback_list; cb; cb = cb->_next) {
|
||||
if (!cb->le_param_req) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!cb->le_param_req(conn, param)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* The callback may modify the parameters so we need to
|
||||
* double-check that it returned valid parameters.
|
||||
*/
|
||||
if (!bt_le_conn_params_valid(param)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Default to accepting if there's no app callback */
|
||||
return true;
|
||||
}
|
||||
|
||||
static void le_conn_update(struct k_work *work)
|
||||
{
|
||||
struct bt_conn_le *le = CONTAINER_OF(work, struct bt_conn_le,
|
||||
|
|
|
@ -167,6 +167,8 @@ int bt_conn_le_conn_update(struct bt_conn *conn,
|
|||
|
||||
void notify_le_param_updated(struct bt_conn *conn);
|
||||
|
||||
bool le_param_req(struct bt_conn *conn, struct bt_le_conn_param *param);
|
||||
|
||||
#if defined(CONFIG_BLUETOOTH_SMP)
|
||||
/* rand and ediv should be in BT order */
|
||||
int bt_conn_le_start_encryption(struct bt_conn *conn, uint64_t rand,
|
||||
|
|
|
@ -853,6 +853,7 @@ static int le_conn_param_req(struct net_buf *buf)
|
|||
struct bt_le_conn_param param;
|
||||
struct bt_conn *conn;
|
||||
uint16_t handle;
|
||||
int err;
|
||||
|
||||
handle = sys_le16_to_cpu(evt->handle);
|
||||
param.interval_min = sys_le16_to_cpu(evt->interval_min);
|
||||
|
@ -867,14 +868,15 @@ static int le_conn_param_req(struct net_buf *buf)
|
|||
BT_HCI_ERR_UNKNOWN_CONN_ID);
|
||||
}
|
||||
|
||||
bt_conn_unref(conn);
|
||||
|
||||
if (!bt_le_conn_params_valid(¶m)) {
|
||||
return le_conn_param_neg_reply(handle,
|
||||
BT_HCI_ERR_INVALID_LL_PARAMS);
|
||||
if (!le_param_req(conn, ¶m)) {
|
||||
err = le_conn_param_neg_reply(handle,
|
||||
BT_HCI_ERR_INVALID_LL_PARAMS);
|
||||
} else {
|
||||
err = le_conn_param_req_reply(handle, ¶m);
|
||||
}
|
||||
|
||||
return le_conn_param_req_reply(handle, ¶m);
|
||||
bt_conn_unref(conn);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void le_conn_update_complete(struct net_buf *buf)
|
||||
|
|
|
@ -554,9 +554,9 @@ static void le_conn_param_update_req(struct bt_l2cap *l2cap, uint8_t ident,
|
|||
{
|
||||
struct bt_conn *conn = l2cap->chan.chan.conn;
|
||||
struct bt_le_conn_param param;
|
||||
bool params_valid;
|
||||
struct bt_l2cap_conn_param_rsp *rsp;
|
||||
struct bt_l2cap_conn_param_req *req = (void *)buf->data;
|
||||
bool accepted;
|
||||
|
||||
if (buf->len < sizeof(*req)) {
|
||||
BT_ERR("Too small LE conn update param req");
|
||||
|
@ -584,10 +584,10 @@ static void le_conn_param_update_req(struct bt_l2cap *l2cap, uint8_t ident,
|
|||
return;
|
||||
}
|
||||
|
||||
params_valid = bt_le_conn_params_valid(¶m);
|
||||
accepted = le_param_req(conn, ¶m);
|
||||
|
||||
rsp = net_buf_add(buf, sizeof(*rsp));
|
||||
if (params_valid) {
|
||||
if (accepted) {
|
||||
rsp->result = sys_cpu_to_le16(BT_L2CAP_CONN_PARAM_ACCEPTED);
|
||||
} else {
|
||||
rsp->result = sys_cpu_to_le16(BT_L2CAP_CONN_PARAM_REJECTED);
|
||||
|
@ -595,7 +595,7 @@ static void le_conn_param_update_req(struct bt_l2cap *l2cap, uint8_t ident,
|
|||
|
||||
bt_l2cap_send(conn, BT_L2CAP_CID_LE_SIG, buf);
|
||||
|
||||
if (params_valid) {
|
||||
if (accepted) {
|
||||
bt_conn_le_conn_update(conn, ¶m);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue