linux-bluetooth.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC 0/6] LE advertising cache
@ 2011-03-04 20:35 Andre Guedes
  2011-03-04 20:35 ` [RFC 1/6] Bluetooth: Implement advertising report meta event Andre Guedes
                   ` (6 more replies)
  0 siblings, 7 replies; 11+ messages in thread
From: Andre Guedes @ 2011-03-04 20:35 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Andre Guedes

During a LE connection establishment, the host should be able to infer the
bdaddr type from a given bdaddr.

To achieve that, during the LE scanning, the host stores the bdaddr and the
bdaddr type gathered from advertising reports. The host keeps a list of
advertising entry (bdaddr and bdaddr_type) for later lookup. This list will
be called Advertising Cache.

Since the penality to connect to an unreachable device is relatively high,
we must keep only fresh advertising entries on 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.

Next steps include removing all advertising cache from userspace and
implementing a mechanism to sync kernel and userspace advertising cache.

Patches are rebased using Vinicius SMP patches, repo:
git://git.infradead.org/users/vcgomes/linux-2.6.git for-next

Anderson Briglia (1):
  Bluetooth: Implement advertising report meta event

Andre Guedes (5):
  Bluetooth: LE advertising info caching
  Bluetooth: Protect adv_entries with a RW semaphore
  Bluetooth: Check advertising cache in hci_connect()
  Bluetooth: Clear advertising cache before scanning
  Bluetooth: Add a timer to clear the advertising cache

 include/net/bluetooth/hci.h      |   20 ++++++++
 include/net/bluetooth/hci_core.h |   16 +++++++
 net/bluetooth/hci_conn.c         |   12 ++++-
 net/bluetooth/hci_core.c         |   92 ++++++++++++++++++++++++++++++++++++++
 net/bluetooth/hci_event.c        |   48 ++++++++++++++++++++
 5 files changed, 185 insertions(+), 3 deletions(-)


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [RFC 1/6] Bluetooth: Implement advertising report meta event
  2011-03-04 20:35 [RFC 0/6] LE advertising cache Andre Guedes
@ 2011-03-04 20:35 ` Andre Guedes
  2011-03-09 13:58   ` Anderson Briglia
  2011-03-04 20:35 ` [RFC 2/6] Bluetooth: LE advertising info caching Andre Guedes
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 11+ messages in thread
From: Andre Guedes @ 2011-03-04 20:35 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Anderson Briglia

From: Anderson Briglia <anderson.briglia@openbossa.org>

This patch implements new LE meta event in order to handle advertising
reports.

Signed-off-by: Anderson Briglia <anderson.briglia@openbossa.org>
---
 include/net/bluetooth/hci.h |   18 ++++++++++++++++++
 net/bluetooth/hci_event.c   |   22 ++++++++++++++++++++++
 2 files changed, 40 insertions(+), 0 deletions(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index d851f8b..fdcc494 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -1011,6 +1011,24 @@ struct hci_ev_le_conn_complete {
 	__u8     clk_accurancy;
 } __packed;
 
+#define ADV_IND		0x00
+#define ADV_DIRECT_IND	0x01
+#define ADV_SCAN_IND	0x02
+#define ADV_NONCONN_IND	0x03
+#define SCAN_RSP	0x04
+
+#define ADDR_DEV_PUBLIC	0x00
+#define ADDR_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;
+
 #define HCI_EV_LE_LTK_REQ		0x05
 struct hci_ev_le_ltk_req {
 	__le16	handle;
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 5a2ab2c..8acc4a5 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2556,6 +2556,24 @@ static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
 	hci_dev_unlock(hdev);
 }
 
+static inline void hci_le_adv_report_evt(struct hci_dev *hdev,
+						struct sk_buff *skb)
+{
+	struct hci_ev_le_advertising_info *ev;
+	u8 num_reports, i;
+
+	num_reports = skb->data[0];
+
+	ev = (void *) &skb->data[1];
+
+	BT_DBG("adv from: %s", batostr(&ev->bdaddr));
+
+	for (i = 1; i < num_reports; i++) {
+		ev = (void *) (ev->data + ev->length + 1);
+		BT_DBG("adv from: %s", batostr(&ev->bdaddr));
+	}
+}
+
 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;
@@ -2571,6 +2589,10 @@ static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
 		hci_le_ltk_request_evt(hdev, skb);
 		break;
 
+	case HCI_EV_LE_ADVERTISING_REPORT:
+		hci_le_adv_report_evt(hdev, skb);
+		break;
+
 	default:
 		break;
 	}
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [RFC 2/6] Bluetooth: LE advertising info caching
  2011-03-04 20:35 [RFC 0/6] LE advertising cache Andre Guedes
  2011-03-04 20:35 ` [RFC 1/6] Bluetooth: Implement advertising report meta event Andre Guedes
@ 2011-03-04 20:35 ` Andre Guedes
  2011-03-04 20:35 ` [RFC 3/6] Bluetooth: Protect adv_entries with a RW semaphore Andre Guedes
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 11+ messages in thread
From: Andre Guedes @ 2011-03-04 20:35 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Andre Guedes

This patch adds a list of 'advertising entry' to the struct hci_dev.

The advertising entry (struct adv_entry) stores sensitive information
(bdaddr and bdaddr_type so far) gathered from LE advertising report
events.

A double-linked list (list_head adv_entries) is used to store those
advertising entries. Only advertising entries from connectables devices
are inserted into the list.

Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
 include/net/bluetooth/hci_core.h |   12 ++++++
 net/bluetooth/hci_core.c         |   69 ++++++++++++++++++++++++++++++++++++++
 net/bluetooth/hci_event.c        |    5 +--
 3 files changed, 83 insertions(+), 3 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index c59e857..970711d 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -82,6 +82,12 @@ struct link_key {
 	u8 pin_len;
 };
 
+struct adv_entry {
+	struct list_head list;
+	bdaddr_t bdaddr;
+	u8 bdaddr_type;
+};
+
 #define NUM_REASSEMBLY 4
 struct hci_dev {
 	struct list_head list;
@@ -171,6 +177,8 @@ struct hci_dev {
 
 	struct list_head	link_keys;
 
+	struct list_head	adv_entries;
+
 	struct hci_dev_stats	stat;
 
 	struct sk_buff_head	driver_init;
@@ -508,6 +516,10 @@ int hci_add_link_key(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr,
 						u8 *key, u8 type, u8 pin_len);
 int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
 
+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 ff67843..cbff329 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1080,6 +1080,72 @@ static void hci_cmd_timer(unsigned long arg)
 	tasklet_schedule(&hdev->cmd_task);
 }
 
+static 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);
+	}
+
+	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);
+
+	return 0;
+}
+
 static struct crypto_blkcipher *alloc_cypher(void)
 {
 	if (enable_smp)
@@ -1152,6 +1218,8 @@ int hci_register_dev(struct hci_dev *hdev)
 
 	INIT_LIST_HEAD(&hdev->link_keys);
 
+	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);
@@ -1239,6 +1307,7 @@ int hci_unregister_dev(struct hci_dev *hdev)
 	hci_blacklist_clear(hdev);
 	hci_uuids_clear(hdev);
 	hci_link_keys_clear(hdev);
+	hci_adv_entries_clear(hdev);
 	hci_dev_unlock_bh(hdev);
 
 	__hci_dev_put(hdev);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 8acc4a5..825de59 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2565,12 +2565,11 @@ static inline void hci_le_adv_report_evt(struct hci_dev *hdev,
 	num_reports = skb->data[0];
 
 	ev = (void *) &skb->data[1];
-
-	BT_DBG("adv from: %s", batostr(&ev->bdaddr));
+	hci_add_adv_entry(hdev, ev);
 
 	for (i = 1; i < num_reports; i++) {
 		ev = (void *) (ev->data + ev->length + 1);
-		BT_DBG("adv from: %s", batostr(&ev->bdaddr));
+		hci_add_adv_entry(hdev, ev);
 	}
 }
 
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [RFC 3/6] Bluetooth: Protect adv_entries with a RW semaphore
  2011-03-04 20:35 [RFC 0/6] LE advertising cache Andre Guedes
  2011-03-04 20:35 ` [RFC 1/6] Bluetooth: Implement advertising report meta event Andre Guedes
  2011-03-04 20:35 ` [RFC 2/6] Bluetooth: LE advertising info caching Andre Guedes
@ 2011-03-04 20:35 ` Andre Guedes
  2011-03-04 20:35 ` [RFC 4/6] Bluetooth: Check advertising cache in hci_connect() Andre Guedes
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 11+ messages in thread
From: Andre Guedes @ 2011-03-04 20:35 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Andre Guedes

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

Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
 include/net/bluetooth/hci_core.h |    1 +
 net/bluetooth/hci_core.c         |   22 ++++++++++++++++++----
 2 files changed, 19 insertions(+), 4 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 970711d..bf7b5df 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -178,6 +178,7 @@ struct hci_dev {
 	struct list_head	link_keys;
 
 	struct list_head	adv_entries;
+	struct rw_semaphore	adv_entries_rwsem;
 
 	struct hci_dev_stats	stat;
 
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index cbff329..71f8788 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -44,6 +44,7 @@
 #include <linux/timer.h>
 #include <linux/crypto.h>
 #include <net/sock.h>
+#include <linux/rwsem.h>
 
 #include <asm/system.h>
 #include <linux/uaccess.h>
@@ -1084,6 +1085,8 @@ static int hci_adv_entries_clear(struct hci_dev *hdev)
 {
 	struct list_head *p, *n;
 
+	down_write(&hdev->adv_entries_rwsem);
+
 	list_for_each_safe(p, n, &hdev->adv_entries) {
 		struct adv_entry *entry;
 
@@ -1093,23 +1096,31 @@ static int hci_adv_entries_clear(struct hci_dev *hdev)
 		kfree(entry);
 	}
 
+	up_write(&hdev->adv_entries_rwsem);
+
 	return 0;
 }
 
 struct adv_entry *hci_find_adv_entry(struct hci_dev *hdev, bdaddr_t *bdaddr)
 {
 	struct list_head *p;
+	struct adv_entry *res = NULL;
+
+	down_read(&hdev->adv_entries_rwsem);
 
 	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:
+	up_read(&hdev->adv_entries_rwsem);
+	return res;
 }
 
 static inline int is_connectable_adv(u8 evt_type)
@@ -1141,7 +1152,9 @@ int hci_add_adv_entry(struct hci_dev *hdev,
 	bacpy(&entry->bdaddr, &ev->bdaddr);
 	entry->bdaddr_type = ev->bdaddr_type;
 
+	down_write(&hdev->adv_entries_rwsem);
 	list_add(&entry->list, &hdev->adv_entries);
+	up_write(&hdev->adv_entries_rwsem);
 
 	return 0;
 }
@@ -1219,6 +1232,7 @@ int hci_register_dev(struct hci_dev *hdev)
 	INIT_LIST_HEAD(&hdev->link_keys);
 
 	INIT_LIST_HEAD(&hdev->adv_entries);
+	init_rwsem(&hdev->adv_entries_rwsem);
 
 	INIT_WORK(&hdev->power_on, hci_power_on);
 	INIT_WORK(&hdev->power_off, hci_power_off);
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [RFC 4/6] Bluetooth: Check advertising cache in hci_connect()
  2011-03-04 20:35 [RFC 0/6] LE advertising cache Andre Guedes
                   ` (2 preceding siblings ...)
  2011-03-04 20:35 ` [RFC 3/6] Bluetooth: Protect adv_entries with a RW semaphore Andre Guedes
@ 2011-03-04 20:35 ` Andre Guedes
  2011-03-04 20:35 ` [RFC 5/6] Bluetooth: Clear advertising cache before scanning Andre Guedes
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 11+ messages in thread
From: Andre Guedes @ 2011-03-04 20:35 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Andre Guedes

When connecting to a LE device, we need to check the advertising cache
in order to know the bdaddr_type of that device. Additionally,
hci_le_connect() was changed to handle the bdaddr_type info.

Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
 net/bluetooth/hci_conn.c |   12 +++++++++---
 1 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 9a4a769..2d3197a 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -45,7 +45,7 @@
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
 
-static void hci_le_connect(struct hci_conn *conn)
+static void hci_le_connect(struct hci_conn *conn, u8 bdaddr_type)
 {
 	struct hci_dev *hdev = conn->hdev;
 	struct hci_cp_le_create_conn cp;
@@ -59,6 +59,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 = bdaddr_type;
 	cp.conn_interval_min = cpu_to_le16(0x0008);
 	cp.conn_interval_max = cpu_to_le16(0x0100);
 	cp.supervision_timeout = cpu_to_le16(0x0064);
@@ -482,8 +483,13 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8
 		le = hci_conn_add(hdev, LE_LINK, dst);
 		if (!le)
 			return ERR_PTR(-ENOMEM);
-		if (le->state == BT_OPEN)
-			hci_le_connect(le);
+		if (le->state == BT_OPEN) {
+			struct adv_entry *entry = hci_find_adv_entry(hdev, dst);
+			if (!entry)
+				return ERR_PTR(-EHOSTUNREACH);
+
+			hci_le_connect(le, entry->bdaddr_type);
+		}
 
 		hci_conn_hold(le);
 
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [RFC 5/6] Bluetooth: Clear advertising cache before scanning
  2011-03-04 20:35 [RFC 0/6] LE advertising cache Andre Guedes
                   ` (3 preceding siblings ...)
  2011-03-04 20:35 ` [RFC 4/6] Bluetooth: Check advertising cache in hci_connect() Andre Guedes
@ 2011-03-04 20:35 ` Andre Guedes
  2011-03-04 20:35 ` [RFC 6/6] Bluetooth: Add a timer to clear the advertising cache Andre Guedes
  2011-03-04 20:49 ` [RFC 0/6] LE " Brian Gix
  6 siblings, 0 replies; 11+ messages in thread
From: Andre Guedes @ 2011-03-04 20:35 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Andre Guedes

The LE advertising list should be cleared when a LE scanning is
performed. This will force the list to contain only fresh advertising
entries.

In order to achieve that, it was added a handler to the Command
Complete Event generated by the LE Set Scan Enable Command.

Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
 include/net/bluetooth/hci.h      |    2 ++
 include/net/bluetooth/hci_core.h |    1 +
 net/bluetooth/hci_core.c         |    2 +-
 net/bluetooth/hci_event.c        |   23 +++++++++++++++++++++++
 4 files changed, 27 insertions(+), 1 deletions(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index fdcc494..1786794 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -670,6 +670,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/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index bf7b5df..3ead365 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -517,6 +517,7 @@ int hci_add_link_key(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr,
 						u8 *key, u8 type, u8 pin_len);
 int hci_remove_link_key(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);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 71f8788..8f9b3a5 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1081,7 +1081,7 @@ static void hci_cmd_timer(unsigned long arg)
 	tasklet_schedule(&hdev->cmd_task);
 }
 
-static int hci_adv_entries_clear(struct hci_dev *hdev)
+int hci_adv_entries_clear(struct hci_dev *hdev)
 {
 	struct list_head *p, *n;
 
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 825de59..a07ed86 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -843,6 +843,25 @@ 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 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);
+
+	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)
 {
 	BT_DBG("%s status 0x%x", hdev->name, status);
@@ -1799,6 +1818,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_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


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [RFC 6/6] Bluetooth: Add a timer to clear the advertising cache
  2011-03-04 20:35 [RFC 0/6] LE advertising cache Andre Guedes
                   ` (4 preceding siblings ...)
  2011-03-04 20:35 ` [RFC 5/6] Bluetooth: Clear advertising cache before scanning Andre Guedes
@ 2011-03-04 20:35 ` Andre Guedes
  2011-03-04 20:49 ` [RFC 0/6] LE " Brian Gix
  6 siblings, 0 replies; 11+ messages in thread
From: Andre Guedes @ 2011-03-04 20:35 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Andre Guedes

This patch adds a timer to clear adv_entries list 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 adv_entries list.

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

Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
 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 3ead365..790f839 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -179,6 +179,7 @@ struct hci_dev {
 
 	struct list_head	adv_entries;
 	struct rw_semaphore	adv_entries_rwsem;
+	struct timer_list	adv_timer;
 
 	struct hci_dev_stats	stat;
 
@@ -517,6 +518,7 @@ int hci_add_link_key(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr,
 						u8 *key, u8 type, u8 pin_len);
 int hci_remove_link_key(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 8f9b3a5..ea8b0c2 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1081,6 +1081,13 @@ static void hci_cmd_timer(unsigned long arg)
 	tasklet_schedule(&hdev->cmd_task);
 }
 
+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;
@@ -1233,6 +1240,7 @@ int hci_register_dev(struct hci_dev *hdev)
 
 	INIT_LIST_HEAD(&hdev->adv_entries);
 	init_rwsem(&hdev->adv_entries_rwsem);
+	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);
@@ -1314,6 +1322,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 a07ed86..a1fe9cc 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -858,8 +858,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


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [RFC 0/6] LE advertising cache
  2011-03-04 20:35 [RFC 0/6] LE advertising cache Andre Guedes
                   ` (5 preceding siblings ...)
  2011-03-04 20:35 ` [RFC 6/6] Bluetooth: Add a timer to clear the advertising cache Andre Guedes
@ 2011-03-04 20:49 ` Brian Gix
  2011-03-11 13:27   ` Andre Guedes
  6 siblings, 1 reply; 11+ messages in thread
From: Brian Gix @ 2011-03-04 20:49 UTC (permalink / raw)
  To: Andre Guedes; +Cc: linux-bluetooth

On 11-03-04 12:35 PM, Andre Guedes wrote:
> During a LE connection establishment, the host should be able to infer the
> bdaddr type from a given bdaddr.
>
> To achieve that, during the LE scanning, the host stores the bdaddr and the
> bdaddr type gathered from advertising reports. The host keeps a list of
> advertising entry (bdaddr and bdaddr_type) for later lookup. This list will
> be called Advertising Cache.

My biggest problem with this is testing purposes.

While it is true that the bdaddr_type can be extracted from the LE Scan 
data, when you are at an event like UPF, there can be an awful lot of 
devices very close to you.

It would be nice to be able to explicitly specify both the bdaddr and 
bdaddr_type during these things.

But I agree that as a deployed device, caching from an LE scan makes the 
most sense.

Will this also work for (future) private addressing, where the address 
being connected to may not be the one initially seen in the scan?


>
> Since the penality to connect to an unreachable device is relatively high,
> we must keep only fresh advertising entries on 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.
>
> Next steps include removing all advertising cache from userspace and
> implementing a mechanism to sync kernel and userspace advertising cache.
>
> Patches are rebased using Vinicius SMP patches, repo:
> git://git.infradead.org/users/vcgomes/linux-2.6.git for-next
>
> Anderson Briglia (1):
>    Bluetooth: Implement advertising report meta event
>
> Andre Guedes (5):
>    Bluetooth: LE advertising info caching
>    Bluetooth: Protect adv_entries with a RW semaphore
>    Bluetooth: Check advertising cache in hci_connect()
>    Bluetooth: Clear advertising cache before scanning
>    Bluetooth: Add a timer to clear the advertising cache
>
>   include/net/bluetooth/hci.h      |   20 ++++++++
>   include/net/bluetooth/hci_core.h |   16 +++++++
>   net/bluetooth/hci_conn.c         |   12 ++++-
>   net/bluetooth/hci_core.c         |   92 ++++++++++++++++++++++++++++++++++++++
>   net/bluetooth/hci_event.c        |   48 ++++++++++++++++++++
>   5 files changed, 185 insertions(+), 3 deletions(-)
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


-- 
Brian Gix
bgix@codeaurora.org
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC 1/6] Bluetooth: Implement advertising report meta event
  2011-03-04 20:35 ` [RFC 1/6] Bluetooth: Implement advertising report meta event Andre Guedes
@ 2011-03-09 13:58   ` Anderson Briglia
  2011-03-10 21:56     ` Andre Guedes
  0 siblings, 1 reply; 11+ messages in thread
From: Anderson Briglia @ 2011-03-09 13:58 UTC (permalink / raw)
  To: Andre Guedes; +Cc: linux-bluetooth

Hi,

On Fri, Mar 4, 2011 at 4:35 PM, Andre Guedes <andre.guedes@openbossa.org> wrote:
> From: Anderson Briglia <anderson.briglia@openbossa.org>
>
> This patch implements new LE meta event in order to handle advertising
> reports.
>
> Signed-off-by: Anderson Briglia <anderson.briglia@openbossa.org>
> ---
>  include/net/bluetooth/hci.h |   18 ++++++++++++++++++
>  net/bluetooth/hci_event.c   |   22 ++++++++++++++++++++++
>  2 files changed, 40 insertions(+), 0 deletions(-)
>
> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
> index d851f8b..fdcc494 100644
> --- a/include/net/bluetooth/hci.h
> +++ b/include/net/bluetooth/hci.h
> @@ -1011,6 +1011,24 @@ struct hci_ev_le_conn_complete {
>        __u8     clk_accurancy;
>  } __packed;
>
> +#define ADV_IND                0x00
> +#define ADV_DIRECT_IND 0x01
> +#define ADV_SCAN_IND   0x02
> +#define ADV_NONCONN_IND        0x03
> +#define SCAN_RSP       0x04
> +
> +#define ADDR_DEV_PUBLIC        0x00
> +#define ADDR_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;
> +
>  #define HCI_EV_LE_LTK_REQ              0x05
>  struct hci_ev_le_ltk_req {
>        __le16  handle;
> diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
> index 5a2ab2c..8acc4a5 100644
> --- a/net/bluetooth/hci_event.c
> +++ b/net/bluetooth/hci_event.c
> @@ -2556,6 +2556,24 @@ static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
>        hci_dev_unlock(hdev);
>  }
>
> +static inline void hci_le_adv_report_evt(struct hci_dev *hdev,
> +                                               struct sk_buff *skb)
> +{
> +       struct hci_ev_le_advertising_info *ev;
> +       u8 num_reports, i;
> +
> +       num_reports = skb->data[0];
> +
> +       ev = (void *) &skb->data[1];
> +
> +       BT_DBG("adv from: %s", batostr(&ev->bdaddr));
> +
> +       for (i = 1; i < num_reports; i++) {
> +               ev = (void *) (ev->data + ev->length + 1);
> +               BT_DBG("adv from: %s", batostr(&ev->bdaddr));
> +       }
> +}
> +
>  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;
> @@ -2571,6 +2589,10 @@ static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
>                hci_le_ltk_request_evt(hdev, skb);
>                break;
>
> +       case HCI_EV_LE_ADVERTISING_REPORT:
> +               hci_le_adv_report_evt(hdev, skb);
> +               break;
> +
>        default:
>                break;
>        }
> --
> 1.7.1
>
>

Please, do not consider this patch. I have another one with some
modifications proposed by padovan. Andre, rebase your git tree,
please.


-- 
INdT - Instituto Nokia de tecnologia
+55 2126 1122
http://techblog.briglia.net

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC 1/6] Bluetooth: Implement advertising report meta event
  2011-03-09 13:58   ` Anderson Briglia
@ 2011-03-10 21:56     ` Andre Guedes
  0 siblings, 0 replies; 11+ messages in thread
From: Andre Guedes @ 2011-03-10 21:56 UTC (permalink / raw)
  To: Anderson Briglia; +Cc: linux-bluetooth

Ok,

Please, do not consider this patch set, I will rebase and send a v2 soon.

Thanks,

Andre.

On Wed, Mar 9, 2011 at 10:58 AM, Anderson Briglia
<anderson.briglia@openbossa.org> wrote:
>
> Hi,
>
> On Fri, Mar 4, 2011 at 4:35 PM, Andre Guedes <andre.guedes@openbossa.org> wrote:
> > From: Anderson Briglia <anderson.briglia@openbossa.org>
> >
> > This patch implements new LE meta event in order to handle advertising
> > reports.
> >
> > Signed-off-by: Anderson Briglia <anderson.briglia@openbossa.org>
> > ---
> >  include/net/bluetooth/hci.h |   18 ++++++++++++++++++
> >  net/bluetooth/hci_event.c   |   22 ++++++++++++++++++++++
> >  2 files changed, 40 insertions(+), 0 deletions(-)
> >
> > diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
> > index d851f8b..fdcc494 100644
> > --- a/include/net/bluetooth/hci.h
> > +++ b/include/net/bluetooth/hci.h
> > @@ -1011,6 +1011,24 @@ struct hci_ev_le_conn_complete {
> >        __u8     clk_accurancy;
> >  } __packed;
> >
> > +#define ADV_IND                0x00
> > +#define ADV_DIRECT_IND 0x01
> > +#define ADV_SCAN_IND   0x02
> > +#define ADV_NONCONN_IND        0x03
> > +#define SCAN_RSP       0x04
> > +
> > +#define ADDR_DEV_PUBLIC        0x00
> > +#define ADDR_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;
> > +
> >  #define HCI_EV_LE_LTK_REQ              0x05
> >  struct hci_ev_le_ltk_req {
> >        __le16  handle;
> > diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
> > index 5a2ab2c..8acc4a5 100644
> > --- a/net/bluetooth/hci_event.c
> > +++ b/net/bluetooth/hci_event.c
> > @@ -2556,6 +2556,24 @@ static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
> >        hci_dev_unlock(hdev);
> >  }
> >
> > +static inline void hci_le_adv_report_evt(struct hci_dev *hdev,
> > +                                               struct sk_buff *skb)
> > +{
> > +       struct hci_ev_le_advertising_info *ev;
> > +       u8 num_reports, i;
> > +
> > +       num_reports = skb->data[0];
> > +
> > +       ev = (void *) &skb->data[1];
> > +
> > +       BT_DBG("adv from: %s", batostr(&ev->bdaddr));
> > +
> > +       for (i = 1; i < num_reports; i++) {
> > +               ev = (void *) (ev->data + ev->length + 1);
> > +               BT_DBG("adv from: %s", batostr(&ev->bdaddr));
> > +       }
> > +}
> > +
> >  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;
> > @@ -2571,6 +2589,10 @@ static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
> >                hci_le_ltk_request_evt(hdev, skb);
> >                break;
> >
> > +       case HCI_EV_LE_ADVERTISING_REPORT:
> > +               hci_le_adv_report_evt(hdev, skb);
> > +               break;
> > +
> >        default:
> >                break;
> >        }
> > --
> > 1.7.1
> >
> >
>
> Please, do not consider this patch. I have another one with some
> modifications proposed by padovan. Andre, rebase your git tree,
> please.
>
>
> --
> INdT - Instituto Nokia de tecnologia
> +55 2126 1122
> http://techblog.briglia.net

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC 0/6] LE advertising cache
  2011-03-04 20:49 ` [RFC 0/6] LE " Brian Gix
@ 2011-03-11 13:27   ` Andre Guedes
  0 siblings, 0 replies; 11+ messages in thread
From: Andre Guedes @ 2011-03-11 13:27 UTC (permalink / raw)
  To: Brian Gix; +Cc: linux-bluetooth

Hi Brian,

On Fri, Mar 4, 2011 at 5:49 PM, Brian Gix <bgix@codeaurora.org> wrote:
>
> On 11-03-04 12:35 PM, Andre Guedes wrote:
>>
>> During a LE connection establishment, the host should be able to infer the
>> bdaddr type from a given bdaddr.
>>
>> To achieve that, during the LE scanning, the host stores the bdaddr and the
>> bdaddr type gathered from advertising reports. The host keeps a list of
>> advertising entry (bdaddr and bdaddr_type) for later lookup. This list will
>> be called Advertising Cache.
>
> My biggest problem with this is testing purposes.
>
> While it is true that the bdaddr_type can be extracted from the LE Scan data, when you are at an event like UPF, there can be an awful lot of devices very close to you.
>
> It would be nice to be able to explicitly specify both the bdaddr and bdaddr_type during these things.

For testing purposes, hcitool lecc [--random] <bdaddr> command can be
used to explicitly specify both the bdaddr and bdaddr_type.

For the L2CAP socket, we could have extended the "struct sockaddr_l2"
to add the address type field, but we've decided to not add a new
field which is not applied to basic rate.

>
> But I agree that as a deployed device, caching from an LE scan makes the most sense.
>
> Will this also work for (future) private addressing, where the address being connected to may not be the one initially seen in the scan?

Yes. Advertising entries are cached during both active and passive
scanning. We need to define how to put all pieces together: whitelist,
active/passive scanning and address resolution in the kernel.

>>
>> Since the penality to connect to an unreachable device is relatively high,
>> we must keep only fresh advertising entries on 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.
>>
>> Next steps include removing all advertising cache from userspace and
>> implementing a mechanism to sync kernel and userspace advertising cache.
>>
>> Patches are rebased using Vinicius SMP patches, repo:
>> git://git.infradead.org/users/vcgomes/linux-2.6.git for-next
>>
>> Anderson Briglia (1):
>>   Bluetooth: Implement advertising report meta event
>>
>> Andre Guedes (5):
>>   Bluetooth: LE advertising info caching
>>   Bluetooth: Protect adv_entries with a RW semaphore
>>   Bluetooth: Check advertising cache in hci_connect()
>>   Bluetooth: Clear advertising cache before scanning
>>   Bluetooth: Add a timer to clear the advertising cache
>>
>>  include/net/bluetooth/hci.h      |   20 ++++++++
>>  include/net/bluetooth/hci_core.h |   16 +++++++
>>  net/bluetooth/hci_conn.c         |   12 ++++-
>>  net/bluetooth/hci_core.c         |   92 ++++++++++++++++++++++++++++++++++++++
>>  net/bluetooth/hci_event.c        |   48 ++++++++++++++++++++
>>  5 files changed, 185 insertions(+), 3 deletions(-)
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
>
> --
> Brian Gix
> bgix@codeaurora.org
> Employee of Qualcomm Innovation Center, Inc.
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum

Regards,

Andre Guedes.

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2011-03-11 13:27 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-03-04 20:35 [RFC 0/6] LE advertising cache Andre Guedes
2011-03-04 20:35 ` [RFC 1/6] Bluetooth: Implement advertising report meta event Andre Guedes
2011-03-09 13:58   ` Anderson Briglia
2011-03-10 21:56     ` Andre Guedes
2011-03-04 20:35 ` [RFC 2/6] Bluetooth: LE advertising info caching Andre Guedes
2011-03-04 20:35 ` [RFC 3/6] Bluetooth: Protect adv_entries with a RW semaphore Andre Guedes
2011-03-04 20:35 ` [RFC 4/6] Bluetooth: Check advertising cache in hci_connect() Andre Guedes
2011-03-04 20:35 ` [RFC 5/6] Bluetooth: Clear advertising cache before scanning Andre Guedes
2011-03-04 20:35 ` [RFC 6/6] Bluetooth: Add a timer to clear the advertising cache Andre Guedes
2011-03-04 20:49 ` [RFC 0/6] LE " Brian Gix
2011-03-11 13:27   ` Andre Guedes

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).