2014-07-01 21:10:08

by Andre Guedes

[permalink] [raw]
Subject: [RFC v3 1/4] 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 <[email protected]>
---
include/net/bluetooth/hci.h | 28 +++++++++++++++++++++++++
net/bluetooth/hci_event.c | 50 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 78 insertions(+)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 58c5930..95b7547 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -355,6 +355,7 @@ enum {
#define HCI_LK_AUTH_COMBINATION_P256 0x08

/* ---- HCI Error Codes ---- */
+#define HCI_ERROR_UNKNOWN_CONN_ID 0x02
#define HCI_ERROR_AUTH_FAILURE 0x05
#define HCI_ERROR_MEMORY_EXCEEDED 0x07
#define HCI_ERROR_CONNECTION_TIMEOUT 0x08
@@ -364,6 +365,7 @@ enum {
#define HCI_ERROR_REMOTE_POWER_OFF 0x15
#define HCI_ERROR_LOCAL_HOST_TERM 0x16
#define HCI_ERROR_PAIRING_NOT_ALLOWED 0x18
+#define HCI_ERROR_INVALID_LL_PARAMS 0x1E
#define HCI_ERROR_ADVERTISING_TIMEOUT 0x3c

/* Flow control modes */
@@ -1305,6 +1307,23 @@ struct hci_rp_le_read_supported_states {
__u8 le_states[8];
} __packed;

+#define HCI_OP_LE_CONN_PARAM_REQ_REPLY 0x2020
+struct hci_cp_le_conn_param_req_reply {
+ __le16 handle;
+ __le16 interval_min;
+ __le16 interval_max;
+ __le16 latency;
+ __le16 timeout;
+ __le16 min_ce_len;
+ __le16 max_ce_len;
+} __packed;
+
+#define HCI_OP_LE_CONN_PARAM_REQ_NEG_REPLY 0x2021
+struct hci_cp_le_conn_param_req_neg_reply {
+ __le16 handle;
+ __u8 reason;
+} __packed;
+
/* ---- HCI Events ---- */
#define HCI_EV_INQUIRY_COMPLETE 0x01

@@ -1700,6 +1719,15 @@ struct hci_ev_le_ltk_req {
__le16 ediv;
} __packed;

+#define HCI_EV_LE_REMOTE_CONN_PARAM_REQ 0x06
+struct hci_ev_le_remote_conn_param_req {
+ __le16 handle;
+ __le16 interval_min;
+ __le16 interval_max;
+ __le16 latency;
+ __le16 timeout;
+} __packed;
+
/* Advertising report event types */
#define LE_ADV_IND 0x00
#define LE_ADV_DIRECT_IND 0x01
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index b0b760d..544e2ef 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;
}
--
1.9.1



2014-07-01 21:45:40

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [RFC v3 4/4] Bluetooth: Introduce "New Connection Parameter" Event

Hi Andre,

> This patch introduces a new Mgmt event called "New Connection Parameter".
> This event indicates to userspace the connection parameters values the
> remote device requested.
>
> The user may store these values and load them into kernel. This way, next
> time a connection is established to that device, the kernel will use those
> parameters values instead of the default ones.
>
> This event is sent when the remote device requests new connection
> parameters through connection parameter update procedure. This event is
> not sent for slave connections.
>
> Signed-off-by: Andre Guedes <[email protected]>
> ---
> include/net/bluetooth/hci_core.h | 3 +++
> include/net/bluetooth/mgmt.h | 10 ++++++++++
> net/bluetooth/hci_event.c | 4 ++++
> net/bluetooth/l2cap_core.c | 6 +++++-
> net/bluetooth/mgmt.c | 19 +++++++++++++++++++
> 5 files changed, 41 insertions(+), 1 deletion(-)

patch has been applied to bluetooth-next tree.

Regards

Marcel


2014-07-01 21:37:26

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [RFC v3 3/4] Bluetooth: Enable new LE meta event

Hi Andre,

> The Bluetooth 4.1 introduces a new LE meta event called "LE Remote
> Connection Parameter Request" event. In order to the controller
> sends this event to host, we should enable it during controller
> initialization.
>
> Signed-off-by: Andre Guedes <[email protected]>
> ---
> include/net/bluetooth/hci.h | 3 +++
> net/bluetooth/hci_core.c | 7 +++++++
> 2 files changed, 10 insertions(+)

patch has been applied to bluetooth-next tree.

> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
> index 95b7547..66358af 100644
> --- a/include/net/bluetooth/hci.h
> +++ b/include/net/bluetooth/hci.h
> @@ -307,6 +307,9 @@ enum {
> #define LMP_HOST_LE_BREDR 0x04
> #define LMP_HOST_SC 0x08
>
> +/* LE features */
> +#define HCI_LE_CONN_PARAM_REQ_PROC 0x02
> +
> /* Connection modes */
> #define HCI_CM_ACTIVE 0x0000
> #define HCI_CM_HOLD 0x0001
> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> index 5788e03..8a54ca2 100644
> --- a/net/bluetooth/hci_core.c
> +++ b/net/bluetooth/hci_core.c
> @@ -1611,6 +1611,13 @@ static void hci_init3_req(struct hci_request *req, unsigned long opt)
>
> memset(events, 0, sizeof(events));
> events[0] = 0x1f;
> +
> + /* If controller supports the Connection Parameters Request
> + * Link Layer Procedure, enable the corresponding event.
> + */
> + if (hdev->le_features[0] & HCI_LE_CONN_PARAM_REQ_PROC)
> + events[0] = events[0] | 0x20;
> +

However I fixed this to do this properly:

events[0] |= 0x20;

We used this everywhere else. No idea why you had to make it so complicated ;)

Regards

Marcel


2014-07-01 21:36:14

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [RFC v3 2/4] Bluetooth: Move LE event mask setting into init3 phase

Hi Andre,

> During init2 phase, the LE local features have not be read yet so
> we aren't able to rely on hdev->le_features to determine if the
> controller supports the Connection Parameters Request Procedure.
>
> For that reason, this patch moves LE event mask setting from init2
> into init3 initialization phase.
>
> The hdev->le_features mask will be checked by the next patch in order
> to know if "LE Remote Connection Parameter Request Event" should be
> enabled.
>
> Signed-off-by: Andre Guedes <[email protected]>
> ---
> net/bluetooth/hci_core.c | 17 +++++++++--------
> 1 file changed, 9 insertions(+), 8 deletions(-)

patch has been applied to bluetooth-next tree.

Regards

Marcel


2014-07-01 21:35:49

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [RFC v3 1/4] Bluetooth: Connection Parameter Update Procedure

Hi Andre,

> 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 <[email protected]>
> ---
> include/net/bluetooth/hci.h | 28 +++++++++++++++++++++++++
> net/bluetooth/hci_event.c | 50 +++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 78 insertions(+)

patch has been applied to bluetooth-next tree.

Regards

Marcel


2014-07-01 21:10:11

by Andre Guedes

[permalink] [raw]
Subject: [RFC v3 4/4] Bluetooth: Introduce "New Connection Parameter" Event

This patch introduces a new Mgmt event called "New Connection Parameter".
This event indicates to userspace the connection parameters values the
remote device requested.

The user may store these values and load them into kernel. This way, next
time a connection is established to that device, the kernel will use those
parameters values instead of the default ones.

This event is sent when the remote device requests new connection
parameters through connection parameter update procedure. This event is
not sent for slave connections.

Signed-off-by: Andre Guedes <[email protected]>
---
include/net/bluetooth/hci_core.h | 3 +++
include/net/bluetooth/mgmt.h | 10 ++++++++++
net/bluetooth/hci_event.c | 4 ++++
net/bluetooth/l2cap_core.c | 6 +++++-
net/bluetooth/mgmt.c | 19 +++++++++++++++++++
5 files changed, 41 insertions(+), 1 deletion(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 3404f9b..01fbbe2 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -1329,6 +1329,9 @@ void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent);
void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk);
void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
bool persistent);
+void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
+ u8 bdaddr_type, u16 min_interval, u16 max_interval,
+ u16 latency, u16 timeout);
void mgmt_reenable_advertising(struct hci_dev *hdev);
void mgmt_smp_complete(struct hci_conn *conn, bool complete);

diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 2d88f36..3c0f296 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -615,3 +615,13 @@ struct mgmt_ev_device_added {
struct mgmt_ev_device_removed {
struct mgmt_addr_info addr;
} __packed;
+
+#define MGMT_EV_NEW_CONN_PARAM 0x001c
+struct mgmt_ev_new_conn_param {
+ struct mgmt_addr_info addr;
+ __u8 store_hint;
+ __le16 min_interval;
+ __le16 max_interval;
+ __le16 latency;
+ __le16 timeout;
+} __packed;
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 544e2ef..b9d16e0 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -4417,6 +4417,10 @@ static void hci_le_remote_conn_param_req_evt(struct hci_dev *hdev,
return send_conn_param_neg_reply(hdev, handle,
HCI_ERROR_INVALID_LL_PARAMS);

+ if (test_bit(HCI_CONN_MASTER, &hcon->flags))
+ mgmt_new_conn_param(hdev, &hcon->dst, hcon->dst_type, min, max,
+ latency, timeout);
+
cp.handle = ev->handle;
cp.interval_min = ev->interval_min;
cp.interval_max = ev->interval_max;
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index e203a5f..058b3b2 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -5249,8 +5249,12 @@ static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
sizeof(rsp), &rsp);

- if (!err)
+ if (!err) {
+ mgmt_new_conn_param(hcon->hdev, &hcon->dst, hcon->dst_type,
+ min, max, latency, to_multiplier);
+
hci_le_conn_update(hcon, min, max, latency, to_multiplier);
+ }

return 0;
}
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index ba5e215..93cfefa 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -116,6 +116,7 @@ static const u16 mgmt_events[] = {
MGMT_EV_NEW_CSRK,
MGMT_EV_DEVICE_ADDED,
MGMT_EV_DEVICE_REMOVED,
+ MGMT_EV_NEW_CONN_PARAM,
};

#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
@@ -5690,6 +5691,24 @@ void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
}

+void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
+ u8 bdaddr_type, u16 min_interval, u16 max_interval,
+ u16 latency, u16 timeout)
+{
+ struct mgmt_ev_new_conn_param ev;
+
+ memset(&ev, 0, sizeof(ev));
+ bacpy(&ev.addr.bdaddr, bdaddr);
+ ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
+ ev.store_hint = 0x00;
+ ev.min_interval = cpu_to_le16(min_interval);
+ ev.max_interval = cpu_to_le16(max_interval);
+ ev.latency = cpu_to_le16(latency);
+ ev.timeout = cpu_to_le16(timeout);
+
+ mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
+}
+
static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
u8 data_len)
{
--
1.9.1


2014-07-01 21:10:09

by Andre Guedes

[permalink] [raw]
Subject: [RFC v3 2/4] Bluetooth: Move LE event mask setting into init3 phase

During init2 phase, the LE local features have not be read yet so
we aren't able to rely on hdev->le_features to determine if the
controller supports the Connection Parameters Request Procedure.

For that reason, this patch moves LE event mask setting from init2
into init3 initialization phase.

The hdev->le_features mask will be checked by the next patch in order
to know if "LE Remote Connection Parameter Request Event" should be
enabled.

Signed-off-by: Andre Guedes <[email protected]>
---
net/bluetooth/hci_core.c | 17 +++++++++--------
1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 72eb414..5788e03 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1437,13 +1437,6 @@ static void hci_setup_event_mask(struct hci_request *req)
events[7] |= 0x20; /* LE Meta-Event */

hci_req_add(req, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
-
- if (lmp_le_capable(hdev)) {
- memset(events, 0, sizeof(events));
- events[0] = 0x1f;
- hci_req_add(req, HCI_OP_LE_SET_EVENT_MASK,
- sizeof(events), events);
- }
}

static void hci_init2_req(struct hci_request *req, unsigned long opt)
@@ -1613,8 +1606,16 @@ static void hci_init3_req(struct hci_request *req, unsigned long opt)
if (hdev->commands[5] & 0x10)
hci_setup_link_policy(req);

- if (lmp_le_capable(hdev))
+ if (lmp_le_capable(hdev)) {
+ u8 events[8];
+
+ memset(events, 0, sizeof(events));
+ events[0] = 0x1f;
+ hci_req_add(req, HCI_OP_LE_SET_EVENT_MASK, sizeof(events),
+ events);
+
hci_set_le_support(req);
+ }

/* Read features beyond page 1 if available */
for (p = 2; p < HCI_MAX_PAGES && p <= hdev->max_page; p++) {
--
1.9.1


2014-07-01 21:10:10

by Andre Guedes

[permalink] [raw]
Subject: [RFC v3 3/4] Bluetooth: Enable new LE meta event

The Bluetooth 4.1 introduces a new LE meta event called "LE Remote
Connection Parameter Request" event. In order to the controller
sends this event to host, we should enable it during controller
initialization.

Signed-off-by: Andre Guedes <[email protected]>
---
include/net/bluetooth/hci.h | 3 +++
net/bluetooth/hci_core.c | 7 +++++++
2 files changed, 10 insertions(+)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 95b7547..66358af 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -307,6 +307,9 @@ enum {
#define LMP_HOST_LE_BREDR 0x04
#define LMP_HOST_SC 0x08

+/* LE features */
+#define HCI_LE_CONN_PARAM_REQ_PROC 0x02
+
/* Connection modes */
#define HCI_CM_ACTIVE 0x0000
#define HCI_CM_HOLD 0x0001
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 5788e03..8a54ca2 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1611,6 +1611,13 @@ static void hci_init3_req(struct hci_request *req, unsigned long opt)

memset(events, 0, sizeof(events));
events[0] = 0x1f;
+
+ /* If controller supports the Connection Parameters Request
+ * Link Layer Procedure, enable the corresponding event.
+ */
+ if (hdev->le_features[0] & HCI_LE_CONN_PARAM_REQ_PROC)
+ events[0] = events[0] | 0x20;
+
hci_req_add(req, HCI_OP_LE_SET_EVENT_MASK, sizeof(events),
events);

--
1.9.1