All of lore.kernel.org
 help / color / mirror / Atom feed
From: Andre Guedes <andre.guedes@openbossa.org>
To: linux-bluetooth@vger.kernel.org
Subject: [RFC v11 03/15] Bluetooth: Stop scanning on LE connection
Date: Mon, 24 Feb 2014 19:30:49 -0300	[thread overview]
Message-ID: <1393281061-14320-4-git-send-email-andre.guedes@openbossa.org> (raw)
In-Reply-To: <1393281061-14320-1-git-send-email-andre.guedes@openbossa.org>

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    | 89 ++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 88 insertions(+), 2 deletions(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 1bb45a4..c3834d3 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -356,6 +356,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 dc8aad9..ae2c3e1 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -594,12 +594,83 @@ 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;
+	u8 own_addr_type;
+
+	memset(&cp, 0, sizeof(cp));
+
+	/* Update random address, but set require_privacy to false so
+	 * that we never connect with an unresolvable address.
+	 */
+	if (hci_update_random_address(req, false, &own_addr_type))
+		return;
+
+	conn->src_type = own_addr_type;
+
+	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))
@@ -675,9 +746,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


  parent reply	other threads:[~2014-02-24 22:30 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-02-24 22:30 [RFC v11 00/15] LE auto connection Andre Guedes
2014-02-24 22:30 ` [RFC v11 01/15] Bluetooth: Create hci_req_add_le_scan_disable helper Andre Guedes
2014-02-25  5:57   ` Johan Hedberg
2014-02-25 17:16     ` Andre Guedes
2014-02-24 22:30 ` [RFC v11 02/15] Bluetooth: Declare le_conn_failed in hci_core.h Andre Guedes
2014-02-24 22:30 ` Andre Guedes [this message]
2014-02-24 22:30 ` [RFC v11 04/15] Bluetooth: Remove unused function Andre Guedes
2014-02-24 22:30 ` [RFC v11 05/15] Bluetooth: Introduce hdev->pend_le_conn list Andre Guedes
2014-02-24 22:30 ` [RFC v11 06/15] Bluetooth: Introduce LE auto connection infrastructure Andre Guedes
2014-02-25  4:23   ` Johan Hedberg
2014-02-25 17:16     ` Andre Guedes
2014-02-25 17:43       ` Marcel Holtmann
2014-02-24 22:30 ` [RFC v11 07/15] Bluetooth: Introduce LE auto connect options Andre Guedes
2014-02-24 22:30 ` [RFC v11 08/15] Bluetooth: Connection parameters and auto connection Andre Guedes
2014-02-24 22:30 ` [RFC v11 09/15] Bluetooth: Temporarily stop background scanning on discovery Andre Guedes
2014-02-24 22:30 ` [RFC v11 10/15] Bluetooth: Auto connection and power on Andre Guedes
2014-02-24 22:30 ` [RFC v11 11/15] Bluetooth: Connection parameters and resolvable address Andre Guedes
2014-02-24 22:30 ` [RFC v11 12/15] Bluetooth: Support resolvable private addresses Andre Guedes
2014-02-24 22:30 ` [RFC v11 13/15] Bluetooth: Add le_auto_conn file on debugfs Andre Guedes
2014-02-24 22:31 ` [RFC v11 14/15] Bluetooth: Create hci_req_add_le_passive_scan helper Andre Guedes
2014-02-24 22:31 ` [RFC v11 15/15] Bluetooth: Update background scan parameters Andre Guedes

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1393281061-14320-4-git-send-email-andre.guedes@openbossa.org \
    --to=andre.guedes@openbossa.org \
    --cc=linux-bluetooth@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.