All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC v10 01/10] Bluetooth: Create hci_req_add_le_scan_disable helper
@ 2014-02-18 20:15 Andre Guedes
  2014-02-18 20:15 ` [RFC v10 02/10] Bluetooth: Declare le_conn_failed in hci_core.h Andre Guedes
                   ` (8 more replies)
  0 siblings, 9 replies; 16+ messages in thread
From: Andre Guedes @ 2014-02-18 20:15 UTC (permalink / raw)
  To: linux-bluetooth

This patch moves stop LE scanning duplicate code to one single
place and reuses it. This will avoid more duplicate code in
upcoming patches.

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

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 64c4e3f..259b876 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -1112,6 +1112,7 @@ void hci_req_add(struct hci_request *req, u16 opcode, u32 plen,
 void hci_req_add_ev(struct hci_request *req, u16 opcode, u32 plen,
 		    const void *param, u8 event);
 void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status);
+void hci_req_add_le_scan_disable(struct hci_request *req);
 
 struct sk_buff *__hci_cmd_sync(struct hci_dev *hdev, u16 opcode, u32 plen,
 			       const void *param, u32 timeout);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index e4c5b9d..3211546 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -3151,7 +3151,6 @@ static void le_scan_disable_work(struct work_struct *work)
 {
 	struct hci_dev *hdev = container_of(work, struct hci_dev,
 					    le_scan_disable.work);
-	struct hci_cp_le_set_scan_enable cp;
 	struct hci_request req;
 	int err;
 
@@ -3159,9 +3158,7 @@ static void le_scan_disable_work(struct work_struct *work)
 
 	hci_req_init(&req, hdev);
 
-	memset(&cp, 0, sizeof(cp));
-	cp.enable = LE_SCAN_DISABLE;
-	hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp);
+	hci_req_add_le_scan_disable(&req);
 
 	err = hci_req_run(&req, le_scan_disable_work_complete);
 	if (err)
@@ -4632,3 +4629,12 @@ static void hci_cmd_work(struct work_struct *work)
 		}
 	}
 }
+
+void hci_req_add_le_scan_disable(struct hci_request *req)
+{
+	struct hci_cp_le_set_scan_enable cp;
+
+	memset(&cp, 0, sizeof(cp));
+	cp.enable = LE_SCAN_DISABLE;
+	hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp);
+}
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 747cb9b..98396f9 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -3424,7 +3424,6 @@ static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
 	struct hci_cp_remote_name_req_cancel cp;
 	struct inquiry_entry *e;
 	struct hci_request req;
-	struct hci_cp_le_set_scan_enable enable_cp;
 	int err;
 
 	BT_DBG("%s", hdev->name);
@@ -3460,10 +3459,7 @@ static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
 		} else {
 			cancel_delayed_work(&hdev->le_scan_disable);
 
-			memset(&enable_cp, 0, sizeof(enable_cp));
-			enable_cp.enable = LE_SCAN_DISABLE;
-			hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE,
-				    sizeof(enable_cp), &enable_cp);
+			hci_req_add_le_scan_disable(&req);
 		}
 
 		break;
-- 
1.8.5.4


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

* [RFC v10 02/10] Bluetooth: Declare le_conn_failed in hci_core.h
  2014-02-18 20:15 [RFC v10 01/10] Bluetooth: Create hci_req_add_le_scan_disable helper Andre Guedes
@ 2014-02-18 20:15 ` Andre Guedes
  2014-02-18 20:15 ` [RFC v10 03/10] Bluetooth: Stop scanning on LE connection Andre Guedes
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 16+ messages in thread
From: Andre Guedes @ 2014-02-18 20:15 UTC (permalink / raw)
  To: linux-bluetooth

This patch adds the "hci_" prefix to le_conn_failed() helper and
declares it in hci_core.h so it can be reused in hci_event.c.

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

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 259b876..1d14b39 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -637,6 +637,8 @@ int hci_conn_switch_role(struct hci_conn *conn, __u8 role);
 
 void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active);
 
+void hci_le_conn_failed(struct hci_conn *conn, u8 status);
+
 /*
  * hci_conn_get() and hci_conn_put() are used to control the life-time of an
  * "hci_conn" object. They do not guarantee that the hci_conn object is running,
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 40ec373..96e4cc6 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -515,7 +515,7 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src)
 EXPORT_SYMBOL(hci_get_route);
 
 /* This function requires the caller holds hdev->lock */
-static void le_conn_failed(struct hci_conn *conn, u8 status)
+void hci_le_conn_failed(struct hci_conn *conn, u8 status)
 {
 	struct hci_dev *hdev = conn->hdev;
 
@@ -545,7 +545,7 @@ static void create_le_conn_complete(struct hci_dev *hdev, u8 status)
 	if (!conn)
 		goto done;
 
-	le_conn_failed(conn, status);
+	hci_le_conn_failed(conn, status);
 
 done:
 	hci_dev_unlock(hdev);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 49a2d4d..87baf21 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -3609,11 +3609,7 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 	}
 
 	if (ev->status) {
-		mgmt_connect_failed(hdev, &conn->dst, conn->type,
-				    conn->dst_type, ev->status);
-		hci_proto_connect_cfm(conn, ev->status);
-		conn->state = BT_CLOSED;
-		hci_conn_del(conn);
+		hci_le_conn_failed(conn, ev->status);
 		goto unlock;
 	}
 
-- 
1.8.5.4


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

* [RFC v10 03/10] Bluetooth: Stop scanning on LE connection
  2014-02-18 20:15 [RFC v10 01/10] Bluetooth: Create hci_req_add_le_scan_disable helper Andre Guedes
  2014-02-18 20:15 ` [RFC v10 02/10] Bluetooth: Declare le_conn_failed in hci_core.h Andre Guedes
@ 2014-02-18 20:15 ` Andre Guedes
  2014-02-18 20:15 ` [RFC v10 04/10] Bluetooth: Remove unused function Andre Guedes
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 16+ messages in thread
From: Andre Guedes @ 2014-02-18 20:15 UTC (permalink / raw)
  To: linux-bluetooth

Some LE controllers don't support scanning and creating a connection
at the same time. So we should always stop scanning in order to
establish the connection.

Since we may prematurely stop the discovery procedure in favor of
the connection establishment, we should also cancel hdev->le_scan_
disable delayed work and set the discovery state to DISCOVERY_STOPPED.

This change does a small improvement since it is not mandatory the
user stops scanning before connecting anymore. Moreover, this change
is required by upcoming LE auto connection mechanism in order to work
properly with controllers that don't support background scanning and
connection establishment at the same time.

In future, we might want to do a small optimization by checking if
controller is able to scan and connect at the same time. For now,
we want the simplest approach so we always stop scanning (even if
the controller is able to carry out both operations).

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

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index d3a8fff..0962809 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -353,6 +353,7 @@ enum {
 
 /* ---- HCI Error Codes ---- */
 #define HCI_ERROR_AUTH_FAILURE		0x05
+#define HCI_ERROR_MEMORY_EXCEEDED	0x07
 #define HCI_ERROR_CONNECTION_TIMEOUT	0x08
 #define HCI_ERROR_REJ_BAD_ADDR		0x0f
 #define HCI_ERROR_REMOTE_USER_TERM	0x13
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 96e4cc6..e147fd3 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -583,12 +583,73 @@ static int hci_create_le_conn(struct hci_conn *conn)
 	return 0;
 }
 
+static void hci_req_add_le_create_conn(struct hci_request *req,
+				       struct hci_conn *conn)
+{
+	struct hci_cp_le_create_conn cp;
+	struct hci_dev *hdev = conn->hdev;
+
+	memset(&cp, 0, sizeof(cp));
+	cp.scan_interval = cpu_to_le16(hdev->le_scan_interval);
+	cp.scan_window = cpu_to_le16(hdev->le_scan_window);
+	bacpy(&cp.peer_addr, &conn->dst);
+	cp.peer_addr_type = conn->dst_type;
+	cp.own_address_type = conn->src_type;
+	cp.conn_interval_min = cpu_to_le16(conn->le_conn_min_interval);
+	cp.conn_interval_max = cpu_to_le16(conn->le_conn_max_interval);
+	cp.supervision_timeout = __constant_cpu_to_le16(0x002a);
+	cp.min_ce_len = __constant_cpu_to_le16(0x0000);
+	cp.max_ce_len = __constant_cpu_to_le16(0x0000);
+
+	hci_req_add(req, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp);
+}
+
+static void stop_scan_complete(struct hci_dev *hdev, u8 status)
+{
+	struct hci_request req;
+	struct hci_conn *conn;
+	int err;
+
+	conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
+	if (!conn)
+		return;
+
+	if (status) {
+		BT_DBG("HCI request failed to stop scanning: status 0x%2.2x",
+		       status);
+
+		hci_dev_lock(hdev);
+		hci_le_conn_failed(conn, status);
+		hci_dev_unlock(hdev);
+		return;
+	}
+
+	/* Since we may have prematurely stopped discovery procedure, we should
+	 * update discovery state.
+	 */
+	cancel_delayed_work(&hdev->le_scan_disable);
+	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
+
+	hci_req_init(&req, hdev);
+
+	hci_req_add_le_create_conn(&req, conn);
+
+	err = hci_req_run(&req, create_le_conn_complete);
+	if (err) {
+		hci_dev_lock(hdev);
+		hci_le_conn_failed(conn, HCI_ERROR_MEMORY_EXCEEDED);
+		hci_dev_unlock(hdev);
+		return;
+	}
+}
+
 static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
 				    u8 dst_type, u8 sec_level, u8 auth_type)
 {
 	struct hci_conn_params *params;
 	struct hci_conn *conn;
 	struct smp_irk *irk;
+	struct hci_request req;
 	int err;
 
 	if (test_bit(HCI_ADVERTISING, &hdev->flags))
@@ -652,9 +713,23 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
 		conn->le_conn_max_interval = hdev->le_conn_max_interval;
 	}
 
-	err = hci_create_le_conn(conn);
-	if (err)
+	hci_req_init(&req, hdev);
+
+	/* If controller is scanning, we stop it since some controllers are
+	 * not able to scan and connect at the same time.
+	 */
+	if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) {
+		hci_req_add_le_scan_disable(&req);
+		err = hci_req_run(&req, stop_scan_complete);
+	} else {
+		hci_req_add_le_create_conn(&req, conn);
+		err = hci_req_run(&req, create_le_conn_complete);
+	}
+
+	if (err) {
+		hci_conn_del(conn);
 		return ERR_PTR(err);
+	}
 
 done:
 	hci_conn_hold(conn);
-- 
1.8.5.4


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

* [RFC v10 04/10] Bluetooth: Remove unused function
  2014-02-18 20:15 [RFC v10 01/10] Bluetooth: Create hci_req_add_le_scan_disable helper Andre Guedes
  2014-02-18 20:15 ` [RFC v10 02/10] Bluetooth: Declare le_conn_failed in hci_core.h Andre Guedes
  2014-02-18 20:15 ` [RFC v10 03/10] Bluetooth: Stop scanning on LE connection Andre Guedes
@ 2014-02-18 20:15 ` Andre Guedes
  2014-02-18 20:15 ` [RFC v10 05/10] Bluetooth: Introduce hdev->pend_le_conn list Andre Guedes
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 16+ messages in thread
From: Andre Guedes @ 2014-02-18 20:15 UTC (permalink / raw)
  To: linux-bluetooth

This patch removes hci_create_le_conn() since it is not used anymore.

Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
 net/bluetooth/hci_conn.c | 32 --------------------------------
 1 file changed, 32 deletions(-)

diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index e147fd3..0ae7692 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -551,38 +551,6 @@ done:
 	hci_dev_unlock(hdev);
 }
 
-static int hci_create_le_conn(struct hci_conn *conn)
-{
-	struct hci_dev *hdev = conn->hdev;
-	struct hci_cp_le_create_conn cp;
-	struct hci_request req;
-	int err;
-
-	hci_req_init(&req, hdev);
-
-	memset(&cp, 0, sizeof(cp));
-	cp.scan_interval = cpu_to_le16(hdev->le_scan_interval);
-	cp.scan_window = cpu_to_le16(hdev->le_scan_window);
-	bacpy(&cp.peer_addr, &conn->dst);
-	cp.peer_addr_type = conn->dst_type;
-	cp.own_address_type = conn->src_type;
-	cp.conn_interval_min = cpu_to_le16(conn->le_conn_min_interval);
-	cp.conn_interval_max = cpu_to_le16(conn->le_conn_max_interval);
-	cp.supervision_timeout = __constant_cpu_to_le16(0x002a);
-	cp.min_ce_len = __constant_cpu_to_le16(0x0000);
-	cp.max_ce_len = __constant_cpu_to_le16(0x0000);
-
-	hci_req_add(&req, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp);
-
-	err = hci_req_run(&req, create_le_conn_complete);
-	if (err) {
-		hci_conn_del(conn);
-		return err;
-	}
-
-	return 0;
-}
-
 static void hci_req_add_le_create_conn(struct hci_request *req,
 				       struct hci_conn *conn)
 {
-- 
1.8.5.4


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

* [RFC v10 05/10] Bluetooth: Introduce hdev->pend_le_conn list
  2014-02-18 20:15 [RFC v10 01/10] Bluetooth: Create hci_req_add_le_scan_disable helper Andre Guedes
                   ` (2 preceding siblings ...)
  2014-02-18 20:15 ` [RFC v10 04/10] Bluetooth: Remove unused function Andre Guedes
@ 2014-02-18 20:15 ` Andre Guedes
  2014-02-18 20:15 ` [RFC v10 06/10] Bluetooth: Introduce LE auto connection infrastructure Andre Guedes
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 16+ messages in thread
From: Andre Guedes @ 2014-02-18 20:15 UTC (permalink / raw)
  To: linux-bluetooth

This patch introduces the hdev->pend_le_conn list which holds the
device addresses the kernel should autonomously connect. It also
introduces some helper functions to manipulate the list.

The list and helper functions will be used by the next patch which
implements the LE auto connection infrastructure.

Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
 include/net/bluetooth/hci_core.h |  7 +++++
 net/bluetooth/hci_core.c         | 68 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 75 insertions(+)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 1d14b39..f0617ab 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -280,6 +280,7 @@ struct hci_dev {
 	struct list_head	identity_resolving_keys;
 	struct list_head	remote_oob_data;
 	struct list_head	le_conn_params;
+	struct list_head	pend_le_conns;
 
 	struct hci_dev_stats	stat;
 
@@ -781,6 +782,12 @@ void hci_conn_params_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type,
 void hci_conn_params_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type);
 void hci_conn_params_clear(struct hci_dev *hdev);
 
+struct bdaddr_list *hci_pend_le_conn_lookup(struct hci_dev *hdev,
+					    bdaddr_t *addr, u8 addr_type);
+void hci_pend_le_conn_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type);
+void hci_pend_le_conn_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type);
+void hci_pend_le_conns_clear(struct hci_dev *hdev);
+
 void hci_uuids_clear(struct hci_dev *hdev);
 
 void hci_link_keys_clear(struct hci_dev *hdev);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 3211546..992f9ea 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -3092,6 +3092,72 @@ void hci_conn_params_clear(struct hci_dev *hdev)
 	BT_DBG("All LE connection parameters were removed");
 }
 
+/* This function requires the caller holds hdev->lock */
+struct bdaddr_list *hci_pend_le_conn_lookup(struct hci_dev *hdev,
+					    bdaddr_t *addr, u8 addr_type)
+{
+	struct bdaddr_list *entry;
+
+	list_for_each_entry(entry, &hdev->pend_le_conns, list) {
+		if (bacmp(&entry->bdaddr, addr) == 0 &&
+		    entry->bdaddr_type == addr_type)
+			return entry;
+	}
+
+	return NULL;
+}
+
+/* This function requires the caller holds hdev->lock */
+void hci_pend_le_conn_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type)
+{
+	struct bdaddr_list *entry;
+
+	entry = hci_pend_le_conn_lookup(hdev, addr, addr_type);
+	if (entry)
+		return;
+
+	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+	if (!entry) {
+		BT_ERR("Out of memory");
+		return;
+	}
+
+	bacpy(&entry->bdaddr, addr);
+	entry->bdaddr_type = addr_type;
+
+	list_add(&entry->list, &hdev->pend_le_conns);
+
+	BT_DBG("addr %pMR (type %u)", addr, addr_type);
+}
+
+/* This function requires the caller holds hdev->lock */
+void hci_pend_le_conn_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type)
+{
+	struct bdaddr_list *entry;
+
+	entry = hci_pend_le_conn_lookup(hdev, addr, addr_type);
+	if (!entry)
+		return;
+
+	list_del(&entry->list);
+	kfree(entry);
+
+	BT_DBG("addr %pMR (type %u)", addr, addr_type);
+}
+
+/* This function requires the caller holds hdev->lock */
+void hci_pend_le_conns_clear(struct hci_dev *hdev)
+{
+	struct bdaddr_list *entry, *tmp;
+
+	list_for_each_entry_safe(entry, tmp, &hdev->pend_le_conns, list) {
+		list_del(&entry->list);
+		kfree(entry);
+	}
+
+	BT_DBG("All LE pending connections cleared");
+}
+
 static void inquiry_complete(struct hci_dev *hdev, u8 status)
 {
 	if (status) {
@@ -3201,6 +3267,7 @@ struct hci_dev *hci_alloc_dev(void)
 	INIT_LIST_HEAD(&hdev->identity_resolving_keys);
 	INIT_LIST_HEAD(&hdev->remote_oob_data);
 	INIT_LIST_HEAD(&hdev->le_conn_params);
+	INIT_LIST_HEAD(&hdev->pend_le_conns);
 	INIT_LIST_HEAD(&hdev->conn_hash.list);
 
 	INIT_WORK(&hdev->rx_work, hci_rx_work);
@@ -3402,6 +3469,7 @@ void hci_unregister_dev(struct hci_dev *hdev)
 	hci_smp_irks_clear(hdev);
 	hci_remote_oob_data_clear(hdev);
 	hci_conn_params_clear(hdev);
+	hci_pend_le_conns_clear(hdev);
 	hci_dev_unlock(hdev);
 
 	hci_dev_put(hdev);
-- 
1.8.5.4


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

* [RFC v10 06/10] Bluetooth: Introduce LE auto connection infrastructure
  2014-02-18 20:15 [RFC v10 01/10] Bluetooth: Create hci_req_add_le_scan_disable helper Andre Guedes
                   ` (3 preceding siblings ...)
  2014-02-18 20:15 ` [RFC v10 05/10] Bluetooth: Introduce hdev->pend_le_conn list Andre Guedes
@ 2014-02-18 20:15 ` Andre Guedes
  2014-02-18 20:52   ` Marcel Holtmann
  2014-02-18 20:15 ` [RFC v10 07/10] Bluetooth: Temporarily stop background scanning on discovery Andre Guedes
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 16+ messages in thread
From: Andre Guedes @ 2014-02-18 20:15 UTC (permalink / raw)
  To: linux-bluetooth

This patch introduces the LE auto connection infrastructure which
will be used to implement the LE auto connection options.

In summary, the auto connection mechanism works as follows: Once the
first pending LE connection is created, the background scanning is
started. When the target device is found in range, the kernel
autonomously starts the connection attempt. If connection is
established successfully, that pending LE connection is deleted and
the background is stopped.

To achieve that, this patch introduces the hci_update_background_scan()
which controls the background scanning state. This function starts or
stops the background scanning based on the hdev->pend_le_conns list. If
there is no pending LE connection, the background scanning is stopped.
Otherwise, we start the background scanning.

Then, every time a pending LE connection is added we call hci_update_
background_scan() so the background scanning is started (in case it is
not already running). Likewise, every time a pending LE connection is
deleted we call hci_update_background_scan() so the background scanning
is stopped (in case this was the last pending LE connection) or it is
started again (in case we have more pending LE connections). Finally,
we also call hci_update_background_scan() in hci_le_conn_failed() so
the background scan is restarted in case the connection establishment
fails. This way the background scanning keeps running until all pending
LE connection are established.

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

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index f0617ab..297b954 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -788,6 +788,8 @@ void hci_pend_le_conn_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type);
 void hci_pend_le_conn_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type);
 void hci_pend_le_conns_clear(struct hci_dev *hdev);
 
+void hci_update_background_scan(struct hci_dev *hdev);
+
 void hci_uuids_clear(struct hci_dev *hdev);
 
 void hci_link_keys_clear(struct hci_dev *hdev);
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 0ae7692..e291d68 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -527,6 +527,11 @@ void hci_le_conn_failed(struct hci_conn *conn, u8 status)
 	hci_proto_connect_cfm(conn, status);
 
 	hci_conn_del(conn);
+
+	/* Since we may have temporarily stopped the background scanning in
+	 * favor of connection establishment, we should restart it.
+	 */
+	hci_update_background_scan(hdev);
 }
 
 static void create_le_conn_complete(struct hci_dev *hdev, u8 status)
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 992f9ea..18ef960 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -3114,7 +3114,7 @@ void hci_pend_le_conn_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type)
 
 	entry = hci_pend_le_conn_lookup(hdev, addr, addr_type);
 	if (entry)
-		return;
+		goto done;
 
 	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
 	if (!entry) {
@@ -3128,6 +3128,9 @@ void hci_pend_le_conn_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type)
 	list_add(&entry->list, &hdev->pend_le_conns);
 
 	BT_DBG("addr %pMR (type %u)", addr, addr_type);
+
+done:
+	hci_update_background_scan(hdev);
 }
 
 /* This function requires the caller holds hdev->lock */
@@ -3137,12 +3140,15 @@ void hci_pend_le_conn_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type)
 
 	entry = hci_pend_le_conn_lookup(hdev, addr, addr_type);
 	if (!entry)
-		return;
+		goto done;
 
 	list_del(&entry->list);
 	kfree(entry);
 
 	BT_DBG("addr %pMR (type %u)", addr, addr_type);
+
+done:
+	hci_update_background_scan(hdev);
 }
 
 /* This function requires the caller holds hdev->lock */
@@ -4706,3 +4712,76 @@ void hci_req_add_le_scan_disable(struct hci_request *req)
 	cp.enable = LE_SCAN_DISABLE;
 	hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp);
 }
+
+static void update_background_scan_complete(struct hci_dev *hdev, u8 status)
+{
+	if (status)
+		BT_DBG("HCI request failed to update background scanning: "
+		       "status 0x%2.2x", status);
+}
+
+/* This function controls the background scanning based on hdev->pend_le_conns
+ * list. If there are pending LE connection we start the background scanning,
+ * otherwise we stop it.
+ *
+ * This function requires the caller holds hdev->lock.
+ */
+void hci_update_background_scan(struct hci_dev *hdev)
+{
+	struct hci_cp_le_set_scan_param param_cp;
+	struct hci_cp_le_set_scan_enable enable_cp;
+	struct hci_request req;
+	struct hci_conn *conn;
+	int err;
+
+	hci_req_init(&req, hdev);
+
+	if (list_empty(&hdev->pend_le_conns)) {
+		/* If there is no pending LE connections, we should stop
+		 * the background scanning.
+		 */
+
+		/* If controller is not scanning we are done. */
+		if (!test_bit(HCI_LE_SCAN, &hdev->dev_flags))
+			return;
+
+		hci_req_add_le_scan_disable(&req);
+
+		BT_DBG("%s stopping background scanning", hdev->name);
+	} else {
+		/* If there is at least one pending LE connection, we should
+		 * keep the background scan running.
+		 */
+
+		/* If controller is already scanning we are done. */
+		if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
+			return;
+
+		/* If controller is connecting, we should not start scanning
+		 * since some controllers are not able to scan and connect at
+		 * the same time.
+		 */
+		conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
+		if (conn)
+			return;
+
+		memset(&param_cp, 0, sizeof(param_cp));
+		param_cp.type = LE_SCAN_PASSIVE;
+		param_cp.interval = cpu_to_le16(hdev->le_scan_interval);
+		param_cp.window = cpu_to_le16(hdev->le_scan_window);
+		hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
+			    &param_cp);
+
+		memset(&enable_cp, 0, sizeof(enable_cp));
+		enable_cp.enable = LE_SCAN_ENABLE;
+		enable_cp.filter_dup = LE_SCAN_FILTER_DUP_DISABLE;
+		hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
+			    &enable_cp);
+
+		BT_DBG("%s starting background scanning", hdev->name);
+	}
+
+	err = hci_req_run(&req, update_background_scan_complete);
+	if (err)
+		BT_ERR("Failed to run HCI request: err %d", err);
+}
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 87baf21..b25cefd 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -3628,25 +3628,69 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 
 	hci_proto_connect_cfm(conn, ev->status);
 
+	hci_pend_le_conn_del(hdev, &ev->bdaddr, ev->bdaddr_type);
+
 unlock:
 	hci_dev_unlock(hdev);
 }
 
+/* This function requires the caller holds hdev->lock */
+static void check_pending_le_conn(struct hci_dev *hdev, bdaddr_t *addr,
+				  u8 addr_type)
+{
+	struct hci_conn *conn;
+	u8 bdaddr_type;
+
+	if (!hci_pend_le_conn_lookup(hdev, addr, addr_type))
+		return;
+
+	if (addr_type == ADDR_LE_DEV_PUBLIC)
+		bdaddr_type = BDADDR_LE_PUBLIC;
+	else
+		bdaddr_type = BDADDR_LE_RANDOM;
+
+	conn = hci_connect(hdev, LE_LINK, addr, bdaddr_type, BT_SECURITY_LOW,
+			   HCI_AT_NO_BONDING);
+	if (!IS_ERR(conn))
+		return;
+
+	switch (PTR_ERR(conn)) {
+	case -EBUSY:
+		/* If hci_connect() returns -EBUSY it means there is already
+		 * an LE connection attempt going on. Since controllers don't
+		 * support more than one connection attempt at the time, we
+		 * don't consider this an error case.
+		 */
+		break;
+	default:
+		BT_DBG("Failed to connect: err %ld", PTR_ERR(conn));
+	}
+}
+
 static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	u8 num_reports = skb->data[0];
 	void *ptr = &skb->data[1];
 	s8 rssi;
 
+	hci_dev_lock(hdev);
+
 	while (num_reports--) {
 		struct hci_ev_le_advertising_info *ev = ptr;
 
+		if (ev->evt_type == LE_ADV_IND ||
+		    ev->evt_type == LE_ADV_DIRECT_IND)
+			check_pending_le_conn(hdev, &ev->bdaddr,
+					      ev->bdaddr_type);
+
 		rssi = ev->data[ev->length];
 		mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
 				  NULL, rssi, 0, 1, ev->data, ev->length);
 
 		ptr += sizeof(*ev) + ev->length + 1;
 	}
+
+	hci_dev_unlock(hdev);
 }
 
 static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
-- 
1.8.5.4


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

* [RFC v10 07/10] Bluetooth: Temporarily stop background scanning on discovery
  2014-02-18 20:15 [RFC v10 01/10] Bluetooth: Create hci_req_add_le_scan_disable helper Andre Guedes
                   ` (4 preceding siblings ...)
  2014-02-18 20:15 ` [RFC v10 06/10] Bluetooth: Introduce LE auto connection infrastructure Andre Guedes
@ 2014-02-18 20:15 ` Andre Guedes
  2014-02-18 20:15 ` [RFC v10 08/10] Bluetooth: Introduce LE auto connect options Andre Guedes
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 16+ messages in thread
From: Andre Guedes @ 2014-02-18 20:15 UTC (permalink / raw)
  To: linux-bluetooth

If the user sends a mgmt start discovery command while the background
scanning is running, we should temporarily stop it. Once the discovery
finishes, we start the background scanning again.

Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
 net/bluetooth/hci_core.c |  2 ++
 net/bluetooth/mgmt.c     | 12 ++++++------
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 18ef960..9434d1c 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1612,6 +1612,8 @@ void hci_discovery_set_state(struct hci_dev *hdev, int state)
 
 	switch (state) {
 	case DISCOVERY_STOPPED:
+		hci_update_background_scan(hdev);
+
 		if (hdev->discovery.state != DISCOVERY_STARTING)
 			mgmt_discovering(hdev, 0);
 		break;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 98396f9..70ca1a7 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -3343,12 +3343,12 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
 			goto failed;
 		}
 
-		if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) {
-			err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
-					 MGMT_STATUS_BUSY);
-			mgmt_pending_remove(cmd);
-			goto failed;
-		}
+		/* If controller is scanning, it means the background scanning
+		 * is running. Thus, we should temporarily stop it in order to
+		 * set the discovery scanning parameters.
+		 */
+		if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
+			hci_req_add_le_scan_disable(&req);
 
 		memset(&param_cp, 0, sizeof(param_cp));
 		param_cp.type = LE_SCAN_ACTIVE;
-- 
1.8.5.4


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

* [RFC v10 08/10] Bluetooth: Introduce LE auto connect options
  2014-02-18 20:15 [RFC v10 01/10] Bluetooth: Create hci_req_add_le_scan_disable helper Andre Guedes
                   ` (5 preceding siblings ...)
  2014-02-18 20:15 ` [RFC v10 07/10] Bluetooth: Temporarily stop background scanning on discovery Andre Guedes
@ 2014-02-18 20:15 ` Andre Guedes
  2014-02-18 20:15 ` [RFC v10 09/10] Bluetooth: Auto connection and power on Andre Guedes
  2014-02-18 20:15 ` [RFC v10 10/10] Bluetooth: Add le_auto_conn file on debugfs Andre Guedes
  8 siblings, 0 replies; 16+ messages in thread
From: Andre Guedes @ 2014-02-18 20:15 UTC (permalink / raw)
  To: linux-bluetooth

This patch introduces the LE auto connection options: HCI_AUTO_CONN_
ALWAYS and HCI_AUTO_CONN_LINK_LOSS. Their working mechanism are
described as follows:

The HCI_AUTO_CONN_ALWAYS option configures the kernel to always re-
establish the connection, no matter the reason the connection was
terminated. This feature is required by some LE profiles such as
HID over GATT, Health Thermometer and Blood Pressure. These profiles
require the host autonomously connect to the device as soon as it
enters in connectable mode (start advertising) so the device is able
to delivery notifications or indications.

The BT_AUTO_CONN_LINK_LOSS option configures the kernel to re-
establish the connection in case the connection was terminated due
to a link loss. This feature is required by the majority of LE
profiles such as Proximity, Find Me, Cycling Speed and Cadence and
Time.

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

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 297b954..de6357b 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -393,6 +393,12 @@ struct hci_conn_params {
 
 	u16 conn_min_interval;
 	u16 conn_max_interval;
+
+	enum {
+		HCI_AUTO_CONN_DISABLED,
+		HCI_AUTO_CONN_ALWAYS,
+		HCI_AUTO_CONN_LINK_LOSS,
+	} auto_connect;
 };
 
 extern struct list_head hci_dev_list;
@@ -778,7 +784,8 @@ int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
 struct hci_conn_params *hci_conn_params_lookup(struct hci_dev *hdev,
 					       bdaddr_t *addr, u8 addr_type);
 void hci_conn_params_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type,
-			 u16 conn_min_interval, u16 conn_max_interval);
+			 u8 auto_connect, u16 conn_min_interval,
+			 u16 conn_max_interval);
 void hci_conn_params_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type);
 void hci_conn_params_clear(struct hci_dev *hdev);
 
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 9434d1c..4f9db12 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -3037,7 +3037,8 @@ struct hci_conn_params *hci_conn_params_lookup(struct hci_dev *hdev,
 
 /* This function requires the caller holds hdev->lock */
 void hci_conn_params_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type,
-			 u16 conn_min_interval, u16 conn_max_interval)
+			 u8 auto_connect, u16 conn_min_interval,
+			 u16 conn_max_interval)
 {
 	struct hci_conn_params *params;
 
@@ -3045,6 +3046,7 @@ void hci_conn_params_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type,
 	if (params) {
 		params->conn_min_interval = conn_min_interval;
 		params->conn_max_interval = conn_max_interval;
+		params->auto_connect = auto_connect;
 		return;
 	}
 
@@ -3058,12 +3060,13 @@ void hci_conn_params_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type,
 	params->addr_type = addr_type;
 	params->conn_min_interval = conn_min_interval;
 	params->conn_max_interval = conn_max_interval;
+	params->auto_connect = auto_connect;
 
 	list_add(&params->list, &hdev->le_conn_params);
 
-	BT_DBG("addr %pMR (type %u) conn_min_interval 0x%.4x "
-	       "conn_max_interval 0x%.4x", addr, addr_type, conn_min_interval,
-	       conn_max_interval);
+	BT_DBG("addr %pMR (type %u) auto_connect %u conn_min_interval 0x%.4x "
+	       "conn_max_interval 0x%.4x", addr, addr_type, auto_connect,
+	       conn_min_interval, conn_max_interval);
 }
 
 /* This function requires the caller holds hdev->lock */
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index b25cefd..86c02dd 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1825,6 +1825,7 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	struct hci_ev_disconn_complete *ev = (void *) skb->data;
 	u8 reason = hci_to_mgmt_reason(ev->reason);
+	struct hci_conn_params *params;
 	struct hci_conn *conn;
 	u8 type;
 
@@ -1851,6 +1852,23 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 	if (conn->type == ACL_LINK && conn->flush_key)
 		hci_remove_link_key(hdev, &conn->dst);
 
+	params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type);
+	if (params) {
+		switch (params->auto_connect) {
+		case HCI_AUTO_CONN_LINK_LOSS:
+			if (ev->reason != HCI_ERROR_CONNECTION_TIMEOUT)
+				break;
+			/* Fall through */
+
+		case HCI_AUTO_CONN_ALWAYS:
+			hci_pend_le_conn_add(hdev, &conn->dst, conn->dst_type);
+			break;
+
+		default:
+			break;
+		}
+	}
+
 	type = conn->type;
 
 	hci_proto_disconn_cfm(conn, ev->reason);
-- 
1.8.5.4


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

* [RFC v10 09/10] Bluetooth: Auto connection and power on
  2014-02-18 20:15 [RFC v10 01/10] Bluetooth: Create hci_req_add_le_scan_disable helper Andre Guedes
                   ` (6 preceding siblings ...)
  2014-02-18 20:15 ` [RFC v10 08/10] Bluetooth: Introduce LE auto connect options Andre Guedes
@ 2014-02-18 20:15 ` Andre Guedes
  2014-02-18 20:55   ` Marcel Holtmann
  2014-02-18 20:15 ` [RFC v10 10/10] Bluetooth: Add le_auto_conn file on debugfs Andre Guedes
  8 siblings, 1 reply; 16+ messages in thread
From: Andre Guedes @ 2014-02-18 20:15 UTC (permalink / raw)
  To: linux-bluetooth

When hdev is closed (e.g. Mgmt power off command, RFKILL or controller
is reset), the ongoing active connections are silently dropped by the
controller (no Disconnection Complete Event is sent to host). For that
reason, the devices that require HCI_AUTO_CONN_ALWAYS are not added to
hdev->pend_le_conns list and they won't auto connect.

So to fix this issue, during hdev closing, we remove all pending LE
connections. After adapter is powered on, we add a pending LE connection
for each HCI_AUTO_CONN_ALWAYS address.

This way, the auto connection mechanism works propely after a power
off and power on sequence as well as RFKILL block/unblock.

Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
 net/bluetooth/hci_core.c |  1 +
 net/bluetooth/mgmt.c     | 13 +++++++++++++
 2 files changed, 14 insertions(+)

diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 4f9db12..5d5d38b 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -2088,6 +2088,7 @@ static int hci_dev_do_close(struct hci_dev *hdev)
 	hci_dev_lock(hdev);
 	hci_inquiry_cache_flush(hdev);
 	hci_conn_hash_flush(hdev);
+	hci_pend_le_conns_clear(hdev);
 	hci_dev_unlock(hdev);
 
 	hci_notify(hdev, HCI_DEV_DOWN);
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 70ca1a7..511a0fc 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -4510,6 +4510,17 @@ void mgmt_index_removed(struct hci_dev *hdev)
 	mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
 }
 
+/* This function requires the caller holds hdev->lock */
+static void restart_le_auto_conns(struct hci_dev *hdev)
+{
+	struct hci_conn_params *p;
+
+	list_for_each_entry(p, &hdev->le_conn_params, list) {
+		if (p->auto_connect == HCI_AUTO_CONN_ALWAYS)
+			hci_pend_le_conn_add(hdev, &p->addr, p->addr_type);
+	}
+}
+
 static void powered_complete(struct hci_dev *hdev, u8 status)
 {
 	struct cmd_lookup match = { NULL, hdev };
@@ -4518,6 +4529,8 @@ static void powered_complete(struct hci_dev *hdev, u8 status)
 
 	hci_dev_lock(hdev);
 
+	restart_le_auto_conns(hdev);
+
 	mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
 
 	new_settings(hdev, match.sk);
-- 
1.8.5.4


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

* [RFC v10 10/10] Bluetooth: Add le_auto_conn file on debugfs
  2014-02-18 20:15 [RFC v10 01/10] Bluetooth: Create hci_req_add_le_scan_disable helper Andre Guedes
                   ` (7 preceding siblings ...)
  2014-02-18 20:15 ` [RFC v10 09/10] Bluetooth: Auto connection and power on Andre Guedes
@ 2014-02-18 20:15 ` Andre Guedes
  2014-02-18 20:53   ` Marcel Holtmann
  8 siblings, 1 reply; 16+ messages in thread
From: Andre Guedes @ 2014-02-18 20:15 UTC (permalink / raw)
  To: linux-bluetooth

This patch adds to debugfs the le_auto_conn file. This file will be
used to test LE auto connection infrastructure.

To add a new auto connection address we write on le_auto_conn file
following the format <address> <address type> <auto_connect>.

The <address type> values are:
  * 0 for public address
  * 1 for random address

The <auto_connect> values are (for more details see struct hci_
conn_params):
  * 0 for disabled
  * 1 for always
  * 2 for link loss

So for instance, if you want the kernel autonomously establishes
connections with device AA:BB:CC:DD:EE:FF (public address) every
time the device enters in connectable mode (starts advertising),
you should run the command:
$ echo "AA:BB:CC:DD:EE:FF 0 1" > /sys/kernel/debug/bluetooth/hci0/le_auto_conn

To get the list of connection parameters configured in kernel, read
the le_auto_conn file:
$ cat /sys/kernel/debug/bluetooth/hci0/le_auto_conn

Finally, to clear the connection parameters list, write an empty
string:
$ echo "" > /sys/kernel/debug/bluetooth/hci0/le_auto_conn

This file is created only if LE is enabled.

Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
 net/bluetooth/hci_core.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 85 insertions(+)

diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 5d5d38b..3fd6a6f 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -728,6 +728,89 @@ static const struct file_operations lowpan_debugfs_fops = {
 	.llseek		= default_llseek,
 };
 
+static int le_auto_conn_show(struct seq_file *sf, void *ptr)
+{
+	struct hci_dev *hdev = sf->private;
+	struct hci_conn_params *p;
+
+	hci_dev_lock(hdev);
+
+	list_for_each_entry(p, &hdev->le_conn_params, list) {
+		seq_printf(sf, "%pMR %u %u\n", &p->addr, p->addr_type,
+			   p->auto_connect);
+	}
+
+	hci_dev_unlock(hdev);
+
+	return 0;
+}
+
+static int le_auto_conn_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, le_auto_conn_show, inode->i_private);
+}
+
+static ssize_t le_auto_conn_write(struct file *file, const char __user *data,
+				  size_t count, loff_t *offset)
+{
+	struct seq_file *sf = file->private_data;
+	struct hci_dev *hdev = sf->private;
+	u8 auto_connect;
+	bdaddr_t addr;
+	u8 addr_type;
+	char *buf;
+	int n;
+
+	/* Don't allow partial write */
+	if (*offset != 0)
+		return -EINVAL;
+
+	/* If empty string, clear the connection parameters and pending LE
+	 * connection list.
+	 */
+	if (count == 1) {
+		hci_dev_lock(hdev);
+		hci_conn_params_clear(hdev);
+		hci_pend_le_conns_clear(hdev);
+		hci_dev_unlock(hdev);
+		return count;
+	}
+
+	buf = kzalloc(count, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	if (copy_from_user(buf, data, count)) {
+		kfree(buf);
+		return -EFAULT;
+	}
+
+	n = sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx %hhu %hhu", &addr.b[5],
+		   &addr.b[4], &addr.b[3], &addr.b[2], &addr.b[1], &addr.b[0],
+		   &addr_type, &auto_connect);
+	if (n != 8) {
+		kfree(buf);
+		return -EINVAL;
+	}
+
+	hci_dev_lock(hdev);
+	hci_conn_params_add(hdev, &addr, addr_type, auto_connect,
+			    hdev->le_conn_min_interval,
+			    hdev->le_conn_max_interval);
+	hci_dev_unlock(hdev);
+
+	kfree(buf);
+	return count;
+}
+
+static const struct file_operations le_auto_conn_fops = {
+	.open		= le_auto_conn_open,
+	.read		= seq_read,
+	.write		= le_auto_conn_write,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
 /* ---- HCI requests ---- */
 
 static void hci_req_sync_complete(struct hci_dev *hdev, u8 result)
@@ -1520,6 +1603,8 @@ static int __hci_init(struct hci_dev *hdev)
 				    hdev, &conn_max_interval_fops);
 		debugfs_create_file("6lowpan", 0644, hdev->debugfs, hdev,
 				    &lowpan_debugfs_fops);
+		debugfs_create_file("le_auto_conn", 0644, hdev->debugfs, hdev,
+				    &le_auto_conn_fops);
 	}
 
 	return 0;
-- 
1.8.5.4


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

* Re: [RFC v10 06/10] Bluetooth: Introduce LE auto connection infrastructure
  2014-02-18 20:15 ` [RFC v10 06/10] Bluetooth: Introduce LE auto connection infrastructure Andre Guedes
@ 2014-02-18 20:52   ` Marcel Holtmann
  2014-02-19 16:37     ` Andre Guedes
  0 siblings, 1 reply; 16+ messages in thread
From: Marcel Holtmann @ 2014-02-18 20:52 UTC (permalink / raw)
  To: Andre Guedes; +Cc: bluez mailin list (linux-bluetooth@vger.kernel.org)

Hi Andre,

> This patch introduces the LE auto connection infrastructure which
> will be used to implement the LE auto connection options.
> 
> In summary, the auto connection mechanism works as follows: Once the
> first pending LE connection is created, the background scanning is
> started. When the target device is found in range, the kernel
> autonomously starts the connection attempt. If connection is
> established successfully, that pending LE connection is deleted and
> the background is stopped.
> 
> To achieve that, this patch introduces the hci_update_background_scan()
> which controls the background scanning state. This function starts or
> stops the background scanning based on the hdev->pend_le_conns list. If
> there is no pending LE connection, the background scanning is stopped.
> Otherwise, we start the background scanning.
> 
> Then, every time a pending LE connection is added we call hci_update_
> background_scan() so the background scanning is started (in case it is
> not already running). Likewise, every time a pending LE connection is
> deleted we call hci_update_background_scan() so the background scanning
> is stopped (in case this was the last pending LE connection) or it is
> started again (in case we have more pending LE connections). Finally,
> we also call hci_update_background_scan() in hci_le_conn_failed() so
> the background scan is restarted in case the connection establishment
> fails. This way the background scanning keeps running until all pending
> LE connection are established.
> 
> Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
> ---
> include/net/bluetooth/hci_core.h |  2 +
> net/bluetooth/hci_conn.c         |  5 +++
> net/bluetooth/hci_core.c         | 83 +++++++++++++++++++++++++++++++++++++++-
> net/bluetooth/hci_event.c        | 44 +++++++++++++++++++++
> 4 files changed, 132 insertions(+), 2 deletions(-)
> 
> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> index f0617ab..297b954 100644
> --- a/include/net/bluetooth/hci_core.h
> +++ b/include/net/bluetooth/hci_core.h
> @@ -788,6 +788,8 @@ void hci_pend_le_conn_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type);
> void hci_pend_le_conn_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type);
> void hci_pend_le_conns_clear(struct hci_dev *hdev);
> 
> +void hci_update_background_scan(struct hci_dev *hdev);
> +
> void hci_uuids_clear(struct hci_dev *hdev);
> 
> void hci_link_keys_clear(struct hci_dev *hdev);
> diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
> index 0ae7692..e291d68 100644
> --- a/net/bluetooth/hci_conn.c
> +++ b/net/bluetooth/hci_conn.c
> @@ -527,6 +527,11 @@ void hci_le_conn_failed(struct hci_conn *conn, u8 status)
> 	hci_proto_connect_cfm(conn, status);
> 
> 	hci_conn_del(conn);
> +
> +	/* Since we may have temporarily stopped the background scanning in
> +	 * favor of connection establishment, we should restart it.
> +	 */
> +	hci_update_background_scan(hdev);
> }
> 
> static void create_le_conn_complete(struct hci_dev *hdev, u8 status)
> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> index 992f9ea..18ef960 100644
> --- a/net/bluetooth/hci_core.c
> +++ b/net/bluetooth/hci_core.c
> @@ -3114,7 +3114,7 @@ void hci_pend_le_conn_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type)
> 
> 	entry = hci_pend_le_conn_lookup(hdev, addr, addr_type);
> 	if (entry)
> -		return;
> +		goto done;
> 
> 	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
> 	if (!entry) {
> @@ -3128,6 +3128,9 @@ void hci_pend_le_conn_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type)
> 	list_add(&entry->list, &hdev->pend_le_conns);
> 
> 	BT_DBG("addr %pMR (type %u)", addr, addr_type);
> +
> +done:
> +	hci_update_background_scan(hdev);
> }
> 
> /* This function requires the caller holds hdev->lock */
> @@ -3137,12 +3140,15 @@ void hci_pend_le_conn_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type)
> 
> 	entry = hci_pend_le_conn_lookup(hdev, addr, addr_type);
> 	if (!entry)
> -		return;
> +		goto done;
> 
> 	list_del(&entry->list);
> 	kfree(entry);
> 
> 	BT_DBG("addr %pMR (type %u)", addr, addr_type);
> +
> +done:
> +	hci_update_background_scan(hdev);
> }
> 
> /* This function requires the caller holds hdev->lock */
> @@ -4706,3 +4712,76 @@ void hci_req_add_le_scan_disable(struct hci_request *req)
> 	cp.enable = LE_SCAN_DISABLE;
> 	hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp);
> }
> +
> +static void update_background_scan_complete(struct hci_dev *hdev, u8 status)
> +{
> +	if (status)
> +		BT_DBG("HCI request failed to update background scanning: "
> +		       "status 0x%2.2x", status);
> +}
> +
> +/* This function controls the background scanning based on hdev->pend_le_conns
> + * list. If there are pending LE connection we start the background scanning,
> + * otherwise we stop it.
> + *
> + * This function requires the caller holds hdev->lock.
> + */
> +void hci_update_background_scan(struct hci_dev *hdev)
> +{
> +	struct hci_cp_le_set_scan_param param_cp;
> +	struct hci_cp_le_set_scan_enable enable_cp;
> +	struct hci_request req;
> +	struct hci_conn *conn;
> +	int err;
> +
> +	hci_req_init(&req, hdev);
> +
> +	if (list_empty(&hdev->pend_le_conns)) {
> +		/* If there is no pending LE connections, we should stop
> +		 * the background scanning.
> +		 */
> +
> +		/* If controller is not scanning we are done. */
> +		if (!test_bit(HCI_LE_SCAN, &hdev->dev_flags))
> +			return;
> +
> +		hci_req_add_le_scan_disable(&req);
> +
> +		BT_DBG("%s stopping background scanning", hdev->name);
> +	} else {
> +		/* If there is at least one pending LE connection, we should
> +		 * keep the background scan running.
> +		 */
> +
> +		/* If controller is already scanning we are done. */
> +		if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
> +			return;
> +
> +		/* If controller is connecting, we should not start scanning
> +		 * since some controllers are not able to scan and connect at
> +		 * the same time.
> +		 */
> +		conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
> +		if (conn)
> +			return;
> +
> +		memset(&param_cp, 0, sizeof(param_cp));
> +		param_cp.type = LE_SCAN_PASSIVE;
> +		param_cp.interval = cpu_to_le16(hdev->le_scan_interval);
> +		param_cp.window = cpu_to_le16(hdev->le_scan_window);
> +		hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
> +			    &param_cp);
> +
> +		memset(&enable_cp, 0, sizeof(enable_cp));
> +		enable_cp.enable = LE_SCAN_ENABLE;
> +		enable_cp.filter_dup = LE_SCAN_FILTER_DUP_DISABLE;
> +		hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
> +			    &enable_cp);
> +
> +		BT_DBG("%s starting background scanning", hdev->name);
> +	}

so I was inclined to take the whole patch set as it is, but this code is not useful at all at the moment.

Disabling the duplicate filter is a horrible idea. I just have my controller going crazy. I rather background scan with the filter enabled and then from time to time disable scanning and start it again to make sure that new devices are captured. This idea of reporting everything up to the host every single time is insane.

Also we need to fine tune the scan_interval and scan_window we use for connection attempts for background scanning. This is just crazy. We have a mgmt command that lets us configure these values. So please make sure that it integrates with the background scanning and allows us to change these parameters on the fly. I want to see what kind of difference different values make.

There is a difference between we lost our link and want to reconnect as quickly as possible. And hey, we have some devices that we might want to connect to. When you find it, go ahead and connect, but no hurry type of connection establishment.

And most importantly. Make sure this works with the RPA resolving work that we just merged. I am testing this against my iPhone and auto-connect is not picking up my public identity address.

Regards

Marcel


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

* Re: [RFC v10 10/10] Bluetooth: Add le_auto_conn file on debugfs
  2014-02-18 20:15 ` [RFC v10 10/10] Bluetooth: Add le_auto_conn file on debugfs Andre Guedes
@ 2014-02-18 20:53   ` Marcel Holtmann
  2014-02-19 16:37     ` Andre Guedes
  0 siblings, 1 reply; 16+ messages in thread
From: Marcel Holtmann @ 2014-02-18 20:53 UTC (permalink / raw)
  To: Andre Guedes; +Cc: bluez mailin list (linux-bluetooth@vger.kernel.org)

Hi Andre,

> This patch adds to debugfs the le_auto_conn file. This file will be
> used to test LE auto connection infrastructure.
> 
> To add a new auto connection address we write on le_auto_conn file
> following the format <address> <address type> <auto_connect>.
> 
> The <address type> values are:
>  * 0 for public address
>  * 1 for random address
> 
> The <auto_connect> values are (for more details see struct hci_
> conn_params):
>  * 0 for disabled
>  * 1 for always
>  * 2 for link loss
> 
> So for instance, if you want the kernel autonomously establishes
> connections with device AA:BB:CC:DD:EE:FF (public address) every
> time the device enters in connectable mode (starts advertising),
> you should run the command:
> $ echo "AA:BB:CC:DD:EE:FF 0 1" > /sys/kernel/debug/bluetooth/hci0/le_auto_conn
> 
> To get the list of connection parameters configured in kernel, read
> the le_auto_conn file:
> $ cat /sys/kernel/debug/bluetooth/hci0/le_auto_conn
> 
> Finally, to clear the connection parameters list, write an empty
> string:
> $ echo "" > /sys/kernel/debug/bluetooth/hci0/le_auto_conn

adding the first entry to this list should start scanning and deleting the last entry should stop scanning.

Regards

Marcel


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

* Re: [RFC v10 09/10] Bluetooth: Auto connection and power on
  2014-02-18 20:15 ` [RFC v10 09/10] Bluetooth: Auto connection and power on Andre Guedes
@ 2014-02-18 20:55   ` Marcel Holtmann
  2014-02-19 16:37     ` Andre Guedes
  0 siblings, 1 reply; 16+ messages in thread
From: Marcel Holtmann @ 2014-02-18 20:55 UTC (permalink / raw)
  To: Andre Guedes; +Cc: bluez mailin list (linux-bluetooth@vger.kernel.org)

Hi Andre,

> When hdev is closed (e.g. Mgmt power off command, RFKILL or controller
> is reset), the ongoing active connections are silently dropped by the
> controller (no Disconnection Complete Event is sent to host). For that
> reason, the devices that require HCI_AUTO_CONN_ALWAYS are not added to
> hdev->pend_le_conns list and they won't auto connect.
> 
> So to fix this issue, during hdev closing, we remove all pending LE
> connections. After adapter is powered on, we add a pending LE connection
> for each HCI_AUTO_CONN_ALWAYS address.
> 
> This way, the auto connection mechanism works propely after a power
> off and power on sequence as well as RFKILL block/unblock.

and when background scan is running, you might want to make sure to disable LE scan first before doing the actual power down. I just crashed my controller.

Regards

Marcel


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

* Re: [RFC v10 06/10] Bluetooth: Introduce LE auto connection infrastructure
  2014-02-18 20:52   ` Marcel Holtmann
@ 2014-02-19 16:37     ` Andre Guedes
  0 siblings, 0 replies; 16+ messages in thread
From: Andre Guedes @ 2014-02-19 16:37 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: bluez mailin list (linux-bluetooth@vger.kernel.org)

Hi Marcel,

On Tue, Feb 18, 2014 at 5:52 PM, Marcel Holtmann <marcel@holtmann.org> wrot=
e:
> Hi Andre,
>
>> This patch introduces the LE auto connection infrastructure which
>> will be used to implement the LE auto connection options.
>>
>> In summary, the auto connection mechanism works as follows: Once the
>> first pending LE connection is created, the background scanning is
>> started. When the target device is found in range, the kernel
>> autonomously starts the connection attempt. If connection is
>> established successfully, that pending LE connection is deleted and
>> the background is stopped.
>>
>> To achieve that, this patch introduces the hci_update_background_scan()
>> which controls the background scanning state. This function starts or
>> stops the background scanning based on the hdev->pend_le_conns list. If
>> there is no pending LE connection, the background scanning is stopped.
>> Otherwise, we start the background scanning.
>>
>> Then, every time a pending LE connection is added we call hci_update_
>> background_scan() so the background scanning is started (in case it is
>> not already running). Likewise, every time a pending LE connection is
>> deleted we call hci_update_background_scan() so the background scanning
>> is stopped (in case this was the last pending LE connection) or it is
>> started again (in case we have more pending LE connections). Finally,
>> we also call hci_update_background_scan() in hci_le_conn_failed() so
>> the background scan is restarted in case the connection establishment
>> fails. This way the background scanning keeps running until all pending
>> LE connection are established.
>>
>> Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
>> ---
>> include/net/bluetooth/hci_core.h |  2 +
>> net/bluetooth/hci_conn.c         |  5 +++
>> net/bluetooth/hci_core.c         | 83 ++++++++++++++++++++++++++++++++++=
+++++-
>> net/bluetooth/hci_event.c        | 44 +++++++++++++++++++++
>> 4 files changed, 132 insertions(+), 2 deletions(-)
>>
>> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hc=
i_core.h
>> index f0617ab..297b954 100644
>> --- a/include/net/bluetooth/hci_core.h
>> +++ b/include/net/bluetooth/hci_core.h
>> @@ -788,6 +788,8 @@ void hci_pend_le_conn_add(struct hci_dev *hdev, bdad=
dr_t *addr, u8 addr_type);
>> void hci_pend_le_conn_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_=
type);
>> void hci_pend_le_conns_clear(struct hci_dev *hdev);
>>
>> +void hci_update_background_scan(struct hci_dev *hdev);
>> +
>> void hci_uuids_clear(struct hci_dev *hdev);
>>
>> void hci_link_keys_clear(struct hci_dev *hdev);
>> diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
>> index 0ae7692..e291d68 100644
>> --- a/net/bluetooth/hci_conn.c
>> +++ b/net/bluetooth/hci_conn.c
>> @@ -527,6 +527,11 @@ void hci_le_conn_failed(struct hci_conn *conn, u8 s=
tatus)
>>       hci_proto_connect_cfm(conn, status);
>>
>>       hci_conn_del(conn);
>> +
>> +     /* Since we may have temporarily stopped the background scanning i=
n
>> +      * favor of connection establishment, we should restart it.
>> +      */
>> +     hci_update_background_scan(hdev);
>> }
>>
>> static void create_le_conn_complete(struct hci_dev *hdev, u8 status)
>> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
>> index 992f9ea..18ef960 100644
>> --- a/net/bluetooth/hci_core.c
>> +++ b/net/bluetooth/hci_core.c
>> @@ -3114,7 +3114,7 @@ void hci_pend_le_conn_add(struct hci_dev *hdev, bd=
addr_t *addr, u8 addr_type)
>>
>>       entry =3D hci_pend_le_conn_lookup(hdev, addr, addr_type);
>>       if (entry)
>> -             return;
>> +             goto done;
>>
>>       entry =3D kzalloc(sizeof(*entry), GFP_KERNEL);
>>       if (!entry) {
>> @@ -3128,6 +3128,9 @@ void hci_pend_le_conn_add(struct hci_dev *hdev, bd=
addr_t *addr, u8 addr_type)
>>       list_add(&entry->list, &hdev->pend_le_conns);
>>
>>       BT_DBG("addr %pMR (type %u)", addr, addr_type);
>> +
>> +done:
>> +     hci_update_background_scan(hdev);
>> }
>>
>> /* This function requires the caller holds hdev->lock */
>> @@ -3137,12 +3140,15 @@ void hci_pend_le_conn_del(struct hci_dev *hdev, =
bdaddr_t *addr, u8 addr_type)
>>
>>       entry =3D hci_pend_le_conn_lookup(hdev, addr, addr_type);
>>       if (!entry)
>> -             return;
>> +             goto done;
>>
>>       list_del(&entry->list);
>>       kfree(entry);
>>
>>       BT_DBG("addr %pMR (type %u)", addr, addr_type);
>> +
>> +done:
>> +     hci_update_background_scan(hdev);
>> }
>>
>> /* This function requires the caller holds hdev->lock */
>> @@ -4706,3 +4712,76 @@ void hci_req_add_le_scan_disable(struct hci_reque=
st *req)
>>       cp.enable =3D LE_SCAN_DISABLE;
>>       hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp);
>> }
>> +
>> +static void update_background_scan_complete(struct hci_dev *hdev, u8 st=
atus)
>> +{
>> +     if (status)
>> +             BT_DBG("HCI request failed to update background scanning: =
"
>> +                    "status 0x%2.2x", status);
>> +}
>> +
>> +/* This function controls the background scanning based on hdev->pend_l=
e_conns
>> + * list. If there are pending LE connection we start the background sca=
nning,
>> + * otherwise we stop it.
>> + *
>> + * This function requires the caller holds hdev->lock.
>> + */
>> +void hci_update_background_scan(struct hci_dev *hdev)
>> +{
>> +     struct hci_cp_le_set_scan_param param_cp;
>> +     struct hci_cp_le_set_scan_enable enable_cp;
>> +     struct hci_request req;
>> +     struct hci_conn *conn;
>> +     int err;
>> +
>> +     hci_req_init(&req, hdev);
>> +
>> +     if (list_empty(&hdev->pend_le_conns)) {
>> +             /* If there is no pending LE connections, we should stop
>> +              * the background scanning.
>> +              */
>> +
>> +             /* If controller is not scanning we are done. */
>> +             if (!test_bit(HCI_LE_SCAN, &hdev->dev_flags))
>> +                     return;
>> +
>> +             hci_req_add_le_scan_disable(&req);
>> +
>> +             BT_DBG("%s stopping background scanning", hdev->name);
>> +     } else {
>> +             /* If there is at least one pending LE connection, we shou=
ld
>> +              * keep the background scan running.
>> +              */
>> +
>> +             /* If controller is already scanning we are done. */
>> +             if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
>> +                     return;
>> +
>> +             /* If controller is connecting, we should not start scanni=
ng
>> +              * since some controllers are not able to scan and connect=
 at
>> +              * the same time.
>> +              */
>> +             conn =3D hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONN=
ECT);
>> +             if (conn)
>> +                     return;
>> +
>> +             memset(&param_cp, 0, sizeof(param_cp));
>> +             param_cp.type =3D LE_SCAN_PASSIVE;
>> +             param_cp.interval =3D cpu_to_le16(hdev->le_scan_interval);
>> +             param_cp.window =3D cpu_to_le16(hdev->le_scan_window);
>> +             hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_c=
p),
>> +                         &param_cp);
>> +
>> +             memset(&enable_cp, 0, sizeof(enable_cp));
>> +             enable_cp.enable =3D LE_SCAN_ENABLE;
>> +             enable_cp.filter_dup =3D LE_SCAN_FILTER_DUP_DISABLE;
>> +             hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable=
_cp),
>> +                         &enable_cp);
>> +
>> +             BT_DBG("%s starting background scanning", hdev->name);
>> +     }
>
> so I was inclined to take the whole patch set as it is, but this code is =
not useful at all at the moment.
>
> Disabling the duplicate filter is a horrible idea. I just have my control=
ler going crazy. I rather background scan with the filter enabled and then =
from time to time disable scanning and start it again to make sure that new=
 devices are captured. This idea of reporting everything up to the host eve=
ry single time is insane.

How many time should we wait to re-enable scan?

> Also we need to fine tune the scan_interval and scan_window we use for co=
nnection attempts for background scanning. This is just crazy. We have a mg=
mt command that lets us configure these values. So please make sure that it=
 integrates with the background scanning and allows us to change these para=
meters on the fly. I want to see what kind of difference different values m=
ake.

The "Set Scan Parameters" command and the background scan are already
integrated. I'll just add an extra patch to restart background scan if
scan parameters are changed.

> There is a difference between we lost our link and want to reconnect as q=
uickly as possible. And hey, we have some devices that we might want to con=
nect to. When you find it, go ahead and connect, but no hurry type of conne=
ction establishment.
>
> And most importantly. Make sure this works with the RPA resolving work th=
at we just merged. I am testing this against my iPhone and auto-connect is =
not picking up my public identity address.

Ok.

Regards,

Andre

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

* Re: [RFC v10 09/10] Bluetooth: Auto connection and power on
  2014-02-18 20:55   ` Marcel Holtmann
@ 2014-02-19 16:37     ` Andre Guedes
  0 siblings, 0 replies; 16+ messages in thread
From: Andre Guedes @ 2014-02-19 16:37 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: bluez mailin list (linux-bluetooth@vger.kernel.org)

Hi Marcel,

On Tue, Feb 18, 2014 at 5:55 PM, Marcel Holtmann <marcel@holtmann.org> wrote:
> Hi Andre,
>
>> When hdev is closed (e.g. Mgmt power off command, RFKILL or controller
>> is reset), the ongoing active connections are silently dropped by the
>> controller (no Disconnection Complete Event is sent to host). For that
>> reason, the devices that require HCI_AUTO_CONN_ALWAYS are not added to
>> hdev->pend_le_conns list and they won't auto connect.
>>
>> So to fix this issue, during hdev closing, we remove all pending LE
>> connections. After adapter is powered on, we add a pending LE connection
>> for each HCI_AUTO_CONN_ALWAYS address.
>>
>> This way, the auto connection mechanism works propely after a power
>> off and power on sequence as well as RFKILL block/unblock.
>
> and when background scan is running, you might want to make sure to disable LE scan first before doing the actual power down. I just crashed my controller.

Hum, I didn't get any crash with my controllers. Could you send your kernel log?

BR,

Andre

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

* Re: [RFC v10 10/10] Bluetooth: Add le_auto_conn file on debugfs
  2014-02-18 20:53   ` Marcel Holtmann
@ 2014-02-19 16:37     ` Andre Guedes
  0 siblings, 0 replies; 16+ messages in thread
From: Andre Guedes @ 2014-02-19 16:37 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: bluez mailin list (linux-bluetooth@vger.kernel.org)

Hi Marcel,

On Tue, Feb 18, 2014 at 5:53 PM, Marcel Holtmann <marcel@holtmann.org> wrote:
> Hi Andre,
>
>> This patch adds to debugfs the le_auto_conn file. This file will be
>> used to test LE auto connection infrastructure.
>>
>> To add a new auto connection address we write on le_auto_conn file
>> following the format <address> <address type> <auto_connect>.
>>
>> The <address type> values are:
>>  * 0 for public address
>>  * 1 for random address
>>
>> The <auto_connect> values are (for more details see struct hci_
>> conn_params):
>>  * 0 for disabled
>>  * 1 for always
>>  * 2 for link loss
>>
>> So for instance, if you want the kernel autonomously establishes
>> connections with device AA:BB:CC:DD:EE:FF (public address) every
>> time the device enters in connectable mode (starts advertising),
>> you should run the command:
>> $ echo "AA:BB:CC:DD:EE:FF 0 1" > /sys/kernel/debug/bluetooth/hci0/le_auto_conn
>>
>> To get the list of connection parameters configured in kernel, read
>> the le_auto_conn file:
>> $ cat /sys/kernel/debug/bluetooth/hci0/le_auto_conn
>>
>> Finally, to clear the connection parameters list, write an empty
>> string:
>> $ echo "" > /sys/kernel/debug/bluetooth/hci0/le_auto_conn
>
> adding the first entry to this list should start scanning and deleting the last entry should stop scanning.

Ok, I'll do it.

BR,

Andre

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

end of thread, other threads:[~2014-02-19 16:37 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-02-18 20:15 [RFC v10 01/10] Bluetooth: Create hci_req_add_le_scan_disable helper Andre Guedes
2014-02-18 20:15 ` [RFC v10 02/10] Bluetooth: Declare le_conn_failed in hci_core.h Andre Guedes
2014-02-18 20:15 ` [RFC v10 03/10] Bluetooth: Stop scanning on LE connection Andre Guedes
2014-02-18 20:15 ` [RFC v10 04/10] Bluetooth: Remove unused function Andre Guedes
2014-02-18 20:15 ` [RFC v10 05/10] Bluetooth: Introduce hdev->pend_le_conn list Andre Guedes
2014-02-18 20:15 ` [RFC v10 06/10] Bluetooth: Introduce LE auto connection infrastructure Andre Guedes
2014-02-18 20:52   ` Marcel Holtmann
2014-02-19 16:37     ` Andre Guedes
2014-02-18 20:15 ` [RFC v10 07/10] Bluetooth: Temporarily stop background scanning on discovery Andre Guedes
2014-02-18 20:15 ` [RFC v10 08/10] Bluetooth: Introduce LE auto connect options Andre Guedes
2014-02-18 20:15 ` [RFC v10 09/10] Bluetooth: Auto connection and power on Andre Guedes
2014-02-18 20:55   ` Marcel Holtmann
2014-02-19 16:37     ` Andre Guedes
2014-02-18 20:15 ` [RFC v10 10/10] Bluetooth: Add le_auto_conn file on debugfs Andre Guedes
2014-02-18 20:53   ` Marcel Holtmann
2014-02-19 16:37     ` Andre Guedes

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.