2011-05-21 00:10:35

by Andre Guedes

[permalink] [raw]
Subject: [PATCH v2 01/11] Bluetooth: Add advertising report meta event structs

From: Anderson Briglia <[email protected]>

This patch adds definitions and a new struct for Advertising Report
Event from LE and Dual Mode controllers.

Signed-off-by: Anderson Briglia <[email protected]>
---
include/net/bluetooth/hci.h | 19 +++++++++++++++++++
1 files changed, 19 insertions(+), 0 deletions(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index e0a3cf1..ec0fb2d 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -1029,6 +1029,25 @@ struct hci_ev_le_conn_complete {
__u8 clk_accurancy;
} __packed;

+/* Advertising report event types */
+#define ADV_IND 0x00
+#define ADV_DIRECT_IND 0x01
+#define ADV_SCAN_IND 0x02
+#define ADV_NONCONN_IND 0x03
+#define ADV_SCAN_RSP 0x04
+
+#define ADDR_LE_DEV_PUBLIC 0x00
+#define ADDR_LE_DEV_RANDOM 0x01
+
+#define HCI_EV_LE_ADVERTISING_REPORT 0x02
+struct hci_ev_le_advertising_info {
+ __u8 evt_type;
+ __u8 bdaddr_type;
+ bdaddr_t bdaddr;
+ __u8 length;
+ __u8 data[0];
+} __packed;
+
/* Internal events generated by Bluetooth stack */
#define HCI_EV_STACK_INTERNAL 0xfd
struct hci_ev_stack_internal {
--
1.7.4.1



2011-05-25 16:42:42

by Andre Guedes

[permalink] [raw]
Subject: Re: [PATCH v2 04/11] Bluetooth: LE Set Scan Enable command complete event

Padovan,

Please, don't consider this v2 patchset. I will consider Ville's
comments and send a new version soon.

Thanks Ville.

- Andre

On Tue, May 24, 2011 at 7:42 AM, Ville Tervo <[email protected]> wrote:
> Hi Andre,
>
> On Fri, May 20, 2011 at 09:10:38PM -0300, ext Andre Guedes wrote:
>> This patch adds a function handler to the command complete event
>> generated by the LE Set Scan Enable command.
>>
>
> This patch is not doing anything besides DBG(). Drop it and introduce again
> when it is really needed. hcidump gives same information.
>
>> Signed-off-by: Andre Guedes <[email protected]>
>> ---
>> ?include/net/bluetooth/hci.h | ? ?2 ++
>> ?net/bluetooth/hci_event.c ? | ? 12 ++++++++++++
>> ?2 files changed, 14 insertions(+), 0 deletions(-)
>>
>> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
>> index ec0fb2d..bc90da9 100644
>> --- a/include/net/bluetooth/hci.h
>> +++ b/include/net/bluetooth/hci.h
>> @@ -710,6 +710,8 @@ struct hci_rp_le_read_buffer_size {
>> ? ? ? __u8 ? ? le_max_pkt;
>> ?} __packed;
>>
>> +#define HCI_OP_LE_SET_SCAN_ENABLE ? ?0x200c
>> +
>> ?#define HCI_OP_LE_CREATE_CONN ? ? ? ? ? ? ? ?0x200d
>> ?struct hci_cp_le_create_conn {
>> ? ? ? __le16 ? scan_interval;
>> diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
>> index 458caac..ccf4d4d 100644
>> --- a/net/bluetooth/hci_event.c
>> +++ b/net/bluetooth/hci_event.c
>> @@ -839,6 +839,14 @@ static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? rp->randomizer, rp->status);
>> ?}
>>
>> +static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct sk_buff *skb)
>> +{
>> + ? ? __u8 status = *((__u8 *) skb->data);
>> +
>> + ? ? BT_DBG("%s status 0x%x", hdev->name, status);
>> +}
>> +
>> ?static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
>> ?{
>> ? ? ? BT_DBG("%s status 0x%x", hdev->name, status);
>> @@ -1814,6 +1822,10 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
>> ? ? ? ? ? ? ? hci_cc_user_confirm_neg_reply(hdev, skb);
>> ? ? ? ? ? ? ? break;
>>
>> + ? ? case HCI_OP_LE_SET_SCAN_ENABLE:
>> + ? ? ? ? ? ? hci_cc_le_set_scan_enable(hdev, skb);
>> + ? ? ? ? ? ? break;
>> +
>> ? ? ? default:
>> ? ? ? ? ? ? ? BT_DBG("%s opcode 0x%x", hdev->name, opcode);
>> ? ? ? ? ? ? ? break;
>> --
>> 1.7.4.1
>
> --
> Ville
>

2011-05-24 11:16:52

by Ville Tervo

[permalink] [raw]
Subject: Re: [PATCH v2 11/11] Bluetooth: Set 'peer_addr_type' in hci_le_connect()

On Fri, May 20, 2011 at 09:10:45PM -0300, ext Andre Guedes wrote:
> Set the 'peer_addr_type' field of the LE Create Connection command
> sent in hci_le_connect().
>
> Signed-off-by: Andre Guedes <[email protected]>

Acked-by: Ville Tervo <[email protected]>

> ---
> net/bluetooth/hci_conn.c | 1 +
> 1 files changed, 1 insertions(+), 0 deletions(-)
>
> diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
> index 468d2aa..e58ef96 100644
> --- a/net/bluetooth/hci_conn.c
> +++ b/net/bluetooth/hci_conn.c
> @@ -58,6 +58,7 @@ static void hci_le_connect(struct hci_conn *conn)
> cp.scan_interval = cpu_to_le16(0x0004);
> cp.scan_window = cpu_to_le16(0x0004);
> bacpy(&cp.peer_addr, &conn->dst);
> + cp.peer_addr_type = conn->dst_type;
> cp.conn_interval_min = cpu_to_le16(0x0008);
> cp.conn_interval_max = cpu_to_le16(0x0100);
> cp.supervision_timeout = cpu_to_le16(0x0064);


--
Ville

2011-05-24 11:15:34

by Ville Tervo

[permalink] [raw]
Subject: Re: [PATCH v2 10/11] Bluetooth: Check advertising cache in hci_connect()

On Fri, May 20, 2011 at 09:10:44PM -0300, ext Andre Guedes wrote:
> When connecting to a LE device, we need to check the advertising
> cache in order to know the address type of that device.
>
> If its advertising entry is not found, the connection is not
> established and hci_connect() returns error.
>
> Signed-off-by: Andre Guedes <[email protected]>

Acked-by: Ville Tervo <[email protected]>

> ---
> net/bluetooth/hci_conn.c | 9 ++++++++-
> 1 files changed, 8 insertions(+), 1 deletions(-)
>
> diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
> index b21cbb3..468d2aa 100644
> --- a/net/bluetooth/hci_conn.c
> +++ b/net/bluetooth/hci_conn.c
> @@ -451,10 +451,17 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8
> BT_DBG("%s dst %s", hdev->name, batostr(dst));
>
> if (type == LE_LINK) {
> + struct adv_entry *entry;
> +
> le = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst);
> if (le)
> return ERR_PTR(-EBUSY);
> - le = hci_conn_add(hdev, LE_LINK, dst, 0);
> +
> + entry = hci_find_adv_entry(hdev, dst);
> + if (!entry)
> + return ERR_PTR(-EHOSTUNREACH);
> +
> + le = hci_conn_add(hdev, LE_LINK, dst, entry->bdaddr_type);
> if (!le)
> return ERR_PTR(-ENOMEM);
>
> --
> 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

2011-05-24 11:13:22

by Ville Tervo

[permalink] [raw]
Subject: Re: [PATCH v2 09/11] Bluetooth: Remove useless check in hci_connect()

Hi Andre,

On Fri, May 20, 2011 at 09:10:43PM -0300, ext Andre Guedes wrote:
> There is no need to check the connection's state since hci_conn_add()
> has just created a new connection and its state has been set properly.
>
> Signed-off-by: Andre Guedes <[email protected]>

Yes this is useless check.

Acked-by: Ville Tervo <[email protected]>

> ---
> net/bluetooth/hci_conn.c | 4 ++--
> 1 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
> index 84ad32b..b21cbb3 100644
> --- a/net/bluetooth/hci_conn.c
> +++ b/net/bluetooth/hci_conn.c
> @@ -457,8 +457,8 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8
> le = hci_conn_add(hdev, LE_LINK, dst, 0);
> if (!le)
> return ERR_PTR(-ENOMEM);
> - if (le->state == BT_OPEN)
> - hci_le_connect(le);
> +
> + hci_le_connect(le);
>
> hci_conn_hold(le);
>
> --
> 1.7.4.1

--
Ville

2011-05-24 11:08:19

by Ville Tervo

[permalink] [raw]
Subject: Re: [PATCH v2 07/11] Bluetooth: Add 'dst_type' field to struct hci_conn

Hi Andre,

On Fri, May 20, 2011 at 09:10:41PM -0300, ext Andre Guedes wrote:
> This patch adds a new field (dst_type) to the struct hci_conn which
> holds the type of the destination address (bdaddr_t dst).
>
> This approach is needed in order to use the struct hci_conn as an
> abstraction of LE connections in HCI Layer.
>
> Signed-off-by: Andre Guedes <[email protected]>
> ---
> include/net/bluetooth/hci_core.h | 1 +
> 1 files changed, 1 insertions(+), 0 deletions(-)
>
> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> index af4b0ed..539eb85 100644
> --- a/include/net/bluetooth/hci_core.h
> +++ b/include/net/bluetooth/hci_core.h
> @@ -224,6 +224,7 @@ struct hci_conn {
> spinlock_t lock;
>
> bdaddr_t dst;
> + __u8 dst_type;

Again add this only when you are using it. IOW include it into your next patch.

--
Ville

2011-05-24 10:51:36

by Ville Tervo

[permalink] [raw]
Subject: Re: [PATCH v2 05/11] Bluetooth: Clear advertising cache before scanning

Hi Andre,

On Fri, May 20, 2011 at 09:10:39PM -0300, ext Andre Guedes wrote:
> The LE advertising cache should be cleared before performing a LE
> scanning. This will force the cache to contain only fresh advertising
> entries.

04/11 can be marged with this one.

>
> Signed-off-by: Andre Guedes <[email protected]>
> ---
> net/bluetooth/hci_event.c | 18 ++++++++++++++++++
> 1 files changed, 18 insertions(+), 0 deletions(-)
>
> diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
> index ccf4d4d..85e12d8 100644
> --- a/net/bluetooth/hci_event.c
> +++ b/net/bluetooth/hci_event.c
> @@ -842,9 +842,27 @@ static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
> static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
> struct sk_buff *skb)
> {
> + void *sent;
> + __u8 param_scan_enable;
> __u8 status = *((__u8 *) skb->data);
>
> BT_DBG("%s status 0x%x", hdev->name, status);
> +
> + if (status)
> + return;
> +
> + sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
> + if (!sent)
> + return;
> +
> + param_scan_enable = *((__u8 *) sent);

A proper struct would be better since this command has two parameters.

> +
> + hci_dev_lock(hdev);
> +
> + if (param_scan_enable == 0x01)
> + hci_adv_entries_clear(hdev);
> +
> + hci_dev_unlock(hdev);
> }
>
> static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
> --
> 1.7.4.1
>

--
Ville

2011-05-24 10:42:23

by Ville Tervo

[permalink] [raw]
Subject: Re: [PATCH v2 04/11] Bluetooth: LE Set Scan Enable command complete event

Hi Andre,

On Fri, May 20, 2011 at 09:10:38PM -0300, ext Andre Guedes wrote:
> This patch adds a function handler to the command complete event
> generated by the LE Set Scan Enable command.
>

This patch is not doing anything besides DBG(). Drop it and introduce again
when it is really needed. hcidump gives same information.

> Signed-off-by: Andre Guedes <[email protected]>
> ---
> include/net/bluetooth/hci.h | 2 ++
> net/bluetooth/hci_event.c | 12 ++++++++++++
> 2 files changed, 14 insertions(+), 0 deletions(-)
>
> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
> index ec0fb2d..bc90da9 100644
> --- a/include/net/bluetooth/hci.h
> +++ b/include/net/bluetooth/hci.h
> @@ -710,6 +710,8 @@ struct hci_rp_le_read_buffer_size {
> __u8 le_max_pkt;
> } __packed;
>
> +#define HCI_OP_LE_SET_SCAN_ENABLE 0x200c
> +
> #define HCI_OP_LE_CREATE_CONN 0x200d
> struct hci_cp_le_create_conn {
> __le16 scan_interval;
> diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
> index 458caac..ccf4d4d 100644
> --- a/net/bluetooth/hci_event.c
> +++ b/net/bluetooth/hci_event.c
> @@ -839,6 +839,14 @@ static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
> rp->randomizer, rp->status);
> }
>
> +static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
> + struct sk_buff *skb)
> +{
> + __u8 status = *((__u8 *) skb->data);
> +
> + BT_DBG("%s status 0x%x", hdev->name, status);
> +}
> +
> static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
> {
> BT_DBG("%s status 0x%x", hdev->name, status);
> @@ -1814,6 +1822,10 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
> hci_cc_user_confirm_neg_reply(hdev, skb);
> break;
>
> + case HCI_OP_LE_SET_SCAN_ENABLE:
> + hci_cc_le_set_scan_enable(hdev, skb);
> + break;
> +
> default:
> BT_DBG("%s opcode 0x%x", hdev->name, opcode);
> break;
> --
> 1.7.4.1

--
Ville

2011-05-21 00:10:45

by Andre Guedes

[permalink] [raw]
Subject: [PATCH v2 11/11] Bluetooth: Set 'peer_addr_type' in hci_le_connect()

Set the 'peer_addr_type' field of the LE Create Connection command
sent in hci_le_connect().

Signed-off-by: Andre Guedes <[email protected]>
---
net/bluetooth/hci_conn.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 468d2aa..e58ef96 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -58,6 +58,7 @@ static void hci_le_connect(struct hci_conn *conn)
cp.scan_interval = cpu_to_le16(0x0004);
cp.scan_window = cpu_to_le16(0x0004);
bacpy(&cp.peer_addr, &conn->dst);
+ cp.peer_addr_type = conn->dst_type;
cp.conn_interval_min = cpu_to_le16(0x0008);
cp.conn_interval_max = cpu_to_le16(0x0100);
cp.supervision_timeout = cpu_to_le16(0x0064);
--
1.7.4.1


2011-05-21 00:10:44

by Andre Guedes

[permalink] [raw]
Subject: [PATCH v2 10/11] Bluetooth: Check advertising cache in hci_connect()

When connecting to a LE device, we need to check the advertising
cache in order to know the address type of that device.

If its advertising entry is not found, the connection is not
established and hci_connect() returns error.

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

diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index b21cbb3..468d2aa 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -451,10 +451,17 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8
BT_DBG("%s dst %s", hdev->name, batostr(dst));

if (type == LE_LINK) {
+ struct adv_entry *entry;
+
le = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst);
if (le)
return ERR_PTR(-EBUSY);
- le = hci_conn_add(hdev, LE_LINK, dst, 0);
+
+ entry = hci_find_adv_entry(hdev, dst);
+ if (!entry)
+ return ERR_PTR(-EHOSTUNREACH);
+
+ le = hci_conn_add(hdev, LE_LINK, dst, entry->bdaddr_type);
if (!le)
return ERR_PTR(-ENOMEM);

--
1.7.4.1


2011-05-21 00:10:43

by Andre Guedes

[permalink] [raw]
Subject: [PATCH v2 09/11] Bluetooth: Remove useless check in hci_connect()

There is no need to check the connection's state since hci_conn_add()
has just created a new connection and its state has been set properly.

Signed-off-by: Andre Guedes <[email protected]>
---
net/bluetooth/hci_conn.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 84ad32b..b21cbb3 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -457,8 +457,8 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8
le = hci_conn_add(hdev, LE_LINK, dst, 0);
if (!le)
return ERR_PTR(-ENOMEM);
- if (le->state == BT_OPEN)
- hci_le_connect(le);
+
+ hci_le_connect(le);

hci_conn_hold(le);

--
1.7.4.1


2011-05-21 00:10:42

by Andre Guedes

[permalink] [raw]
Subject: [PATCH v2 08/11] Bluetooth: Add 'dst_type' param to hci_conn_add()

The address type must be considered to create LE struct hci_conn
objects. For non-LE this parameter is ignored.

Signed-off-by: Andre Guedes <[email protected]>
---
include/net/bluetooth/hci_core.h | 3 ++-
net/bluetooth/hci_conn.c | 12 ++++++++----
net/bluetooth/hci_event.c | 11 +++++++----
3 files changed, 17 insertions(+), 9 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 539eb85..486224d 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -425,7 +425,8 @@ void hci_add_sco(struct hci_conn *conn, __u16 handle);
void hci_setup_sync(struct hci_conn *conn, __u16 handle);
void hci_sco_setup(struct hci_conn *conn, __u8 status);

-struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst);
+struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
+ __u8 dst_type);
int hci_conn_del(struct hci_conn *conn);
void hci_conn_hash_flush(struct hci_dev *hdev);
void hci_conn_check_pending(struct hci_dev *hdev);
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 3163330..84ad32b 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -282,7 +282,8 @@ static void hci_conn_auto_accept(unsigned long arg)
hci_dev_unlock(hdev);
}

-struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
+struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
+ __u8 dst_type)
{
struct hci_conn *conn;

@@ -319,6 +320,9 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
case ESCO_LINK:
conn->pkt_type = hdev->esco_type & ~EDR_ESCO_MASK;
break;
+ case LE_LINK:
+ conn->dst_type = dst_type;
+ break;
}

skb_queue_head_init(&conn->data_q);
@@ -450,7 +454,7 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8
le = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst);
if (le)
return ERR_PTR(-EBUSY);
- le = hci_conn_add(hdev, LE_LINK, dst);
+ le = hci_conn_add(hdev, LE_LINK, dst, 0);
if (!le)
return ERR_PTR(-ENOMEM);
if (le->state == BT_OPEN)
@@ -463,7 +467,7 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8

acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
if (!acl) {
- acl = hci_conn_add(hdev, ACL_LINK, dst);
+ acl = hci_conn_add(hdev, ACL_LINK, dst, 0);
if (!acl)
return NULL;
}
@@ -482,7 +486,7 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8

sco = hci_conn_hash_lookup_ba(hdev, type, dst);
if (!sco) {
- sco = hci_conn_add(hdev, type, dst);
+ sco = hci_conn_add(hdev, type, dst, 0);
if (!sco) {
hci_conn_put(acl);
return NULL;
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 8d6dc1e..2710332 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -913,7 +913,7 @@ static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
}
} else {
if (!conn) {
- conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr);
+ conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr, 0);
if (conn) {
conn->out = 1;
conn->link_mode |= HCI_LM_MASTER;
@@ -1236,7 +1236,8 @@ static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
}
} else {
if (!conn) {
- conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr);
+ conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr,
+ cp->peer_addr_type);
if (conn)
conn->out = 1;
else
@@ -1400,7 +1401,8 @@ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *sk

conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
if (!conn) {
- conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
+ conn = hci_conn_add(hdev, ev->link_type,
+ &ev->bdaddr, 0);
if (!conn) {
BT_ERR("No memory for new connection");
hci_dev_unlock(hdev);
@@ -2684,7 +2686,8 @@ static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff

conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr);
if (!conn) {
- conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
+ conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr,
+ ev->bdaddr_type);
if (!conn) {
BT_ERR("No memory for new connection");
hci_dev_unlock(hdev);
--
1.7.4.1


2011-05-21 00:10:41

by Andre Guedes

[permalink] [raw]
Subject: [PATCH v2 07/11] Bluetooth: Add 'dst_type' field to struct hci_conn

This patch adds a new field (dst_type) to the struct hci_conn which
holds the type of the destination address (bdaddr_t dst).

This approach is needed in order to use the struct hci_conn as an
abstraction of LE connections in HCI Layer.

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

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index af4b0ed..539eb85 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -224,6 +224,7 @@ struct hci_conn {
spinlock_t lock;

bdaddr_t dst;
+ __u8 dst_type;
__u16 handle;
__u16 state;
__u8 mode;
--
1.7.4.1


2011-05-21 00:10:40

by Andre Guedes

[permalink] [raw]
Subject: [PATCH v2 06/11] Bluetooth: Advertising entries lifetime

This patch adds a timer to clear 'adv_entries' after three minutes.

After some amount of time, the advertising entries cached during
the last LE scan should be considered expired and they should be
removed from the advertising cache.

It was chosen a three minutes timeout as an initial attempt. This
value might change in future.

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

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 10dfb85..af4b0ed 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -188,6 +188,7 @@ struct hci_dev {
struct list_head remote_oob_data;

struct list_head adv_entries;
+ struct timer_list adv_timer;

struct hci_dev_stats stat;

@@ -535,6 +536,7 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash,
u8 *randomizer);
int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr);

+#define ADV_CLEAR_TIMEOUT (3*60*HZ) /* Three minutes */
int hci_adv_entries_clear(struct hci_dev *hdev);
struct adv_entry *hci_find_adv_entry(struct hci_dev *hdev, bdaddr_t *bdaddr);
int hci_add_adv_entry(struct hci_dev *hdev,
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index dd27f97..5040c3f 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1204,6 +1204,17 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash,
return 0;
}

+static void hci_clear_adv_cache(unsigned long arg)
+{
+ struct hci_dev *hdev = (void *) arg;
+
+ hci_dev_lock(hdev);
+
+ hci_adv_entries_clear(hdev);
+
+ hci_dev_unlock(hdev);
+}
+
int hci_adv_entries_clear(struct hci_dev *hdev)
{
struct adv_entry *entry, *tmp;
@@ -1332,6 +1343,8 @@ int hci_register_dev(struct hci_dev *hdev)
INIT_LIST_HEAD(&hdev->remote_oob_data);

INIT_LIST_HEAD(&hdev->adv_entries);
+ setup_timer(&hdev->adv_timer, hci_clear_adv_cache,
+ (unsigned long) hdev);

INIT_WORK(&hdev->power_on, hci_power_on);
INIT_WORK(&hdev->power_off, hci_power_off);
@@ -1405,6 +1418,7 @@ int hci_unregister_dev(struct hci_dev *hdev)
hci_unregister_sysfs(hdev);

hci_del_off_timer(hdev);
+ del_timer(&hdev->adv_timer);

destroy_workqueue(hdev->workqueue);

diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 85e12d8..8d6dc1e 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -859,8 +859,12 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,

hci_dev_lock(hdev);

- if (param_scan_enable == 0x01)
+ if (param_scan_enable == 0x01) {
+ del_timer(&hdev->adv_timer);
hci_adv_entries_clear(hdev);
+ } else if (param_scan_enable == 0x00) {
+ mod_timer(&hdev->adv_timer, jiffies + ADV_CLEAR_TIMEOUT);
+ }

hci_dev_unlock(hdev);
}
--
1.7.4.1


2011-05-21 00:10:39

by Andre Guedes

[permalink] [raw]
Subject: [PATCH v2 05/11] Bluetooth: Clear advertising cache before scanning

The LE advertising cache should be cleared before performing a LE
scanning. This will force the cache to contain only fresh advertising
entries.

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

diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index ccf4d4d..85e12d8 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -842,9 +842,27 @@ static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
struct sk_buff *skb)
{
+ void *sent;
+ __u8 param_scan_enable;
__u8 status = *((__u8 *) skb->data);

BT_DBG("%s status 0x%x", hdev->name, status);
+
+ if (status)
+ return;
+
+ sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
+ if (!sent)
+ return;
+
+ param_scan_enable = *((__u8 *) sent);
+
+ hci_dev_lock(hdev);
+
+ if (param_scan_enable == 0x01)
+ hci_adv_entries_clear(hdev);
+
+ hci_dev_unlock(hdev);
}

static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
--
1.7.4.1


2011-05-21 00:10:38

by Andre Guedes

[permalink] [raw]
Subject: [PATCH v2 04/11] Bluetooth: LE Set Scan Enable command complete event

This patch adds a function handler to the command complete event
generated by the LE Set Scan Enable command.

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

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index ec0fb2d..bc90da9 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -710,6 +710,8 @@ struct hci_rp_le_read_buffer_size {
__u8 le_max_pkt;
} __packed;

+#define HCI_OP_LE_SET_SCAN_ENABLE 0x200c
+
#define HCI_OP_LE_CREATE_CONN 0x200d
struct hci_cp_le_create_conn {
__le16 scan_interval;
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 458caac..ccf4d4d 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -839,6 +839,14 @@ static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
rp->randomizer, rp->status);
}

+static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
+ struct sk_buff *skb)
+{
+ __u8 status = *((__u8 *) skb->data);
+
+ BT_DBG("%s status 0x%x", hdev->name, status);
+}
+
static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
{
BT_DBG("%s status 0x%x", hdev->name, status);
@@ -1814,6 +1822,10 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
hci_cc_user_confirm_neg_reply(hdev, skb);
break;

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


2011-05-21 00:10:37

by Andre Guedes

[permalink] [raw]
Subject: [PATCH v2 03/11] Bluetooth: Add Advertising Report Meta Event handler

This patch adds a function to handle LE Advertising Report Meta
Events.

Signed-off-by: Andre Guedes <[email protected]>
Signed-off-by: Anderson Briglia <[email protected]>
---
net/bluetooth/hci_event.c | 26 ++++++++++++++++++++++++++
1 files changed, 26 insertions(+), 0 deletions(-)

diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index f13ddbf..458caac 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2680,6 +2680,28 @@ unlock:
hci_dev_unlock(hdev);
}

+static inline void hci_le_adv_report_evt(struct hci_dev *hdev,
+ struct sk_buff *skb)
+{
+ const u8 RSSI_SIZE = 1;
+ struct hci_ev_le_advertising_info *ev;
+ u8 num_reports;
+
+ num_reports = skb->data[0];
+ ev = (void *) &skb->data[1];
+
+ hci_dev_lock(hdev);
+
+ hci_add_adv_entry(hdev, ev);
+
+ while (--num_reports) {
+ ev = (void *) (ev->data + ev->length + RSSI_SIZE);
+ hci_add_adv_entry(hdev, ev);
+ }
+
+ hci_dev_unlock(hdev);
+}
+
static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_le_meta *le_ev = (void *) skb->data;
@@ -2691,6 +2713,10 @@ static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
hci_le_conn_complete_evt(hdev, skb);
break;

+ case HCI_EV_LE_ADVERTISING_REPORT:
+ hci_le_adv_report_evt(hdev, skb);
+ break;
+
default:
break;
}
--
1.7.4.1


2011-05-21 00:10:36

by Andre Guedes

[permalink] [raw]
Subject: [PATCH v2 02/11] Bluetooth: LE advertising cache

This patch implements the LE advertising cache. It stores sensitive
information (bdaddr and bdaddr_type so far) gathered from LE
advertising report events.

Only advertising entries from connectables devices are added to the
cache.

Signed-off-by: Andre Guedes <[email protected]>
---
include/net/bluetooth/hci_core.h | 13 ++++++++
net/bluetooth/hci_core.c | 64 ++++++++++++++++++++++++++++++++++++++
2 files changed, 77 insertions(+), 0 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 6c994c0..10dfb85 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -89,6 +89,12 @@ struct oob_data {
u8 randomizer[16];
};

+struct adv_entry {
+ struct list_head list;
+ bdaddr_t bdaddr;
+ u8 bdaddr_type;
+};
+
#define NUM_REASSEMBLY 4
struct hci_dev {
struct list_head list;
@@ -181,6 +187,8 @@ struct hci_dev {

struct list_head remote_oob_data;

+ struct list_head adv_entries;
+
struct hci_dev_stats stat;

struct sk_buff_head driver_init;
@@ -527,6 +535,11 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash,
u8 *randomizer);
int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr);

+int hci_adv_entries_clear(struct hci_dev *hdev);
+struct adv_entry *hci_find_adv_entry(struct hci_dev *hdev, bdaddr_t *bdaddr);
+int hci_add_adv_entry(struct hci_dev *hdev,
+ struct hci_ev_le_advertising_info *ev);
+
void hci_del_off_timer(struct hci_dev *hdev);

void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index b6bda3f..dd27f97 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1204,6 +1204,67 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash,
return 0;
}

+int hci_adv_entries_clear(struct hci_dev *hdev)
+{
+ struct adv_entry *entry, *tmp;
+
+ list_for_each_entry_safe(entry, tmp, &hdev->adv_entries, list) {
+ list_del(&entry->list);
+ kfree(entry);
+ }
+
+ BT_DBG("%s adv cache cleared", hdev->name);
+
+ return 0;
+}
+
+struct adv_entry *hci_find_adv_entry(struct hci_dev *hdev, bdaddr_t *bdaddr)
+{
+ struct adv_entry *entry;
+
+ list_for_each_entry(entry, &hdev->adv_entries, list)
+ if (bacmp(bdaddr, &entry->bdaddr) == 0)
+ return entry;
+
+ return NULL;
+}
+
+static inline int is_connectable_adv(u8 evt_type)
+{
+ if (evt_type == ADV_IND || evt_type == ADV_DIRECT_IND)
+ return 1;
+
+ return 0;
+}
+
+int hci_add_adv_entry(struct hci_dev *hdev,
+ struct hci_ev_le_advertising_info *ev)
+{
+ struct adv_entry *entry;
+
+ if (!is_connectable_adv(ev->evt_type))
+ return -EINVAL;
+
+ /* Only new entries should be added to adv_entries. So, if
+ * bdaddr was found, don't add it. */
+ if (hci_find_adv_entry(hdev, &ev->bdaddr))
+ return 0;
+
+ entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
+ if (!entry)
+ return -ENOMEM;
+
+ bacpy(&entry->bdaddr, &ev->bdaddr);
+ entry->bdaddr_type = ev->bdaddr_type;
+
+ list_add(&entry->list, &hdev->adv_entries);
+
+ BT_DBG("%s adv entry added: address %s type %u", hdev->name,
+ batostr(&entry->bdaddr), entry->bdaddr_type);
+
+ return 0;
+}
+
/* Register HCI device */
int hci_register_dev(struct hci_dev *hdev)
{
@@ -1270,6 +1331,8 @@ int hci_register_dev(struct hci_dev *hdev)

INIT_LIST_HEAD(&hdev->remote_oob_data);

+ INIT_LIST_HEAD(&hdev->adv_entries);
+
INIT_WORK(&hdev->power_on, hci_power_on);
INIT_WORK(&hdev->power_off, hci_power_off);
setup_timer(&hdev->off_timer, hci_auto_off, (unsigned long) hdev);
@@ -1350,6 +1413,7 @@ int hci_unregister_dev(struct hci_dev *hdev)
hci_uuids_clear(hdev);
hci_link_keys_clear(hdev);
hci_remote_oob_data_clear(hdev);
+ hci_adv_entries_clear(hdev);
hci_dev_unlock_bh(hdev);

__hci_dev_put(hdev);
--
1.7.4.1


2011-06-09 18:20:21

by Claudio Takahasi

[permalink] [raw]
Subject: Re: [PATCH v2 06/11] Bluetooth: Advertising entries lifetime

Hi Luiz

On Tue, Jun 7, 2011 at 4:08 PM, Andre Guedes <[email protected]> wrote:
> Hi Luiz,
>
> On Tue, Jun 7, 2011 at 2:18 AM, Luiz Augusto von Dentz
> <[email protected]> wrote:
>> Hi Andre,
>>
>> On Sat, May 21, 2011 at 9:10 AM, Andre Guedes
>> <[email protected]> wrote:
>>> This patch adds a timer to clear 'adv_entries' after three minutes.
>>>
>>> After some amount of time, the advertising entries cached during
>>> the last LE scan should be considered expired and they should be
>>> removed from the advertising cache.
>>>
>>> It was chosen a three minutes timeout as an initial attempt. This
>>> value might change in future.
>>>
>>> Signed-off-by: Andre Guedes <[email protected]>
>>> ---
>>>  include/net/bluetooth/hci_core.h |    2 ++
>>>  net/bluetooth/hci_core.c         |   14 ++++++++++++++
>>>  net/bluetooth/hci_event.c        |    6 +++++-
>>>  3 files changed, 21 insertions(+), 1 deletions(-)
>>>
>>> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
>>> index 10dfb85..af4b0ed 100644
>>> --- a/include/net/bluetooth/hci_core.h
>>> +++ b/include/net/bluetooth/hci_core.h
>>> @@ -188,6 +188,7 @@ struct hci_dev {
>>>        struct list_head        remote_oob_data;
>>>
>>>        struct list_head        adv_entries;
>>> +       struct timer_list       adv_timer;
>>>
>>>        struct hci_dev_stats    stat;
>>>
>>> @@ -535,6 +536,7 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash,
>>>                                                                u8 *randomizer);
>>>  int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr);
>>>
>>> +#define ADV_CLEAR_TIMEOUT (3*60*HZ) /* Three minutes */
>>>  int hci_adv_entries_clear(struct hci_dev *hdev);
>>>  struct adv_entry *hci_find_adv_entry(struct hci_dev *hdev, bdaddr_t *bdaddr);
>>>  int hci_add_adv_entry(struct hci_dev *hdev,
>>> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
>>> index dd27f97..5040c3f 100644
>>> --- a/net/bluetooth/hci_core.c
>>> +++ b/net/bluetooth/hci_core.c
>>> @@ -1204,6 +1204,17 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash,
>>>        return 0;
>>>  }
>>>
>>> +static void hci_clear_adv_cache(unsigned long arg)
>>> +{
>>> +       struct hci_dev *hdev = (void *) arg;
>>> +
>>> +       hci_dev_lock(hdev);
>>> +
>>> +       hci_adv_entries_clear(hdev);
>>> +
>>> +       hci_dev_unlock(hdev);
>>> +}
>>> +
>>>  int hci_adv_entries_clear(struct hci_dev *hdev)
>>>  {
>>>        struct adv_entry *entry, *tmp;
>>> @@ -1332,6 +1343,8 @@ int hci_register_dev(struct hci_dev *hdev)
>>>        INIT_LIST_HEAD(&hdev->remote_oob_data);
>>>
>>>        INIT_LIST_HEAD(&hdev->adv_entries);
>>> +       setup_timer(&hdev->adv_timer, hci_clear_adv_cache,
>>> +                                               (unsigned long) hdev);
>>>
>>>        INIT_WORK(&hdev->power_on, hci_power_on);
>>>        INIT_WORK(&hdev->power_off, hci_power_off);
>>> @@ -1405,6 +1418,7 @@ int hci_unregister_dev(struct hci_dev *hdev)
>>>        hci_unregister_sysfs(hdev);
>>>
>>>        hci_del_off_timer(hdev);
>>> +       del_timer(&hdev->adv_timer);
>>>
>>>        destroy_workqueue(hdev->workqueue);
>>>
>>> diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
>>> index 85e12d8..8d6dc1e 100644
>>> --- a/net/bluetooth/hci_event.c
>>> +++ b/net/bluetooth/hci_event.c
>>> @@ -859,8 +859,12 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
>>>
>>>        hci_dev_lock(hdev);
>>>
>>> -       if (param_scan_enable == 0x01)
>>> +       if (param_scan_enable == 0x01) {
>>> +               del_timer(&hdev->adv_timer);
>>>                hci_adv_entries_clear(hdev);
>>> +       } else if (param_scan_enable == 0x00) {
>>> +               mod_timer(&hdev->adv_timer, jiffies + ADV_CLEAR_TIMEOUT);
>>> +       }
>>>
>>>        hci_dev_unlock(hdev);
>>>  }
>>> --
>>> 1.7.4.1
>>
>> Maybe we should not trigger the timer if the we are connected to the
>> device, this would be very convenient if a disconnect happen for
>> unknown reason e.g. bug or crash so we can quickly reconnect without
>> having to scan again, once disconnected then we start the entry timer,
>> what do you think?
>>
>
> I think keeping the advertising entry from the devices we are connected to
> may be a good idea.
>
> The spec says "When a device in the directed connectable mode establishes a
> connection, the device will exit this mode and enter the non-connectable mode".
> So, fast reconnection attempts will fail since the device is in non-connectable
> mode. However, once the connection is dropped, some LE applications will enter
> in connectable mode ASAP (see proximity or health thermometer profiles).
>
> So, I'm not sure we will have much gain implementing this approach. But it
> would be nice to do some experiments to see this in practice.
>
> BTW, instead of deactivating/activating the adv timer, I think a bit better
> approach would be modifying the hci_adv_entries_clear() so it doesn't remove
> the adv entries from devices we are connected to. This way we would keep only
> fresh entries in the advertising cache and we can perform a LE scan normally.

Complementing what Andre wrote: This approach will improve re-connections.
However passive scanning combined with automatic connection management
should be our target. After reboot the cache will be lost and an
active or passive
scanning will be necessary to refresh the cache otherwise connection will always
fail.

If we control "automatic" connections in the userspace, the next discussion will
be how to control passive scanning using management interface.

BR,
Claudio

>
>>
>> --
>> Luiz Augusto von Dentz
>> Computer Engineer
>>
>
> BR,
>
> Andre Guedes.
> --
> 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
>

2011-06-07 19:08:20

by Andre Guedes

[permalink] [raw]
Subject: Re: [PATCH v2 06/11] Bluetooth: Advertising entries lifetime

Hi Luiz,

On Tue, Jun 7, 2011 at 2:18 AM, Luiz Augusto von Dentz
<[email protected]> wrote:
> Hi Andre,
>
> On Sat, May 21, 2011 at 9:10 AM, Andre Guedes
> <[email protected]> wrote:
>> This patch adds a timer to clear 'adv_entries' after three minutes.
>>
>> After some amount of time, the advertising entries cached during
>> the last LE scan should be considered expired and they should be
>> removed from the advertising cache.
>>
>> It was chosen a three minutes timeout as an initial attempt. This
>> value might change in future.
>>
>> Signed-off-by: Andre Guedes <[email protected]>
>> ---
>> ?include/net/bluetooth/hci_core.h | ? ?2 ++
>> ?net/bluetooth/hci_core.c ? ? ? ? | ? 14 ++++++++++++++
>> ?net/bluetooth/hci_event.c ? ? ? ?| ? ?6 +++++-
>> ?3 files changed, 21 insertions(+), 1 deletions(-)
>>
>> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
>> index 10dfb85..af4b0ed 100644
>> --- a/include/net/bluetooth/hci_core.h
>> +++ b/include/net/bluetooth/hci_core.h
>> @@ -188,6 +188,7 @@ struct hci_dev {
>> ? ? ? ?struct list_head ? ? ? ?remote_oob_data;
>>
>> ? ? ? ?struct list_head ? ? ? ?adv_entries;
>> + ? ? ? struct timer_list ? ? ? adv_timer;
>>
>> ? ? ? ?struct hci_dev_stats ? ?stat;
>>
>> @@ -535,6 +536,7 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash,
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?u8 *randomizer);
>> ?int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr);
>>
>> +#define ADV_CLEAR_TIMEOUT (3*60*HZ) /* Three minutes */
>> ?int hci_adv_entries_clear(struct hci_dev *hdev);
>> ?struct adv_entry *hci_find_adv_entry(struct hci_dev *hdev, bdaddr_t *bdaddr);
>> ?int hci_add_adv_entry(struct hci_dev *hdev,
>> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
>> index dd27f97..5040c3f 100644
>> --- a/net/bluetooth/hci_core.c
>> +++ b/net/bluetooth/hci_core.c
>> @@ -1204,6 +1204,17 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash,
>> ? ? ? ?return 0;
>> ?}
>>
>> +static void hci_clear_adv_cache(unsigned long arg)
>> +{
>> + ? ? ? struct hci_dev *hdev = (void *) arg;
>> +
>> + ? ? ? hci_dev_lock(hdev);
>> +
>> + ? ? ? hci_adv_entries_clear(hdev);
>> +
>> + ? ? ? hci_dev_unlock(hdev);
>> +}
>> +
>> ?int hci_adv_entries_clear(struct hci_dev *hdev)
>> ?{
>> ? ? ? ?struct adv_entry *entry, *tmp;
>> @@ -1332,6 +1343,8 @@ int hci_register_dev(struct hci_dev *hdev)
>> ? ? ? ?INIT_LIST_HEAD(&hdev->remote_oob_data);
>>
>> ? ? ? ?INIT_LIST_HEAD(&hdev->adv_entries);
>> + ? ? ? setup_timer(&hdev->adv_timer, hci_clear_adv_cache,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (unsigned long) hdev);
>>
>> ? ? ? ?INIT_WORK(&hdev->power_on, hci_power_on);
>> ? ? ? ?INIT_WORK(&hdev->power_off, hci_power_off);
>> @@ -1405,6 +1418,7 @@ int hci_unregister_dev(struct hci_dev *hdev)
>> ? ? ? ?hci_unregister_sysfs(hdev);
>>
>> ? ? ? ?hci_del_off_timer(hdev);
>> + ? ? ? del_timer(&hdev->adv_timer);
>>
>> ? ? ? ?destroy_workqueue(hdev->workqueue);
>>
>> diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
>> index 85e12d8..8d6dc1e 100644
>> --- a/net/bluetooth/hci_event.c
>> +++ b/net/bluetooth/hci_event.c
>> @@ -859,8 +859,12 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
>>
>> ? ? ? ?hci_dev_lock(hdev);
>>
>> - ? ? ? if (param_scan_enable == 0x01)
>> + ? ? ? if (param_scan_enable == 0x01) {
>> + ? ? ? ? ? ? ? del_timer(&hdev->adv_timer);
>> ? ? ? ? ? ? ? ?hci_adv_entries_clear(hdev);
>> + ? ? ? } else if (param_scan_enable == 0x00) {
>> + ? ? ? ? ? ? ? mod_timer(&hdev->adv_timer, jiffies + ADV_CLEAR_TIMEOUT);
>> + ? ? ? }
>>
>> ? ? ? ?hci_dev_unlock(hdev);
>> ?}
>> --
>> 1.7.4.1
>
> Maybe we should not trigger the timer if the we are connected to the
> device, this would be very convenient if a disconnect happen for
> unknown reason e.g. bug or crash so we can quickly reconnect without
> having to scan again, once disconnected then we start the entry timer,
> what do you think?
>

I think keeping the advertising entry from the devices we are connected to
may be a good idea.

The spec says "When a device in the directed connectable mode establishes a
connection, the device will exit this mode and enter the non-connectable mode".
So, fast reconnection attempts will fail since the device is in non-connectable
mode. However, once the connection is dropped, some LE applications will enter
in connectable mode ASAP (see proximity or health thermometer profiles).

So, I'm not sure we will have much gain implementing this approach. But it
would be nice to do some experiments to see this in practice.

BTW, instead of deactivating/activating the adv timer, I think a bit better
approach would be modifying the hci_adv_entries_clear() so it doesn't remove
the adv entries from devices we are connected to. This way we would keep only
fresh entries in the advertising cache and we can perform a LE scan normally.

>
> --
> Luiz Augusto von Dentz
> Computer Engineer
>

BR,

Andre Guedes.

2011-06-07 15:32:29

by Anderson Lizardo

[permalink] [raw]
Subject: Re: [PATCH v2 06/11] Bluetooth: Advertising entries lifetime

Hi Johan,

On Tue, Jun 7, 2011 at 11:02 AM, Johan Hedberg <[email protected]> wrote:
> Hi Luiz,
>
> On Tue, Jun 07, 2011, Luiz Augusto von Dentz wrote:
>> Maybe we should not trigger the timer if the we are connected to the
>> device, this would be very convenient if a disconnect happen for
>> unknown reason e.g. bug or crash so we can quickly reconnect without
>> having to scan again, once disconnected then we start the entry timer,
>> what do you think?
>
> Initially this sounds like a good idea, however almost all of the
> devices we've tested with automatically disable advertising when
> connected so an immediate reconnect attempt like that would fail in most
> cases.

Correct. And by reading the connection procedures from specs, looks
like this is intentional, because they leave the "connectable mode".
Devices which want to be reconnected (e.g. which have a pending
indication) should reenter connectable mode manually. The spec also
describes when the adapter should re-attempt connection establishment.
Therefore, this is GATT profile specific and IMHO we cannot hard-code
connection mode behavior on the kernel.

Vol. 3, Part C, Section 9 describes all the available operational modes.

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

2011-06-07 15:02:02

by Johan Hedberg

[permalink] [raw]
Subject: Re: [PATCH v2 06/11] Bluetooth: Advertising entries lifetime

Hi Luiz,

On Tue, Jun 07, 2011, Luiz Augusto von Dentz wrote:
> Maybe we should not trigger the timer if the we are connected to the
> device, this would be very convenient if a disconnect happen for
> unknown reason e.g. bug or crash so we can quickly reconnect without
> having to scan again, once disconnected then we start the entry timer,
> what do you think?

Initially this sounds like a good idea, however almost all of the
devices we've tested with automatically disable advertising when
connected so an immediate reconnect attempt like that would fail in most
cases.

Johan

2011-06-07 05:18:07

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: Re: [PATCH v2 06/11] Bluetooth: Advertising entries lifetime

Hi Andre,

On Sat, May 21, 2011 at 9:10 AM, Andre Guedes
<[email protected]> wrote:
> This patch adds a timer to clear 'adv_entries' after three minutes.
>
> After some amount of time, the advertising entries cached during
> the last LE scan should be considered expired and they should be
> removed from the advertising cache.
>
> It was chosen a three minutes timeout as an initial attempt. This
> value might change in future.
>
> Signed-off-by: Andre Guedes <[email protected]>
> ---
> ?include/net/bluetooth/hci_core.h | ? ?2 ++
> ?net/bluetooth/hci_core.c ? ? ? ? | ? 14 ++++++++++++++
> ?net/bluetooth/hci_event.c ? ? ? ?| ? ?6 +++++-
> ?3 files changed, 21 insertions(+), 1 deletions(-)
>
> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> index 10dfb85..af4b0ed 100644
> --- a/include/net/bluetooth/hci_core.h
> +++ b/include/net/bluetooth/hci_core.h
> @@ -188,6 +188,7 @@ struct hci_dev {
> ? ? ? ?struct list_head ? ? ? ?remote_oob_data;
>
> ? ? ? ?struct list_head ? ? ? ?adv_entries;
> + ? ? ? struct timer_list ? ? ? adv_timer;
>
> ? ? ? ?struct hci_dev_stats ? ?stat;
>
> @@ -535,6 +536,7 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?u8 *randomizer);
> ?int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr);
>
> +#define ADV_CLEAR_TIMEOUT (3*60*HZ) /* Three minutes */
> ?int hci_adv_entries_clear(struct hci_dev *hdev);
> ?struct adv_entry *hci_find_adv_entry(struct hci_dev *hdev, bdaddr_t *bdaddr);
> ?int hci_add_adv_entry(struct hci_dev *hdev,
> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> index dd27f97..5040c3f 100644
> --- a/net/bluetooth/hci_core.c
> +++ b/net/bluetooth/hci_core.c
> @@ -1204,6 +1204,17 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash,
> ? ? ? ?return 0;
> ?}
>
> +static void hci_clear_adv_cache(unsigned long arg)
> +{
> + ? ? ? struct hci_dev *hdev = (void *) arg;
> +
> + ? ? ? hci_dev_lock(hdev);
> +
> + ? ? ? hci_adv_entries_clear(hdev);
> +
> + ? ? ? hci_dev_unlock(hdev);
> +}
> +
> ?int hci_adv_entries_clear(struct hci_dev *hdev)
> ?{
> ? ? ? ?struct adv_entry *entry, *tmp;
> @@ -1332,6 +1343,8 @@ int hci_register_dev(struct hci_dev *hdev)
> ? ? ? ?INIT_LIST_HEAD(&hdev->remote_oob_data);
>
> ? ? ? ?INIT_LIST_HEAD(&hdev->adv_entries);
> + ? ? ? setup_timer(&hdev->adv_timer, hci_clear_adv_cache,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (unsigned long) hdev);
>
> ? ? ? ?INIT_WORK(&hdev->power_on, hci_power_on);
> ? ? ? ?INIT_WORK(&hdev->power_off, hci_power_off);
> @@ -1405,6 +1418,7 @@ int hci_unregister_dev(struct hci_dev *hdev)
> ? ? ? ?hci_unregister_sysfs(hdev);
>
> ? ? ? ?hci_del_off_timer(hdev);
> + ? ? ? del_timer(&hdev->adv_timer);
>
> ? ? ? ?destroy_workqueue(hdev->workqueue);
>
> diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
> index 85e12d8..8d6dc1e 100644
> --- a/net/bluetooth/hci_event.c
> +++ b/net/bluetooth/hci_event.c
> @@ -859,8 +859,12 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
>
> ? ? ? ?hci_dev_lock(hdev);
>
> - ? ? ? if (param_scan_enable == 0x01)
> + ? ? ? if (param_scan_enable == 0x01) {
> + ? ? ? ? ? ? ? del_timer(&hdev->adv_timer);
> ? ? ? ? ? ? ? ?hci_adv_entries_clear(hdev);
> + ? ? ? } else if (param_scan_enable == 0x00) {
> + ? ? ? ? ? ? ? mod_timer(&hdev->adv_timer, jiffies + ADV_CLEAR_TIMEOUT);
> + ? ? ? }
>
> ? ? ? ?hci_dev_unlock(hdev);
> ?}
> --
> 1.7.4.1

Maybe we should not trigger the timer if the we are connected to the
device, this would be very convenient if a disconnect happen for
unknown reason e.g. bug or crash so we can quickly reconnect without
having to scan again, once disconnected then we start the entry timer,
what do you think?


--
Luiz Augusto von Dentz
Computer Engineer