2011-05-06 17:05:09

by Andre Guedes

[permalink] [raw]
Subject: [PATCH 00/12] Caching LE advertising information

Hi all,

This patchset implements the LE advertising cache which is used
to establish LE connections.

Today, we cannot establish LE connections (via l2cap socket) with
devices which use random address type. To achieve that, we came up
with a solution where the host should be able to infer the address
type (public or random) from the device it wants to connect to.

The approach this patchset implements is: during the LE scanning,
the host stores the address and the address type gathered from
advertising reports. These information are stored at the advertising
cache. So, during a LE connection, the host looks up the advertising
cache and gets the address type from the device it wants to connect
to.

Since the penality to connect to an unreachable device is relatively
high, we must keep only fresh advertising entries in the advertising
cache. So, before each LE scanning the advertising cache is cleared.
Also, after the LE scanning, a timer is set to clear the cache.

Thanks,

Andre Guedes.

Anderson Briglia (2):
Bluetooth: Add advertising report meta event structs
Bluetooth: Add advertising report meta event handler

Andre Guedes (10):
Bluetooth: LE advertising cache
Bluetooth: Protect 'adv_entries' with a RW lock
Bluetooth: LE Set Scan Enable command complete event
Bluetooth: Clear advertising cache before scanning
Bluetooth: Advertising entries lifetime
Bluetooth: Add 'dst_type' field to struct hci_conn
Bluetooth: Add hci_le_conn_add()
Bluetooth: Remove useless check in hci_connect()
Bluetooth: Check advertising cache in hci_connect()
Bluetooth: Set 'peer_addr_type' in hci_le_connect()

include/net/bluetooth/hci.h | 21 ++++++++
include/net/bluetooth/hci_core.h | 19 ++++++++
net/bluetooth/hci_conn.c | 26 +++++++++-
net/bluetooth/hci_core.c | 96 ++++++++++++++++++++++++++++++++++++++
net/bluetooth/hci_event.c | 56 +++++++++++++++++++++-
5 files changed, 213 insertions(+), 5 deletions(-)



2011-05-17 18:43:52

by Gustavo Padovan

[permalink] [raw]
Subject: Re: [PATCH 02/12] Bluetooth: LE advertising cache

* Andre Guedes <[email protected]> [2011-05-17 15:22:31 -0300]:

> Hi Gustavo,
>
> On Fri, May 13, 2011 at 4:33 PM, Gustavo F. Padovan
> <[email protected]> wrote:
> > Hi Andre,
> >
> > * Andre Guedes <[email protected]> [2011-05-06 14:05:11 -0300]:
> >
> >> 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 ? ? ? ? | ? 74 ++++++++++++++++++++++++++++++++++++++
> >> ?2 files changed, 87 insertions(+), 0 deletions(-)
> >>
> >> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> >> index 14cc324..65135f8 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;
> >> @@ -526,6 +534,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);
> >
> > Rename this to hci_adv_add_entry()
> >
>
> 'adv_entry' is the element of the list. So, to follow the standard IMO
> we should keep the name hci_add_adv_entry(). See others functions
> like hci_add_link_key() and hci_add_remote_oob_data().

Fair enough. Keep it hci_add_adv_entry()

--
Gustavo F. Padovan
http://profusion.mobi

2011-05-17 18:22:31

by Andre Guedes

[permalink] [raw]
Subject: Re: [PATCH 02/12] Bluetooth: LE advertising cache

Hi Gustavo,

On Fri, May 13, 2011 at 4:33 PM, Gustavo F. Padovan
<[email protected]> wrote:
> Hi Andre,
>
> * Andre Guedes <[email protected]> [2011-05-06 14:05:11 -0300]:
>
>> 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 ? ? ? ? | ? 74 ++++++++++++++++++++++++++++++++++++++
>> ?2 files changed, 87 insertions(+), 0 deletions(-)
>>
>> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
>> index 14cc324..65135f8 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;
>> @@ -526,6 +534,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);
>
> Rename this to hci_adv_add_entry()
>

'adv_entry' is the element of the list. So, to follow the standard IMO
we should keep the name hci_add_adv_entry(). See others functions
like hci_add_link_key() and hci_add_remote_oob_data().

>> +
>> ?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..0ba3c39 100644
>> --- a/net/bluetooth/hci_core.c
>> +++ b/net/bluetooth/hci_core.c
>> @@ -1204,6 +1204,77 @@ 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 list_head *p, *n;
>> +
>> + ? ? list_for_each_safe(p, n, &hdev->adv_entries) {
>
> list_for_each_entry_safe() here.
>
>> + ? ? ? ? ? ? struct adv_entry *entry;
>> +
>> + ? ? ? ? ? ? entry = list_entry(p, struct adv_entry, list);
>> +
>> + ? ? ? ? ? ? list_del(p);
>> + ? ? ? ? ? ? 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 list_head *p;
>> +
>> + ? ? list_for_each(p, &hdev->adv_entries) {
>
> list_for_each_entry() here.
>
>> + ? ? ? ? ? ? struct adv_entry *entry;
>> +
>> + ? ? ? ? ? ? entry = list_entry(p, struct adv_entry, 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;
>
> You use this function just in one place, get rid of it.
>

Yes, this function is used just in one place. It was created to
improve code's readability since

if (is_connectable_adv())
do_something()

means much more than

if (evt_type == ADV_IND || evt_type == ADV_DIRECT_IND)
do_something()

>> +}
>> +
>> +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;
>> +
>> + ? ? entry = hci_find_adv_entry(hdev, &ev->bdaddr);
>> + ? ? /* Only new entries should be added to adv_entries. So, if
>> + ? ? ?* bdaddr was found, don't add it. */
>> + ? ? if (entry)
>> + ? ? ? ? ? ? return 0;
>
> ? ? ? ?if (hci_find_adv_entry())
> ? ? ? ? ? ? ? ?return 0;
>
> --
> Gustavo F. Padovan
> http://profusion.mobi
>

BR,

Andre Guedes.

2011-05-17 14:39:11

by Andre Guedes

[permalink] [raw]
Subject: Re: [PATCH 03/12] Bluetooth: Protect 'adv_entries' with a RW lock

Hi Marcel,

On Wed, May 11, 2011 at 10:24 PM, Marcel Holtmann <[email protected]> wro=
te:
> Hi Andre,
>
>> This patch adds a RW lock to protect concurrent operations on
>> adv_entries list.
>>
>> Signed-off-by: Andre Guedes <[email protected]>
>> ---
>> =A0include/net/bluetooth/hci_core.h | =A0 =A01 +
>> =A0net/bluetooth/hci_core.c =A0 =A0 =A0 =A0 | =A0 21 +++++++++++++++++--=
--
>> =A02 files changed, 18 insertions(+), 4 deletions(-)
>>
>> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hc=
i_core.h
>> index 65135f8..2ceeadf 100644
>> --- a/include/net/bluetooth/hci_core.h
>> +++ b/include/net/bluetooth/hci_core.h
>> @@ -188,6 +188,7 @@ struct hci_dev {
>> =A0 =A0 =A0 struct list_head =A0 =A0 =A0 =A0remote_oob_data;
>>
>> =A0 =A0 =A0 struct list_head =A0 =A0 =A0 =A0adv_entries;
>> + =A0 =A0 rwlock_t =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0adv_entries_lock;
>
> we might wanna consider just using spinlocks and not rwlocks. Also can
> you please look into using RCU.
>
> Regards
>
> Marcel
>
>
>

Ok. I will use hci_dev_lock and friends to protect adv_entries.
This is the approach already used to protect uuids, link_keys,
remote_oob_data lists.

About RCU, I see the point in using it, but since reading operations
in adv_entries are not _extremely_ requested, IMO, we'll not have
much performance gain here. Anyway, the changes to use RCU
are straightforward. So, let me know if you wanna try RCU to
protect the advertising cache.

BR,

Andre Guedes.

2011-05-13 19:33:26

by Gustavo Padovan

[permalink] [raw]
Subject: Re: [PATCH 02/12] Bluetooth: LE advertising cache

Hi Andre,

* Andre Guedes <[email protected]> [2011-05-06 14:05:11 -0300]:

> 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 | 74 ++++++++++++++++++++++++++++++++++++++
> 2 files changed, 87 insertions(+), 0 deletions(-)
>
> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> index 14cc324..65135f8 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;
> @@ -526,6 +534,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);

Rename this to hci_adv_add_entry()

> +
> 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..0ba3c39 100644
> --- a/net/bluetooth/hci_core.c
> +++ b/net/bluetooth/hci_core.c
> @@ -1204,6 +1204,77 @@ 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 list_head *p, *n;
> +
> + list_for_each_safe(p, n, &hdev->adv_entries) {

list_for_each_entry_safe() here.

> + struct adv_entry *entry;
> +
> + entry = list_entry(p, struct adv_entry, list);
> +
> + list_del(p);
> + 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 list_head *p;
> +
> + list_for_each(p, &hdev->adv_entries) {

list_for_each_entry() here.

> + struct adv_entry *entry;
> +
> + entry = list_entry(p, struct adv_entry, 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;

You use this function just in one place, get rid of it.

> +}
> +
> +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;
> +
> + entry = hci_find_adv_entry(hdev, &ev->bdaddr);
> + /* Only new entries should be added to adv_entries. So, if
> + * bdaddr was found, don't add it. */
> + if (entry)
> + return 0;

if (hci_find_adv_entry())
return 0;

--
Gustavo F. Padovan
http://profusion.mobi

2011-05-12 01:27:18

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [PATCH 09/12] Bluetooth: Add hci_le_conn_add()

Hi Andre,

> This patch implements a wrapper function to hci_conn_add() which
> takes the address type as argument. This patch also replaces
> hci_conn_add() calls by hci_le_conn_add() in LE related code.
>
> hci_le_conn_add() was created to consider the destination address
> type when creating a new LE hci_conn.
>
> Signed-off-by: Andre Guedes <[email protected]>
> ---
> include/net/bluetooth/hci_core.h | 2 ++
> net/bluetooth/hci_conn.c | 14 +++++++++++++-
> net/bluetooth/hci_event.c | 5 +++--
> 3 files changed, 18 insertions(+), 3 deletions(-)
>
> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> index 5e64d3f..6dd7cad 100644
> --- a/include/net/bluetooth/hci_core.h
> +++ b/include/net/bluetooth/hci_core.h
> @@ -427,6 +427,8 @@ 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_le_conn_add(struct hci_dev *hdev, bdaddr_t *dst,
> + __u8 addr_type);

the reason why we never split hci_conn_add is too keep it simple. So
better just add the dst_type there directly and only use it when LE_LINK
or we split this clearly in SCO, ACL and LE links. This way is just
half-baked.

Regards

Marcel



2011-05-12 01:24:34

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [PATCH 03/12] Bluetooth: Protect 'adv_entries' with a RW lock

Hi Andre,

> This patch adds a RW lock to protect concurrent operations on
> adv_entries list.
>
> Signed-off-by: Andre Guedes <[email protected]>
> ---
> include/net/bluetooth/hci_core.h | 1 +
> net/bluetooth/hci_core.c | 21 +++++++++++++++++----
> 2 files changed, 18 insertions(+), 4 deletions(-)
>
> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> index 65135f8..2ceeadf 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;
> + rwlock_t adv_entries_lock;

we might wanna consider just using spinlocks and not rwlocks. Also can
you please look into using RCU.

Regards

Marcel



2011-05-12 01:23:34

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [PATCH 00/12] Caching LE advertising information

Hi Andre,

> This patchset implements the LE advertising cache which is used
> to establish LE connections.
>
> Today, we cannot establish LE connections (via l2cap socket) with
> devices which use random address type. To achieve that, we came up
> with a solution where the host should be able to infer the address
> type (public or random) from the device it wants to connect to.
>
> The approach this patchset implements is: during the LE scanning,
> the host stores the address and the address type gathered from
> advertising reports. These information are stored at the advertising
> cache. So, during a LE connection, the host looks up the advertising
> cache and gets the address type from the device it wants to connect
> to.

I would prefer if we try using the cache as long as possible. As long as
this works out it should be fine. Adding the BDADDR_TYPE to all public
socket address structures seems a bit of a pain to me.

And as backup we can always revert to that, but we can never ever remove
that address from the socket structure. While we can remove the cache if
we no longer need it.

Regards

Marcel



2011-05-06 17:05:21

by Andre Guedes

[permalink] [raw]
Subject: [PATCH 12/12] 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 ed9ca28..18081a7 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.1


2011-05-06 17:05:20

by Andre Guedes

[permalink] [raw]
Subject: [PATCH 11/12] 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 b67c83c..ed9ca28 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -459,10 +459,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_le_conn_add(hdev, dst, 0);
+
+ entry = hci_find_adv_entry(hdev, dst);
+ if (!entry)
+ return ERR_PTR(-EHOSTUNREACH);
+
+ le = hci_le_conn_add(hdev, dst, entry->bdaddr_type);
if (!le)
return ERR_PTR(-ENOMEM);

--
1.7.1


2011-05-06 17:05:19

by Andre Guedes

[permalink] [raw]
Subject: [PATCH 10/12] Bluetooth: Remove useless check in hci_connect()

There is no need to check the connection's state since hci_le_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 8896174..b67c83c 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -465,8 +465,8 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8
le = hci_le_conn_add(hdev, 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.1


2011-05-06 17:05:18

by Andre Guedes

[permalink] [raw]
Subject: [PATCH 09/12] Bluetooth: Add hci_le_conn_add()

This patch implements a wrapper function to hci_conn_add() which
takes the address type as argument. This patch also replaces
hci_conn_add() calls by hci_le_conn_add() in LE related code.

hci_le_conn_add() was created to consider the destination address
type when creating a new LE hci_conn.

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

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 5e64d3f..6dd7cad 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -427,6 +427,8 @@ 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_le_conn_add(struct hci_dev *hdev, bdaddr_t *dst,
+ __u8 addr_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 7f5ad8a..8896174 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -347,6 +347,18 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
return conn;
}

+struct hci_conn *hci_le_conn_add(struct hci_dev *hdev, bdaddr_t *dst,
+ __u8 addr_type)
+{
+ struct hci_conn *conn = hci_conn_add(hdev, LE_LINK, dst);
+ if (!conn)
+ return NULL;
+
+ conn->dst_type = addr_type;
+
+ return conn;
+}
+
int hci_conn_del(struct hci_conn *conn)
{
struct hci_dev *hdev = conn->hdev;
@@ -450,7 +462,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_le_conn_add(hdev, dst, 0);
if (!le)
return ERR_PTR(-ENOMEM);
if (le->state == BT_OPEN)
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index a676757..8c0e3b4 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1231,7 +1231,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_le_conn_add(hdev, &cp->peer_addr,
+ cp->peer_addr_type);
if (conn)
conn->out = 1;
else
@@ -2679,7 +2680,7 @@ 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_le_conn_add(hdev, &ev->bdaddr, ev->bdaddr_type);
if (!conn) {
BT_ERR("No memory for new connection");
hci_dev_unlock(hdev);
--
1.7.1


2011-05-06 17:05:17

by Andre Guedes

[permalink] [raw]
Subject: [PATCH 08/12] 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 7b5c991..5e64d3f 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -225,6 +225,7 @@ struct hci_conn {
spinlock_t lock;

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


2011-05-06 17:05:16

by Andre Guedes

[permalink] [raw]
Subject: [PATCH 07/12] 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 | 9 +++++++++
net/bluetooth/hci_event.c | 6 +++++-
3 files changed, 16 insertions(+), 1 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 2ceeadf..7b5c991 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -189,6 +189,7 @@ struct hci_dev {

struct list_head adv_entries;
rwlock_t adv_entries_lock;
+ 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 89d7cc8..b0b12ac 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1204,6 +1204,13 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash,
return 0;
}

+static void hci_adv_clear(unsigned long arg)
+{
+ struct hci_dev *hdev = (void *) arg;
+
+ hci_adv_entries_clear(hdev);
+}
+
int hci_adv_entries_clear(struct hci_dev *hdev)
{
struct list_head *p, *n;
@@ -1355,6 +1362,7 @@ int hci_register_dev(struct hci_dev *hdev)

INIT_LIST_HEAD(&hdev->adv_entries);
rwlock_init(&hdev->adv_entries_lock);
+ setup_timer(&hdev->adv_timer, hci_adv_clear, (unsigned long) hdev);

INIT_WORK(&hdev->power_on, hci_power_on);
INIT_WORK(&hdev->power_off, hci_power_off);
@@ -1428,6 +1436,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 600425a..a676757 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -856,8 +856,12 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
return;

param_scan_enable = *((__u8 *) sent);
- 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);
+ }
}

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


2011-05-06 17:05:15

by Andre Guedes

[permalink] [raw]
Subject: [PATCH 06/12] 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 | 13 +++++++++++++
1 files changed, 13 insertions(+), 0 deletions(-)

diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 8305abf..600425a 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -842,9 +842,22 @@ 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);
+ if (param_scan_enable == 0x01)
+ hci_adv_entries_clear(hdev);
}

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


2011-05-06 17:05:14

by Andre Guedes

[permalink] [raw]
Subject: [PATCH 05/12] 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 3fb36bc..8305abf 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.1


2011-05-06 17:05:13

by Andre Guedes

[permalink] [raw]
Subject: [PATCH 04/12] Bluetooth: Add advertising report meta event handler

From: Anderson Briglia <[email protected]>

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

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

diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index d5aa97e..3fb36bc 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2677,6 +2677,24 @@ 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_add_adv_entry(hdev, ev);
+
+ while (--num_reports) {
+ ev = (void *) (ev->data + ev->length + RSSI_SIZE);
+ hci_add_adv_entry(hdev, ev);
+ }
+}
+
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;
@@ -2688,6 +2706,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.1


2011-05-06 17:05:12

by Andre Guedes

[permalink] [raw]
Subject: [PATCH 03/12] Bluetooth: Protect 'adv_entries' with a RW lock

This patch adds a RW lock to protect concurrent operations on
adv_entries list.

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

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 65135f8..2ceeadf 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;
+ rwlock_t adv_entries_lock;

struct hci_dev_stats stat;

diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 0ba3c39..89d7cc8 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1208,6 +1208,8 @@ int hci_adv_entries_clear(struct hci_dev *hdev)
{
struct list_head *p, *n;

+ write_lock_bh(&hdev->adv_entries_lock);
+
list_for_each_safe(p, n, &hdev->adv_entries) {
struct adv_entry *entry;

@@ -1217,6 +1219,8 @@ int hci_adv_entries_clear(struct hci_dev *hdev)
kfree(entry);
}

+ write_unlock_bh(&hdev->adv_entries_lock);
+
BT_DBG("%s adv cache cleared", hdev->name);

return 0;
@@ -1225,17 +1229,23 @@ int hci_adv_entries_clear(struct hci_dev *hdev)
struct adv_entry *hci_find_adv_entry(struct hci_dev *hdev, bdaddr_t *bdaddr)
{
struct list_head *p;
+ struct adv_entry *res = NULL;
+
+ read_lock_bh(&hdev->adv_entries_lock);

list_for_each(p, &hdev->adv_entries) {
struct adv_entry *entry;

entry = list_entry(p, struct adv_entry, list);

- if (bacmp(bdaddr, &entry->bdaddr) == 0)
- return entry;
+ if (bacmp(bdaddr, &entry->bdaddr) == 0) {
+ res = entry;
+ goto out;
+ }
}
-
- return NULL;
+out:
+ read_unlock_bh(&hdev->adv_entries_lock);
+ return res;
}

static inline int is_connectable_adv(u8 evt_type)
@@ -1267,7 +1277,9 @@ int hci_add_adv_entry(struct hci_dev *hdev,
bacpy(&entry->bdaddr, &ev->bdaddr);
entry->bdaddr_type = ev->bdaddr_type;

+ write_lock(&hdev->adv_entries_lock);
list_add(&entry->list, &hdev->adv_entries);
+ write_unlock(&hdev->adv_entries_lock);

BT_DBG("%s adv entry added: address %s type %u", hdev->name,
batostr(&entry->bdaddr), entry->bdaddr_type);
@@ -1342,6 +1354,7 @@ int hci_register_dev(struct hci_dev *hdev)
INIT_LIST_HEAD(&hdev->remote_oob_data);

INIT_LIST_HEAD(&hdev->adv_entries);
+ rwlock_init(&hdev->adv_entries_lock);

INIT_WORK(&hdev->power_on, hci_power_on);
INIT_WORK(&hdev->power_off, hci_power_off);
--
1.7.1


2011-05-06 17:05:11

by Andre Guedes

[permalink] [raw]
Subject: [PATCH 02/12] 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 | 74 ++++++++++++++++++++++++++++++++++++++
2 files changed, 87 insertions(+), 0 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 14cc324..65135f8 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;
@@ -526,6 +534,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..0ba3c39 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1204,6 +1204,77 @@ 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 list_head *p, *n;
+
+ list_for_each_safe(p, n, &hdev->adv_entries) {
+ struct adv_entry *entry;
+
+ entry = list_entry(p, struct adv_entry, list);
+
+ list_del(p);
+ 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 list_head *p;
+
+ list_for_each(p, &hdev->adv_entries) {
+ struct adv_entry *entry;
+
+ entry = list_entry(p, struct adv_entry, 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;
+
+ entry = hci_find_adv_entry(hdev, &ev->bdaddr);
+ /* Only new entries should be added to adv_entries. So, if
+ * bdaddr was found, don't add it. */
+ if (entry)
+ 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 +1341,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 +1423,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.1


2011-05-06 17:05:10

by Andre Guedes

[permalink] [raw]
Subject: [PATCH 01/12] 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.1