Bluetooth: MGMT: Make MGMT_OP_LOAD_CONN_PARAM update existing connection
This makes MGMT_OP_LOAD_CONN_PARAM update existing connection by dectecting the request is just for one connection, parameters already exists and there is a connection. Since this is a new behavior the revision is also updated to enable userspace to detect it. Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
parent
ecb1e1dcb7
commit
0ece498c27
@ -138,6 +138,7 @@ int hci_suspend_sync(struct hci_dev *hdev);
|
||||
int hci_resume_sync(struct hci_dev *hdev);
|
||||
|
||||
struct hci_conn;
|
||||
struct hci_conn_params;
|
||||
|
||||
int hci_abort_conn_sync(struct hci_dev *hdev, struct hci_conn *conn, u8 reason);
|
||||
|
||||
@ -156,3 +157,5 @@ int hci_connect_acl_sync(struct hci_dev *hdev, struct hci_conn *conn);
|
||||
int hci_connect_le_sync(struct hci_dev *hdev, struct hci_conn *conn);
|
||||
|
||||
int hci_cancel_connect_sync(struct hci_dev *hdev, struct hci_conn *conn);
|
||||
int hci_le_conn_update_sync(struct hci_dev *hdev, struct hci_conn *conn,
|
||||
struct hci_conn_params *params);
|
||||
|
@ -6724,3 +6724,21 @@ int hci_cancel_connect_sync(struct hci_dev *hdev, struct hci_conn *conn)
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
int hci_le_conn_update_sync(struct hci_dev *hdev, struct hci_conn *conn,
|
||||
struct hci_conn_params *params)
|
||||
{
|
||||
struct hci_cp_le_conn_update cp;
|
||||
|
||||
memset(&cp, 0, sizeof(cp));
|
||||
cp.handle = cpu_to_le16(conn->handle);
|
||||
cp.conn_interval_min = cpu_to_le16(params->conn_min_interval);
|
||||
cp.conn_interval_max = cpu_to_le16(params->conn_max_interval);
|
||||
cp.conn_latency = cpu_to_le16(params->conn_latency);
|
||||
cp.supervision_timeout = cpu_to_le16(params->supervision_timeout);
|
||||
cp.min_ce_len = cpu_to_le16(0x0000);
|
||||
cp.max_ce_len = cpu_to_le16(0x0000);
|
||||
|
||||
return __hci_cmd_sync_status(hdev, HCI_OP_LE_CONN_UPDATE,
|
||||
sizeof(cp), &cp, HCI_CMD_TIMEOUT);
|
||||
}
|
||||
|
@ -42,7 +42,7 @@
|
||||
#include "aosp.h"
|
||||
|
||||
#define MGMT_VERSION 1
|
||||
#define MGMT_REVISION 22
|
||||
#define MGMT_REVISION 23
|
||||
|
||||
static const u16 mgmt_commands[] = {
|
||||
MGMT_OP_READ_INDEX_LIST,
|
||||
@ -7813,6 +7813,18 @@ unlock:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int conn_update_sync(struct hci_dev *hdev, void *data)
|
||||
{
|
||||
struct hci_conn_params *params = data;
|
||||
struct hci_conn *conn;
|
||||
|
||||
conn = hci_conn_hash_lookup_le(hdev, ¶ms->addr, params->addr_type);
|
||||
if (!conn)
|
||||
return -ECANCELED;
|
||||
|
||||
return hci_le_conn_update_sync(hdev, conn, params);
|
||||
}
|
||||
|
||||
static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
|
||||
u16 len)
|
||||
{
|
||||
@ -7846,13 +7858,15 @@ static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
|
||||
|
||||
hci_dev_lock(hdev);
|
||||
|
||||
hci_conn_params_clear_disabled(hdev);
|
||||
if (param_count > 1)
|
||||
hci_conn_params_clear_disabled(hdev);
|
||||
|
||||
for (i = 0; i < param_count; i++) {
|
||||
struct mgmt_conn_param *param = &cp->params[i];
|
||||
struct hci_conn_params *hci_param;
|
||||
u16 min, max, latency, timeout;
|
||||
u8 addr_type;
|
||||
bool update;
|
||||
|
||||
bt_dev_dbg(hdev, "Adding %pMR (type %u)", ¶m->addr.bdaddr,
|
||||
param->addr.type);
|
||||
@ -7879,6 +7893,19 @@ static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Detect when the loading is for an existing parameter then
|
||||
* attempt to trigger the connection update procedure.
|
||||
*/
|
||||
if (!i && param_count == 1) {
|
||||
hci_param = hci_conn_params_lookup(hdev,
|
||||
¶m->addr.bdaddr,
|
||||
addr_type);
|
||||
if (hci_param)
|
||||
update = true;
|
||||
else
|
||||
hci_conn_params_clear_disabled(hdev);
|
||||
}
|
||||
|
||||
hci_param = hci_conn_params_add(hdev, ¶m->addr.bdaddr,
|
||||
addr_type);
|
||||
if (!hci_param) {
|
||||
@ -7890,6 +7917,25 @@ static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
|
||||
hci_param->conn_max_interval = max;
|
||||
hci_param->conn_latency = latency;
|
||||
hci_param->supervision_timeout = timeout;
|
||||
|
||||
/* Check if we need to trigger a connection update */
|
||||
if (update) {
|
||||
struct hci_conn *conn;
|
||||
|
||||
/* Lookup for existing connection as central and check
|
||||
* if parameters match and if they don't then trigger
|
||||
* a connection update.
|
||||
*/
|
||||
conn = hci_conn_hash_lookup_le(hdev, &hci_param->addr,
|
||||
addr_type);
|
||||
if (conn && conn->role == HCI_ROLE_MASTER &&
|
||||
(conn->le_conn_min_interval != min ||
|
||||
conn->le_conn_max_interval != max ||
|
||||
conn->le_conn_latency != latency ||
|
||||
conn->le_supv_timeout != timeout))
|
||||
hci_cmd_sync_queue(hdev, conn_update_sync,
|
||||
hci_param, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
hci_dev_unlock(hdev);
|
||||
|
Loading…
Reference in New Issue
Block a user