Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1622982 > unrolled thread

[PATCH v5 BlueZ 0/4] Connection Update improvements

Started by"Felipe F. Tonello" <eu@felipetonello.com>
First post2017-04-13 14:30 +0200
Last post2017-04-13 14:30 +0200
Articles 2 — 1 participant

Back to article view | Back to linux.kernel


Contents

  [PATCH v5 BlueZ 0/4] Connection Update improvements "Felipe F. Tonello" <eu@felipetonello.com> - 2017-04-13 14:30 +0200
    [PATCH v5 BlueZ 3/4] Bluetooth: L2CAP: Add BT_LE_CONN_PARAM socket option "Felipe F. Tonello" <eu@felipetonello.com> - 2017-04-13 14:30 +0200

#1622982 — [PATCH v5 BlueZ 0/4] Connection Update improvements

From"Felipe F. Tonello" <eu@felipetonello.com>
Date2017-04-13 14:30 +0200
Subject[PATCH v5 BlueZ 0/4] Connection Update improvements
Message-ID<tvM2R-2Wl-5@gated-at.bofh.it>
These changes implements compliant Bluetooth support for any possible way to
update a connection parameter. Missing functionality is required to be
implemented in user-space, which this patchset allows it.

Changes from v4:
 * Handle Slave Connection Interval Range AD in kernel instead of
   user-space
 * Removed new MGMT command, it is unnecessary since it was only supposed
   to be used for the Slave Connection Interval Range support, which now
   has been implemented in the kernel.

Changes from v3:
 * Remove role check in refactored function
 * Added handler for Connection Parameter Update Response
 * Use Update Request when updating the connection parameters in slave
 * Fix MGMT command name to ADD instead of UPDATE

Changes from v2:
 * Added new MGMT command
 * Roll back to first socket option implementation, details are on the
   patch iself.

Changes from v1:
 * Use simpler user-space API
 * Added refactor function

Felipe F. Tonello (4):
  Bluetooth: L2CAP: Refactor L2CAP_CONN_PARAM_UPDATE_REQ into a function
  Bluetooth: L2CAP: Add handler for Connection Parameter Update Response
  Bluetooth: L2CAP: Add BT_LE_CONN_PARAM socket option
  Bluetooth: Handle Slave Connection Interval Range AD

 include/net/bluetooth/bluetooth.h |   8 +++
 include/net/bluetooth/l2cap.h     |   5 ++
 net/bluetooth/l2cap_core.c        |  78 +++++++++++++++++++++++----
 net/bluetooth/l2cap_sock.c        | 110 ++++++++++++++++++++++++++++++++++++++
 net/bluetooth/mgmt.c              |  53 ++++++++++++++++++
 5 files changed, 243 insertions(+), 11 deletions(-)

-- 
2.12.2

[toc] | [next] | [standalone]


#1622985 — [PATCH v5 BlueZ 3/4] Bluetooth: L2CAP: Add BT_LE_CONN_PARAM socket option

From"Felipe F. Tonello" <eu@felipetonello.com>
Date2017-04-13 14:30 +0200
Subject[PATCH v5 BlueZ 3/4] Bluetooth: L2CAP: Add BT_LE_CONN_PARAM socket option
Message-ID<tvM2R-2Wl-19@gated-at.bofh.it>
In reply to#1622982
There is a need for certain LE profiles (MIDI for example) to change the
current connection's parameters. In order to do that, this patch
introduces a new BT_LE_CONN_PARAM socket option for SOL_BLUETOOTH
protocol which allow user-space l2cap sockets to update the current
connection.

It necessary to expose all the connection parameters to user-space
because user-space are exposed to those values anyway, via PPCP
characteristic or particular profile specification.

If ROLE is SLAVE, then it will send a L2CAP_CONN_PARAM_UPDATE_REQ
signaling command to the MASTER, triggering proper LE parameter update
procedure. The connection parameters update will only occur upon a
successful L2CAP_CONN_PARAM_UPDATE_RSP sent by the MASTER.

If ROLE is MASTER, then immediately update the connection parameters.

Once the connection parameters are effective, a MGMT_EV_NEW_CONN_PARAM
event with the store_hint set is sent to user-space so an application
can store the connection parameters for persistence reasons.

Signed-off-by: Felipe F. Tonello <eu@felipetonello.com>
---
 include/net/bluetooth/bluetooth.h |   8 +++
 net/bluetooth/l2cap_sock.c        | 110 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 118 insertions(+)

diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index 01487192f628..ce5b3abd3b27 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -122,6 +122,14 @@ struct bt_voice {
 #define BT_SNDMTU		12
 #define BT_RCVMTU		13
 
+#define BT_LE_CONN_PARAM	14
+struct bt_le_conn_param {
+	__u16 min_interval;
+	__u16 max_interval;
+	__u16 latency;
+	__u16 supervision_timeout;
+};
+
 __printf(1, 2)
 void bt_info(const char *fmt, ...);
 __printf(1, 2)
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 507b80d59dec..1e096bd9ddde 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -515,6 +515,47 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname,
 	lock_sock(sk);
 
 	switch (optname) {
+	case BT_LE_CONN_PARAM: {
+		struct bt_le_conn_param conn_param;
+		struct hci_conn_params *params;
+		struct hci_conn *hcon;
+		struct hci_dev *hdev;
+
+		if (!chan->conn) {
+			err = -ENOTCONN;
+			break;
+		}
+
+		hcon = chan->conn->hcon;
+		hdev = hcon->hdev;
+		hci_dev_lock(hdev);
+
+		params = hci_conn_params_lookup(hdev, &hcon->dst,
+						hcon->dst_type);
+
+		memset(&conn_param, 0, sizeof(conn_param));
+
+		if (params) {
+			conn_param.min_interval = params->conn_min_interval;
+			conn_param.max_interval = params->conn_max_interval;
+			conn_param.latency = params->conn_latency;
+			conn_param.supervision_timeout =
+				params->supervision_timeout;
+		} else {
+			conn_param.min_interval = hdev->le_conn_min_interval;
+			conn_param.max_interval = hdev->le_conn_max_interval;
+			conn_param.latency = hdev->le_conn_latency;
+			conn_param.supervision_timeout = hdev->le_supv_timeout;
+		}
+
+		hci_dev_unlock(hdev);
+
+		len = min_t(unsigned int, len, sizeof(conn_param));
+		if (copy_to_user(optval, (char *)&conn_param, len))
+			err = -EFAULT;
+
+		break;
+	}
 	case BT_SECURITY:
 		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED &&
 		    chan->chan_type != L2CAP_CHAN_FIXED &&
@@ -762,6 +803,75 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
 	lock_sock(sk);
 
 	switch (optname) {
+	case BT_LE_CONN_PARAM: {
+		struct bt_le_conn_param conn_param;
+		struct hci_conn_params *hci_param;
+		struct hci_conn *hcon;
+		struct hci_dev *hdev;
+
+		len = min_t(unsigned int, sizeof(conn_param), optlen);
+		if (copy_from_user((char *)&conn_param, optval, len)) {
+			err = -EFAULT;
+			break;
+		}
+
+		if (!chan->conn) {
+			err = -ENOTCONN;
+			break;
+		}
+
+		err = hci_check_conn_params(conn_param.min_interval,
+					    conn_param.max_interval,
+					    conn_param.latency,
+					    conn_param.supervision_timeout);
+		if (err < 0) {
+			BT_ERR("Ignoring invalid connection parameters");
+			break;
+		}
+
+		hcon = chan->conn->hcon;
+		hdev = hcon->hdev;
+
+		hci_dev_lock(hdev);
+
+		/* we add new param in case it doesn't exist */
+		hci_param = hci_conn_params_add(hdev, &hcon->dst,
+						hcon->dst_type);
+		if (!hci_param) {
+			err = -ENOMEM;
+			BT_ERR("Failed to add connection parameters");
+			hci_dev_unlock(hcon->hdev);
+			break;
+		}
+
+		hci_dev_unlock(hdev);
+
+		/* Send a L2CAP connection parameters update request, if
+		 * the host role is slave.
+		 */
+		if (hcon->role == HCI_ROLE_SLAVE) {
+			l2cap_le_conn_update_req(chan->conn,
+						 conn_param.min_interval,
+						 conn_param.max_interval,
+						 conn_param.latency,
+						 conn_param.supervision_timeout);
+		} else {
+			/* this function also updates the hci_param value */
+			hci_le_conn_update(hcon, conn_param.min_interval,
+					   conn_param.max_interval,
+					   conn_param.latency,
+					   conn_param.supervision_timeout);
+
+			/* don't set the `store' hint */
+			mgmt_new_conn_param(hdev, &hcon->dst, hcon->dst_type,
+					    false, conn_param.min_interval,
+					    conn_param.max_interval,
+					    conn_param.latency,
+					    conn_param.supervision_timeout);
+		}
+		break;
+	}
+
 	case BT_SECURITY:
 		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED &&
 		    chan->chan_type != L2CAP_CHAN_FIXED &&
-- 
2.12.2

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web