summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorAndre Guedes2014-07-01 23:10:08 +0200
committerMarcel Holtmann2014-07-03 17:42:54 +0200
commit8e75b46a4f5d2c71b2f3ea632df1b15502514948 (patch)
tree42b70a9e2dcfe7af383f3f1954bcab10084ce8f1 /net
parentBluetooth: btmrvl: wait for HOST_SLEEP_ENABLE event in suspend (diff)
downloadkernel-qcow2-linux-8e75b46a4f5d2c71b2f3ea632df1b15502514948.tar.gz
kernel-qcow2-linux-8e75b46a4f5d2c71b2f3ea632df1b15502514948.tar.xz
kernel-qcow2-linux-8e75b46a4f5d2c71b2f3ea632df1b15502514948.zip
Bluetooth: Connection Parameter Update Procedure
This patch adds support for LE Connection Parameters Request Link Layer control procedure introduced in Core spec 4.1. This procedure allows a Peripheral or Central to update the Link Layer connection parameters of an established connection. Regarding the acceptance of connection parameters, the LL procedure follows the same approach of L2CAP procedure (see l2cap_conn_param_ update_req function). We accept any connection parameters values as long as they are within the valid range. Signed-off-by: Andre Guedes <andre.guedes@openbossa.org> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net')
-rw-r--r--net/bluetooth/hci_event.c50
1 files changed, 50 insertions, 0 deletions
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index b0b760dd66a3..544e2ef85d82 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -4382,6 +4382,52 @@ not_found:
hci_dev_unlock(hdev);
}
+static void send_conn_param_neg_reply(struct hci_dev *hdev, u16 handle,
+ u8 reason)
+{
+ struct hci_cp_le_conn_param_req_neg_reply cp;
+
+ cp.handle = cpu_to_le16(handle);
+ cp.reason = reason;
+
+ hci_send_cmd(hdev, HCI_OP_LE_CONN_PARAM_REQ_NEG_REPLY, sizeof(cp),
+ &cp);
+}
+
+static void hci_le_remote_conn_param_req_evt(struct hci_dev *hdev,
+ struct sk_buff *skb)
+{
+ struct hci_ev_le_remote_conn_param_req *ev = (void *) skb->data;
+ struct hci_cp_le_conn_param_req_reply cp;
+ struct hci_conn *hcon;
+ u16 handle, min, max, latency, timeout;
+
+ handle = le16_to_cpu(ev->handle);
+ min = le16_to_cpu(ev->interval_min);
+ max = le16_to_cpu(ev->interval_max);
+ latency = le16_to_cpu(ev->latency);
+ timeout = le16_to_cpu(ev->timeout);
+
+ hcon = hci_conn_hash_lookup_handle(hdev, handle);
+ if (!hcon || hcon->state != BT_CONNECTED)
+ return send_conn_param_neg_reply(hdev, handle,
+ HCI_ERROR_UNKNOWN_CONN_ID);
+
+ if (hci_check_conn_params(min, max, latency, timeout))
+ return send_conn_param_neg_reply(hdev, handle,
+ HCI_ERROR_INVALID_LL_PARAMS);
+
+ cp.handle = ev->handle;
+ cp.interval_min = ev->interval_min;
+ cp.interval_max = ev->interval_max;
+ cp.latency = ev->latency;
+ cp.timeout = ev->timeout;
+ cp.min_ce_len = 0;
+ cp.max_ce_len = 0;
+
+ hci_send_cmd(hdev, HCI_OP_LE_CONN_PARAM_REQ_REPLY, sizeof(cp), &cp);
+}
+
static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_le_meta *le_ev = (void *) skb->data;
@@ -4405,6 +4451,10 @@ static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
hci_le_ltk_request_evt(hdev, skb);
break;
+ case HCI_EV_LE_REMOTE_CONN_PARAM_REQ:
+ hci_le_remote_conn_param_req_evt(hdev, skb);
+ break;
+
default:
break;
}