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>
This commit is contained in:
Andre Guedes
2014-07-01 18:10:08 -03:00
committed by Marcel Holtmann
parent 396e04f4bb
commit 8e75b46a4f
2 changed files with 78 additions and 0 deletions

View File

@@ -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;
}