2011-06-30 22:20:52

by Andre Guedes

[permalink] [raw]
Subject: [PATCH 1/5] Bluetooth: Add extfeatures to struct hci_dev

This new field holds the extended LMP features value. Some LE
mechanism such as discovery procedure needs to read the extended
LMP features to work properly.

Signed-off-by: Andre Guedes <[email protected]>
---
include/net/bluetooth/hci.h | 4 ++++
include/net/bluetooth/hci_core.h | 1 +
net/bluetooth/hci_event.c | 27 +++++++++++++++++++++++++++
3 files changed, 32 insertions(+), 0 deletions(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 65345cd..741a2d6 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -216,6 +216,7 @@ enum {

#define LMP_LSTO 0x01
#define LMP_INQ_TX_PWR 0x02
+#define LMP_EXTFEATURES 0x80

/* Connection modes */
#define HCI_CM_ACTIVE 0x0000
@@ -676,6 +677,9 @@ struct hci_rp_read_local_features {
} __packed;

#define HCI_OP_READ_LOCAL_EXT_FEATURES 0x1004
+struct hci_cp_read_local_ext_features {
+ __u8 page;
+} __packed;
struct hci_rp_read_local_ext_features {
__u8 status;
__u8 page;
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 26233d4..cd65f0e 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -113,6 +113,7 @@ struct hci_dev {
__u8 major_class;
__u8 minor_class;
__u8 features[8];
+ __u8 extfeatures[8];
__u8 commands[64];
__u8 ssp_mode;
__u8 hci_ver;
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index ac2c5e8..93d528c 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -542,6 +542,14 @@ static void hci_setup(struct hci_dev *hdev)

if (hdev->features[7] & LMP_INQ_TX_PWR)
hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
+
+ if (hdev->features[7] & LMP_EXTFEATURES) {
+ struct hci_cp_read_local_ext_features cp;
+
+ cp.page = 0x01;
+ hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES,
+ sizeof(cp), &cp);
+ }
}

static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
@@ -658,6 +666,21 @@ static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb
hdev->features[6], hdev->features[7]);
}

+static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
+ struct sk_buff *skb)
+{
+ struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
+
+ BT_DBG("%s status 0x%x", hdev->name, rp->status);
+
+ if (rp->status)
+ return;
+
+ memcpy(hdev->extfeatures, rp->features, 8);
+
+ hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status);
+}
+
static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_rp_read_buffer_size *rp = (void *) skb->data;
@@ -1826,6 +1849,10 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
hci_cc_read_local_features(hdev, skb);
break;

+ case HCI_OP_READ_LOCAL_EXT_FEATURES:
+ hci_cc_read_local_ext_features(hdev, skb);
+ break;
+
case HCI_OP_READ_BUFFER_SIZE:
hci_cc_read_buffer_size(hdev, skb);
break;
--
1.7.4.1



2011-06-30 22:20:56

by Andre Guedes

[permalink] [raw]
Subject: [PATCH 5/5] Bluetooth: Remove enable_smp parameter

The enable_smp parameter is no longer needed. It can be replaced by
checking lmp_host_le_capable.

Signed-off-by: Andre Guedes <[email protected]>
---
net/bluetooth/hci_core.c | 15 +--------------
net/bluetooth/smp.c | 9 +++++++++
2 files changed, 10 insertions(+), 14 deletions(-)

diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index ecc584d..5742aee 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -60,8 +60,6 @@ static void hci_tx_task(unsigned long arg);

static DEFINE_RWLOCK(hci_task_lock);

-static int enable_smp;
-
/* HCI device list */
LIST_HEAD(hci_dev_list);
DEFINE_RWLOCK(hci_dev_list_lock);
@@ -1368,14 +1366,6 @@ int hci_add_adv_entry(struct hci_dev *hdev,
return 0;
}

-static struct crypto_blkcipher *alloc_cypher(void)
-{
- if (enable_smp)
- return crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
-
- return ERR_PTR(-ENOTSUPP);
-}
-
/* Register HCI device */
int hci_register_dev(struct hci_dev *hdev)
{
@@ -1460,7 +1450,7 @@ int hci_register_dev(struct hci_dev *hdev)
if (!hdev->workqueue)
goto nomem;

- hdev->tfm = alloc_cypher();
+ hdev->tfm = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
if (IS_ERR(hdev->tfm))
BT_INFO("Failed to load transform for ecb(aes): %ld",
PTR_ERR(hdev->tfm));
@@ -2352,6 +2342,3 @@ static void hci_cmd_task(unsigned long arg)
}
}
}
-
-module_param(enable_smp, bool, 0644);
-MODULE_PARM_DESC(enable_smp, "Enable SMP support (LE only)");
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index a36f870..ba55bd4 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -434,6 +434,9 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)

BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);

+ if (!lmp_host_le_capable(hcon->hdev))
+ return 1;
+
if (IS_ERR(hcon->hdev->tfm))
return 1;

@@ -477,6 +480,12 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
__u8 reason;
int err = 0;

+ if (!lmp_host_le_capable(conn->hcon->hdev)) {
+ err = -ENOTSUPP;
+ reason = SMP_PAIRING_NOTSUPP;
+ goto done;
+ }
+
if (IS_ERR(conn->hcon->hdev->tfm)) {
err = PTR_ERR(conn->hcon->hdev->tfm);
reason = SMP_PAIRING_NOTSUPP;
--
1.7.4.1


2011-06-30 22:20:55

by Andre Guedes

[permalink] [raw]
Subject: [PATCH 4/5] Bluetooth: Add lmp_host_le_capable() macro

Since we have the extended LMP features properly implemented, we
should check the LMP_HOST_LE bit to know if the host supports LE.

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

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 5f37822..5004e36 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -219,6 +219,9 @@ enum {
#define LMP_INQ_TX_PWR 0x02
#define LMP_EXTFEATURES 0x80

+/* Extended LMP features */
+#define LMP_HOST_LE 0x02
+
/* Connection modes */
#define HCI_CM_ACTIVE 0x0000
#define HCI_CM_HOLD 0x0001
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index cd65f0e..005e3bb 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -580,6 +580,9 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
#define lmp_no_flush_capable(dev) ((dev)->features[6] & LMP_NO_FLUSH)
#define lmp_le_capable(dev) ((dev)->features[4] & LMP_LE)

+/* ----- Extended LMP capabilities ----- */
+#define lmp_host_le_capable(dev) ((dev)->extfeatures[0] & LMP_HOST_LE)
+
/* ----- HCI protocols ----- */
struct hci_proto {
char *name;
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 0029e17..ecc584d 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -542,7 +542,7 @@ int hci_dev_open(__u16 dev)
ret = __hci_request(hdev, hci_init_req, 0,
msecs_to_jiffies(HCI_INIT_TIMEOUT));

- if (lmp_le_capable(hdev))
+ if (lmp_host_le_capable(hdev))
ret = __hci_request(hdev, hci_le_init_req, 0,
msecs_to_jiffies(HCI_INIT_TIMEOUT));

--
1.7.4.1


2011-06-30 22:20:54

by Andre Guedes

[permalink] [raw]
Subject: [PATCH 3/5] Bluetooth: Add enable_le module parameter

This patch adds a new module parameter to enable/disable host LE
support. By default host LE support is disabled.

Signed-off-by: Andre Guedes <[email protected]>
---
include/net/bluetooth/hci.h | 1 +
net/bluetooth/hci_event.c | 22 ++++++++++++++++++++++
2 files changed, 23 insertions(+), 0 deletions(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index ed1de1b..5f37822 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -211,6 +211,7 @@ enum {
#define LMP_EDR_3S_ESCO 0x80

#define LMP_EXT_INQ 0x01
+#define LMP_SIMUL_LE_BR 0x02
#define LMP_SIMPLE_PAIR 0x08
#define LMP_NO_FLUSH 0x40

diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 4ed59a8..298cd9b 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -45,6 +45,8 @@
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>

+static int enable_le;
+
/* Handle HCI Event packets */

static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
@@ -525,6 +527,20 @@ static void hci_setup_event_mask(struct hci_dev *hdev)
hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
}

+static void hci_set_le_support(struct hci_dev *hdev)
+{
+ struct hci_cp_write_le_host_supported cp;
+
+ memset(&cp, 0, sizeof(cp));
+
+ if (enable_le) {
+ cp.le = 1;
+ cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR);
+ }
+
+ hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp), &cp);
+}
+
static void hci_setup(struct hci_dev *hdev)
{
hci_setup_event_mask(hdev);
@@ -550,6 +566,9 @@ static void hci_setup(struct hci_dev *hdev)
hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES,
sizeof(cp), &cp);
}
+
+ if (hdev->features[4] & LMP_LE)
+ hci_set_le_support(hdev);
}

static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
@@ -3068,3 +3087,6 @@ void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
hci_send_to_sock(hdev, skb, NULL);
kfree_skb(skb);
}
+
+module_param(enable_le, bool, 0444);
+MODULE_PARM_DESC(enable_le, "Enable LE support");
--
1.7.4.1


2011-06-30 22:20:53

by Andre Guedes

[permalink] [raw]
Subject: [PATCH 2/5] Bluetooth: Write LE Host Supported command

This patch adds a handler to Write LE Host Supported command complete
events. Once this commands has completed successfully, we should
read the extended LMP features and update the extfeatures field in
hci_dev.

Signed-off-by: Andre Guedes <[email protected]>
---
include/net/bluetooth/hci.h | 6 ++++++
net/bluetooth/hci_event.c | 19 +++++++++++++++++++
2 files changed, 25 insertions(+), 0 deletions(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 741a2d6..ed1de1b 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -654,6 +654,12 @@ struct hci_rp_read_local_oob_data {

#define HCI_OP_READ_INQ_RSP_TX_POWER 0x0c58

+#define HCI_OP_WRITE_LE_HOST_SUPPORTED 0x0c6d
+struct hci_cp_write_le_host_supported {
+ __u8 le;
+ __u8 simul;
+} __packed;
+
#define HCI_OP_READ_LOCAL_VERSION 0x1001
struct hci_rp_read_local_version {
__u8 status;
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 93d528c..4ed59a8 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -915,6 +915,21 @@ static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
}

+static inline void hci_cc_write_le_host_supported(struct hci_dev *hdev,
+ struct sk_buff *skb)
+{
+ struct hci_cp_read_local_ext_features cp;
+ __u8 status = *((__u8 *) skb->data);
+
+ BT_DBG("%s status 0x%x", hdev->name, status);
+
+ if (status)
+ return;
+
+ cp.page = 0x01;
+ hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp), &cp);
+}
+
static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
{
BT_DBG("%s status 0x%x", hdev->name, status);
@@ -1921,6 +1936,10 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
hci_cc_le_ltk_neg_reply(hdev, skb);
break;

+ case HCI_OP_WRITE_LE_HOST_SUPPORTED:
+ hci_cc_write_le_host_supported(hdev, skb);
+ break;
+
default:
BT_DBG("%s opcode 0x%x", hdev->name, opcode);
break;
--
1.7.4.1


2011-07-06 22:11:31

by Gustavo Padovan

[permalink] [raw]
Subject: Re: [PATCH 5/5] Bluetooth: Remove enable_smp parameter

Hi Andre,

* Andre Guedes <[email protected]> [2011-06-30 19:20:56 -0300]:

> The enable_smp parameter is no longer needed. It can be replaced by
> checking lmp_host_le_capable.
>
> Signed-off-by: Andre Guedes <[email protected]>
> ---
> net/bluetooth/hci_core.c | 15 +--------------
> net/bluetooth/smp.c | 9 +++++++++
> 2 files changed, 10 insertions(+), 14 deletions(-)

All five patches applied, thanks.

Gustavo

2011-07-01 10:56:31

by Anderson Lizardo

[permalink] [raw]
Subject: Re: [PATCH 3/5] Bluetooth: Add enable_le module parameter

Hi Andrei,

On Fri, Jul 1, 2011 at 5:09 AM, Andrei Emeltchenko
<[email protected]> wrote:
>> +static void hci_set_le_support(struct hci_dev *hdev)
>> +{
>> + ? ? struct hci_cp_write_le_host_supported cp;
>> +
>> + ? ? memset(&cp, 0, sizeof(cp));
>> +
>> + ? ? if (enable_le) {
>> + ? ? ? ? ? ? cp.le = 1;
>> + ? ? ? ? ? ? cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR);
>
> Typo?

Usually this is a trick (used in other parts of the kernel) to assign
only 0 or 1 to a variable based on a value where non-zero means
"true". It is equivalent to:

if (hdev->features[6] & LMP_SIMUL_LE_BR)
cp.simul = 1;
else
cp.simul = 0;

(yes, I came across this same feeling when I saw this for the first
time on bluetooth kernel code)

Regards,
--
Anderson Lizardo
Instituto Nokia de Tecnologia - INdT
Manaus - Brazil

2011-07-01 09:09:59

by Andrei Emeltchenko

[permalink] [raw]
Subject: Re: [PATCH 3/5] Bluetooth: Add enable_le module parameter

Hi,

On Thu, Jun 30, 2011 at 07:20:54PM -0300, Andre Guedes wrote:
> This patch adds a new module parameter to enable/disable host LE
> support. By default host LE support is disabled.
>
> Signed-off-by: Andre Guedes <[email protected]>
> ---
> include/net/bluetooth/hci.h | 1 +
> net/bluetooth/hci_event.c | 22 ++++++++++++++++++++++
> 2 files changed, 23 insertions(+), 0 deletions(-)
>
> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
> index ed1de1b..5f37822 100644
> --- a/include/net/bluetooth/hci.h
> +++ b/include/net/bluetooth/hci.h
> @@ -211,6 +211,7 @@ enum {
> #define LMP_EDR_3S_ESCO 0x80
>
> #define LMP_EXT_INQ 0x01
> +#define LMP_SIMUL_LE_BR 0x02
> #define LMP_SIMPLE_PAIR 0x08
> #define LMP_NO_FLUSH 0x40
>
> diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
> index 4ed59a8..298cd9b 100644
> --- a/net/bluetooth/hci_event.c
> +++ b/net/bluetooth/hci_event.c
> @@ -45,6 +45,8 @@
> #include <net/bluetooth/bluetooth.h>
> #include <net/bluetooth/hci_core.h>
>
> +static int enable_le;
> +
> /* Handle HCI Event packets */
>
> static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
> @@ -525,6 +527,20 @@ static void hci_setup_event_mask(struct hci_dev *hdev)
> hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
> }
>
> +static void hci_set_le_support(struct hci_dev *hdev)
> +{
> + struct hci_cp_write_le_host_supported cp;
> +
> + memset(&cp, 0, sizeof(cp));
> +
> + if (enable_le) {
> + cp.le = 1;
> + cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR);

Typo?

Best regards
Andrei Emeltchenko

> + }
> +
> + hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp), &cp);
> +}
> +
> static void hci_setup(struct hci_dev *hdev)
> {
> hci_setup_event_mask(hdev);
> @@ -550,6 +566,9 @@ static void hci_setup(struct hci_dev *hdev)
> hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES,
> sizeof(cp), &cp);
> }
> +
> + if (hdev->features[4] & LMP_LE)
> + hci_set_le_support(hdev);
> }
>
> static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
> @@ -3068,3 +3087,6 @@ void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
> hci_send_to_sock(hdev, skb, NULL);
> kfree_skb(skb);
> }
> +
> +module_param(enable_le, bool, 0444);
> +MODULE_PARM_DESC(enable_le, "Enable LE support");
> --
> 1.7.4.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html