Commit 0ece498c authored by Luiz Augusto von Dentz's avatar Luiz Augusto von Dentz
Browse files

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: default avatarLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
parent ecb1e1dc
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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);
+18 −0
Original line number Diff line number Diff line
@@ -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);
}
+48 −2
Original line number Diff line number Diff line
@@ -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 @@ static int remove_device(struct sock *sk, struct hci_dev *hdev,
	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, &params->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,6 +7858,7 @@ static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,

	hci_dev_lock(hdev);

	if (param_count > 1)
		hci_conn_params_clear_disabled(hdev);

	for (i = 0; i < param_count; i++) {
@@ -7853,6 +7866,7 @@ static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
		struct hci_conn_params *hci_param;
		u16 min, max, latency, timeout;
		u8 addr_type;
		bool update;

		bt_dev_dbg(hdev, "Adding %pMR (type %u)", &param->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,
							   &param->addr.bdaddr,
							   addr_type);
			if (hci_param)
				update = true;
			else
				hci_conn_params_clear_disabled(hdev);
		}

		hci_param = hci_conn_params_add(hdev, &param->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);