浏览代码

Bluetooth: Send LE Connection Update Command

If the new connection update parameter are accepted, the LE master
host sends the LE Connection Update Command to its controller informing
the new requested parameters.

Signed-off-by: Claudio Takahasi <claudio.takahasi@openbossa.org>
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Claudio Takahasi 14 年之前
父节点
当前提交
2ce603ebe1
共有 4 个文件被更改,包括 40 次插入1 次删除
  1. 11 0
      include/net/bluetooth/hci.h
  2. 2 0
      include/net/bluetooth/hci_core.h
  3. 20 0
      net/bluetooth/hci_conn.c
  4. 7 1
      net/bluetooth/l2cap_core.c

+ 11 - 0
include/net/bluetooth/hci.h

@@ -677,6 +677,17 @@ struct hci_cp_le_create_conn {
 
 
 #define HCI_OP_LE_CREATE_CONN_CANCEL	0x200e
 #define HCI_OP_LE_CREATE_CONN_CANCEL	0x200e
 
 
+#define HCI_OP_LE_CONN_UPDATE		0x2013
+struct hci_cp_le_conn_update {
+	__le16   handle;
+	__le16   conn_interval_min;
+	__le16   conn_interval_max;
+	__le16   conn_latency;
+	__le16   supervision_timeout;
+	__le16   min_ce_len;
+	__le16   max_ce_len;
+} __packed;
+
 /* ---- HCI Events ---- */
 /* ---- HCI Events ---- */
 #define HCI_EV_INQUIRY_COMPLETE		0x01
 #define HCI_EV_INQUIRY_COMPLETE		0x01
 
 

+ 2 - 0
include/net/bluetooth/hci_core.h

@@ -777,4 +777,6 @@ struct hci_sec_filter {
 
 
 void hci_req_complete(struct hci_dev *hdev, __u16 cmd, int result);
 void hci_req_complete(struct hci_dev *hdev, __u16 cmd, int result);
 
 
+void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max,
+					u16 latency, u16 to_multiplier);
 #endif /* __HCI_CORE_H */
 #endif /* __HCI_CORE_H */

+ 20 - 0
net/bluetooth/hci_conn.c

@@ -183,6 +183,26 @@ void hci_setup_sync(struct hci_conn *conn, __u16 handle)
 	hci_send_cmd(hdev, HCI_OP_SETUP_SYNC_CONN, sizeof(cp), &cp);
 	hci_send_cmd(hdev, HCI_OP_SETUP_SYNC_CONN, sizeof(cp), &cp);
 }
 }
 
 
+void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max,
+					u16 latency, u16 to_multiplier)
+{
+	struct hci_cp_le_conn_update cp;
+	struct hci_dev *hdev = conn->hdev;
+
+	memset(&cp, 0, sizeof(cp));
+
+	cp.handle		= cpu_to_le16(conn->handle);
+	cp.conn_interval_min	= cpu_to_le16(min);
+	cp.conn_interval_max	= cpu_to_le16(max);
+	cp.conn_latency		= cpu_to_le16(latency);
+	cp.supervision_timeout	= cpu_to_le16(to_multiplier);
+	cp.min_ce_len		= cpu_to_le16(0x0001);
+	cp.max_ce_len		= cpu_to_le16(0x0001);
+
+	hci_send_cmd(hdev, HCI_OP_LE_CONN_UPDATE, sizeof(cp), &cp);
+}
+EXPORT_SYMBOL(hci_le_conn_update);
+
 /* Device _must_ be locked */
 /* Device _must_ be locked */
 void hci_sco_setup(struct hci_conn *conn, __u8 status)
 void hci_sco_setup(struct hci_conn *conn, __u8 status)
 {
 {

+ 7 - 1
net/bluetooth/l2cap_core.c

@@ -2529,6 +2529,7 @@ static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
 	struct l2cap_conn_param_update_req *req;
 	struct l2cap_conn_param_update_req *req;
 	struct l2cap_conn_param_update_rsp rsp;
 	struct l2cap_conn_param_update_rsp rsp;
 	u16 min, max, latency, to_multiplier, cmd_len;
 	u16 min, max, latency, to_multiplier, cmd_len;
+	int err;
 
 
 	if (!(hcon->link_mode & HCI_LM_MASTER))
 	if (!(hcon->link_mode & HCI_LM_MASTER))
 		return -EINVAL;
 		return -EINVAL;
@@ -2547,7 +2548,9 @@ static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
 						min, max, latency, to_multiplier);
 						min, max, latency, to_multiplier);
 
 
 	memset(&rsp, 0, sizeof(rsp));
 	memset(&rsp, 0, sizeof(rsp));
-	if (l2cap_check_conn_param(min, max, latency, to_multiplier))
+
+	err = l2cap_check_conn_param(min, max, latency, to_multiplier);
+	if (err)
 		rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
 		rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
 	else
 	else
 		rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
 		rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
@@ -2555,6 +2558,9 @@ static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
 							sizeof(rsp), &rsp);
 							sizeof(rsp), &rsp);
 
 
+	if (!err)
+		hci_le_conn_update(hcon, min, max, latency, to_multiplier);
+
 	return 0;
 	return 0;
 }
 }