Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH 1/4] Bluetooth: Don't send device found events during passive scanning
@ 2014-03-25  8:30 johan.hedberg
  2014-03-25  8:30 ` [PATCH 2/4] Bluetooth: Add scan_rsp parameter to mgmt_device_found() johan.hedberg
                   ` (3 more replies)
  0 siblings, 4 replies; 8+ messages in thread
From: johan.hedberg @ 2014-03-25  8:30 UTC (permalink / raw)
  To: linux-bluetooth

From: Johan Hedberg <johan.hedberg@intel.com>

Passive LE scanning is only used by the kernel-internal connection
establishment procedure. It makes therefore little sense to send device
found events to user space.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
 net/bluetooth/hci_event.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 0c393fbae6e9..2388f2c09887 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -3964,8 +3964,12 @@ static void check_pending_le_conn(struct hci_dev *hdev, bdaddr_t *addr,
 static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
 			       u8 bdaddr_type, s8 rssi, u8 *data, u8 len)
 {
-	if (type == LE_ADV_IND || type == LE_ADV_DIRECT_IND)
-		check_pending_le_conn(hdev, bdaddr, bdaddr_type);
+	/* Passive scanning shouldn't trigger any device found events */
+	if (hdev->le_scan_type == LE_SCAN_PASSIVE) {
+		if (type == LE_ADV_IND || type == LE_ADV_DIRECT_IND)
+			check_pending_le_conn(hdev, bdaddr, bdaddr_type);
+		return;
+	}
 
 	mgmt_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL, rssi, 0, 1,
 			  data, len);
-- 
1.8.5.3


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

* [PATCH 2/4] Bluetooth: Add scan_rsp parameter to mgmt_device_found()
  2014-03-25  8:30 [PATCH 1/4] Bluetooth: Don't send device found events during passive scanning johan.hedberg
@ 2014-03-25  8:30 ` johan.hedberg
  2014-03-25  8:43   ` Marcel Holtmann
  2014-03-25  8:30 ` [PATCH 3/4] Bluetooth: Merge ADV_IND/ADV_SCAN_IND and SCAN_RSP together johan.hedberg
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 8+ messages in thread
From: johan.hedberg @ 2014-03-25  8:30 UTC (permalink / raw)
  To: linux-bluetooth

From: Johan Hedberg <johan.hedberg@intel.com>

In preparation for being able to merge ADV_IND/ADV_SCAN_IND and SCAN_RSP
together into a single device found event add a second parameter to the
mgmt_device_found function. For now all callers pass NULL as this
parameters since we don't yet have storing of the last received
advertising report.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
 include/net/bluetooth/hci_core.h |  5 +++--
 net/bluetooth/hci_event.c        | 10 +++++-----
 net/bluetooth/mgmt.c             | 16 +++++++++++-----
 3 files changed, 19 insertions(+), 12 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 5f8bc05694ac..a1b8eab8a47d 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -1264,8 +1264,9 @@ void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
 				       u8 *randomizer192, u8 *hash256,
 				       u8 *randomizer256, u8 status);
 void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
-		       u8 addr_type, u8 *dev_class, s8 rssi, u8 cfm_name,
-		       u8 ssp, u8 *eir, u16 eir_len);
+		       u8 addr_type, u8 *dev_class, s8 rssi, u8 cfm_name, u8
+		       ssp, u8 *eir, u16 eir_len, u8 *scan_rsp,
+		       u8 scan_rsp_len);
 void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
 		      u8 addr_type, s8 rssi, u8 *name, u8 name_len);
 void mgmt_discovering(struct hci_dev *hdev, u8 discovering);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 2388f2c09887..4a2c919d5908 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1827,7 +1827,7 @@ static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
 		name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp);
 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
 				  info->dev_class, 0, !name_known, ssp, NULL,
-				  0);
+				  0, NULL, 0);
 	}
 
 	hci_dev_unlock(hdev);
@@ -3102,7 +3102,7 @@ static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
 							      false, &ssp);
 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
 					  info->dev_class, info->rssi,
-					  !name_known, ssp, NULL, 0);
+					  !name_known, ssp, NULL, 0, NULL, 0);
 		}
 	} else {
 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
@@ -3120,7 +3120,7 @@ static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
 							      false, &ssp);
 			mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
 					  info->dev_class, info->rssi,
-					  !name_known, ssp, NULL, 0);
+					  !name_known, ssp, NULL, 0, NULL, 0);
 		}
 	}
 
@@ -3309,7 +3309,7 @@ static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
 		eir_len = eir_get_length(info->data, sizeof(info->data));
 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
 				  info->dev_class, info->rssi, !name_known,
-				  ssp, info->data, eir_len);
+				  ssp, info->data, eir_len, NULL, 0);
 	}
 
 	hci_dev_unlock(hdev);
@@ -3972,7 +3972,7 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
 	}
 
 	mgmt_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL, rssi, 0, 1,
-			  data, len);
+			  data, len, NULL, 0);
 }
 
 static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index d2d4e0d5aed0..a0ef5c076880 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -5669,7 +5669,8 @@ void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
 
 void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
 		       u8 addr_type, u8 *dev_class, s8 rssi, u8 cfm_name, u8
-		       ssp, u8 *eir, u16 eir_len)
+		       ssp, u8 *eir, u16 eir_len, u8 *scan_rsp,
+		       u8 scan_rsp_len)
 {
 	char buf[512];
 	struct mgmt_ev_device_found *ev = (void *) buf;
@@ -5679,8 +5680,10 @@ void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
 	if (!hci_discovery_active(hdev))
 		return;
 
-	/* Leave 5 bytes for a potential CoD field */
-	if (sizeof(*ev) + eir_len + 5 > sizeof(buf))
+	/* Make sure that the buffer is big enough. The 5 extra bytes
+	 * are for the potential CoD field.
+	 */
+	if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
 		return;
 
 	memset(buf, 0, sizeof(buf));
@@ -5707,8 +5710,11 @@ void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
 		eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
 					  dev_class, 3);
 
-	ev->eir_len = cpu_to_le16(eir_len);
-	ev_size = sizeof(*ev) + eir_len;
+	if (scan_rsp_len > 0)
+		memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
+
+	ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
+	ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
 
 	mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
 }
-- 
1.8.5.3


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

* [PATCH 3/4] Bluetooth: Merge ADV_IND/ADV_SCAN_IND and SCAN_RSP together
  2014-03-25  8:30 [PATCH 1/4] Bluetooth: Don't send device found events during passive scanning johan.hedberg
  2014-03-25  8:30 ` [PATCH 2/4] Bluetooth: Add scan_rsp parameter to mgmt_device_found() johan.hedberg
@ 2014-03-25  8:30 ` johan.hedberg
  2014-03-25  8:40   ` Marcel Holtmann
  2014-03-25  8:30 ` [PATCH 4/4] Bluetooth: Add directed advertising support through connect() johan.hedberg
  2014-03-25  8:43 ` [PATCH 1/4] Bluetooth: Don't send device found events during passive scanning Marcel Holtmann
  3 siblings, 1 reply; 8+ messages in thread
From: johan.hedberg @ 2014-03-25  8:30 UTC (permalink / raw)
  To: linux-bluetooth

From: Johan Hedberg <johan.hedberg@intel.com>

To avoid too many events being sent to user space and to help parsing of
all available remote device data it makes sense for us to wait for the
scan response and send a single merged Device Found event to user space.

This patch adds a few new variables to hci_dev to track the last
received ADV_IND/ADV_SCAN_IND, i.e. those which will cause a SCAN_REQ to
be send in the case of active scanning. When the SCAN_RSP is received
the pending data is passed together with the SCAN_RSP to the
mgmt_device_found function which takes care of merging them into a
single Device Found event.

We also need a bit of extra logic to handle situations where we don't
receive a SCAN_RSP after caching some data. In such a scenario we simply
have to send out the pending data as it is and then operate on the new
report as if there was no pending data.

We also need to send out any pending data when scanning stops as
well as ensure that the storage is empty at the start of a new active
scanning session. These both cases are covered by the update to the
hci_cc_le_set_scan_enable function in this patch.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
 include/net/bluetooth/hci_core.h |  4 ++
 net/bluetooth/hci_event.c        | 99 +++++++++++++++++++++++++++++++++++++++-
 2 files changed, 101 insertions(+), 2 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index a1b8eab8a47d..59b112397d39 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -68,6 +68,10 @@ struct discovery_state {
 	struct list_head	unknown;	/* Name state not known */
 	struct list_head	resolve;	/* Name needs to be resolved */
 	__u32			timestamp;
+	bdaddr_t		last_adv_addr;
+	u8			last_adv_addr_type;
+	u8			last_adv_data[HCI_MAX_AD_LENGTH];
+	u8			last_adv_data_len;
 };
 
 struct hci_conn_hash {
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 4a2c919d5908..b9f0b20c9a51 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1018,6 +1018,32 @@ static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
 	hci_dev_unlock(hdev);
 }
 
+static bool has_pending_adv_report(struct hci_dev *hdev)
+{
+	struct discovery_state *d = &hdev->discovery;
+
+	return bacmp(&d->last_adv_addr, BDADDR_ANY);
+}
+
+static void clear_pending_adv_report(struct hci_dev *hdev)
+{
+	struct discovery_state *d = &hdev->discovery;
+
+	bacpy(&d->last_adv_addr, BDADDR_ANY);
+	d->last_adv_data_len = 0;
+}
+
+static void store_pending_adv_report(struct hci_dev *hdev, bdaddr_t *bdaddr,
+				     u8 bdaddr_type, u8 *data, u8 len)
+{
+	struct discovery_state *d = &hdev->discovery;
+
+	bacpy(&d->last_adv_addr, bdaddr);
+	d->last_adv_addr_type = bdaddr_type;
+	memcpy(d->last_adv_data, data, len);
+	d->last_adv_data_len = len;
+}
+
 static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
 				      struct sk_buff *skb)
 {
@@ -1036,9 +1062,25 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
 	switch (cp->enable) {
 	case LE_SCAN_ENABLE:
 		set_bit(HCI_LE_SCAN, &hdev->dev_flags);
+		if (hdev->le_scan_type == LE_SCAN_ACTIVE)
+			clear_pending_adv_report(hdev);
 		break;
 
 	case LE_SCAN_DISABLE:
+		/* We do this here instead of when setting DISCOVERY_STOPPED
+		 * since the latter would potentially require waiting for
+		 * inquiry to stop too.
+		 */
+		if (has_pending_adv_report(hdev)) {
+			struct discovery_state *d = &hdev->discovery;
+
+			mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK,
+						  d->last_adv_addr_type, NULL,
+						  0, 0, 1, d->last_adv_data,
+						  d->last_adv_data_len,
+						  NULL, 0);
+		}
+
 		/* Cancel this timer so that we don't try to disable scanning
 		 * when it's already disabled.
 		 */
@@ -3964,6 +4006,8 @@ static void check_pending_le_conn(struct hci_dev *hdev, bdaddr_t *addr,
 static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
 			       u8 bdaddr_type, s8 rssi, u8 *data, u8 len)
 {
+	struct discovery_state *d = &hdev->discovery;
+
 	/* Passive scanning shouldn't trigger any device found events */
 	if (hdev->le_scan_type == LE_SCAN_PASSIVE) {
 		if (type == LE_ADV_IND || type == LE_ADV_DIRECT_IND)
@@ -3971,8 +4015,59 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
 		return;
 	}
 
-	mgmt_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL, rssi, 0, 1,
-			  data, len, NULL, 0);
+	/* If there's nothing pending either store the data from this
+	 * event or send an immediate device found event if the data
+	 * should not be stored for later.
+	 */
+	if (!has_pending_adv_report(hdev)) {
+		if (type == LE_ADV_IND || type == LE_ADV_SCAN_IND) {
+			store_pending_adv_report(hdev, bdaddr, bdaddr_type,
+						 data, len);
+			return;
+		}
+
+		mgmt_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL,
+				  rssi, 0, 1, data, len, NULL, 0);
+		return;
+	}
+
+	/* If the pending data doesn't match this report or this isn't a
+	 * scan response (e.g. we got a duplicate ADV_IND) then force
+	 * sending of the pending data.
+	 */
+	if (type != LE_ADV_SCAN_RSP || bacmp(bdaddr, &d->last_adv_addr) ||
+	    bdaddr_type != d->last_adv_addr_type) {
+		/* Send out whatever is in the cache */
+		mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK,
+				  d->last_adv_addr_type, NULL, 0, 0, 1,
+				  d->last_adv_data, d->last_adv_data_len,
+				  NULL, 0);
+
+		/* If the new event should be cached store it there */
+		if (type == LE_ADV_IND || type == LE_ADV_SCAN_IND) {
+			store_pending_adv_report(hdev, bdaddr, bdaddr_type,
+						 data, len);
+			return;
+		}
+
+		/* The event can't be cached so clear the cache and send
+		 * an immediate event based on this report.
+		 */
+		clear_pending_adv_report(hdev);
+		mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK,
+				  d->last_adv_addr_type, NULL, rssi, 0, 1,
+				  data, len, NULL, 0);
+		return;
+	}
+
+	/* If we get here we've got a pending ADV_IND or ADV_SCAN_IND and
+	 * the new event is a SCAN_RSP. We can therefore proceed with
+	 * sending a merged device found event.
+	 */
+	mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK,
+			  d->last_adv_addr_type, NULL, rssi, 0, 1, data, len,
+			  d->last_adv_data, d->last_adv_data_len);
+	clear_pending_adv_report(hdev);
 }
 
 static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
-- 
1.8.5.3


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

* [PATCH 4/4] Bluetooth: Add directed advertising support through connect()
  2014-03-25  8:30 [PATCH 1/4] Bluetooth: Don't send device found events during passive scanning johan.hedberg
  2014-03-25  8:30 ` [PATCH 2/4] Bluetooth: Add scan_rsp parameter to mgmt_device_found() johan.hedberg
  2014-03-25  8:30 ` [PATCH 3/4] Bluetooth: Merge ADV_IND/ADV_SCAN_IND and SCAN_RSP together johan.hedberg
@ 2014-03-25  8:30 ` johan.hedberg
  2014-03-25  8:46   ` Marcel Holtmann
  2014-03-25  8:43 ` [PATCH 1/4] Bluetooth: Don't send device found events during passive scanning Marcel Holtmann
  3 siblings, 1 reply; 8+ messages in thread
From: johan.hedberg @ 2014-03-25  8:30 UTC (permalink / raw)
  To: linux-bluetooth

From: Johan Hedberg <johan.hedberg@intel.com>

When we're in peripheral mode (HCI_ADVERTISING flag is set) the most
natural mapping of connect() is to perform directed advertising to the
peer device.

This patch does the necessary changes to enable directed advertising and
keeps the hci_conn state as BT_CONNECT in a similar way as is done for
central or BR/EDR connection initiation.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
 include/net/bluetooth/hci.h |  1 +
 net/bluetooth/hci_conn.c    | 77 ++++++++++++++++++++++++++++++++++++++++-----
 net/bluetooth/hci_event.c   | 19 +++++++++--
 3 files changed, 87 insertions(+), 10 deletions(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index be150cf8cd43..4261a67682c0 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -367,6 +367,7 @@ enum {
 #define HCI_ERROR_REMOTE_POWER_OFF	0x15
 #define HCI_ERROR_LOCAL_HOST_TERM	0x16
 #define HCI_ERROR_PAIRING_NOT_ALLOWED	0x18
+#define HCI_ERROR_ADVERTISING_TIMEOUT	0x3c
 
 /* Flow control modes */
 #define HCI_FLOW_CTL_MODE_PACKET_BASED	0x00
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 129c22a85ccf..55a174317925 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -367,9 +367,23 @@ static void le_conn_timeout(struct work_struct *work)
 {
 	struct hci_conn *conn = container_of(work, struct hci_conn,
 					     le_conn_timeout.work);
+	struct hci_dev *hdev = conn->hdev;
 
 	BT_DBG("");
 
+	/* We could end up here due to having done directed advertising,
+	 * so clean up the state if necessary. This should however only
+	 * happen with broken hardware or if low duty cycle was used
+	 * (which doesn't have a timeout of its own).
+	 */
+	if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
+		u8 enable = 0x00;
+		hci_send_cmd(hdev, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable),
+			     &enable);
+		hci_le_conn_failed(conn, HCI_ERROR_ADVERTISING_TIMEOUT);
+		return;
+	}
+
 	hci_le_create_connection_cancel(conn);
 }
 
@@ -549,6 +563,11 @@ void hci_le_conn_failed(struct hci_conn *conn, u8 status)
 	 * favor of connection establishment, we should restart it.
 	 */
 	hci_update_background_scan(hdev);
+
+	/* Re-enable advertising in case this was a failed connection
+	 * attempt as a peripheral.
+	 */
+	mgmt_reenable_advertising(hdev);
 }
 
 static void create_le_conn_complete(struct hci_dev *hdev, u8 status)
@@ -609,6 +628,45 @@ static void hci_req_add_le_create_conn(struct hci_request *req,
 	conn->state = BT_CONNECT;
 }
 
+static void hci_req_directed_advertising(struct hci_request *req,
+					 struct hci_conn *conn)
+{
+	struct hci_dev *hdev = req->hdev;
+	struct hci_cp_le_set_adv_param cp;
+	u8 own_addr_type;
+	u8 enable;
+
+	enable = 0x00;
+	hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
+
+	/* Clear the HCI_ADVERTISING bit temporarily so that the
+	 * hci_update_random_address knows that it's safe to go ahead
+	 * and write a new random address. The flag will be set back on
+	 * as soon as the SET_ADV_ENABLE HCI command completes.
+	 */
+	clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
+
+	/* Set require_privacy to false so that the remote device has a
+	 * chance of identifying us.
+	 */
+	if (hci_update_random_address(req, false, &own_addr_type) < 0)
+		return;
+
+	memset(&cp, 0, sizeof(cp));
+	cp.type = LE_ADV_DIRECT_IND;
+	cp.own_address_type = own_addr_type;
+	cp.direct_addr_type = conn->dst_type;
+	bacpy(&cp.direct_addr, &conn->dst);
+	cp.channel_map = hdev->le_adv_channel_map;
+
+	hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
+
+	enable = 0x01;
+	hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
+
+	conn->state = BT_CONNECT;
+}
+
 struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
 				u8 dst_type, u8 sec_level, u8 auth_type)
 {
@@ -618,9 +676,6 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
 	struct hci_request req;
 	int err;
 
-	if (test_bit(HCI_ADVERTISING, &hdev->flags))
-		return ERR_PTR(-ENOTSUPP);
-
 	/* Some devices send ATT messages as soon as the physical link is
 	 * established. To be able to handle these ATT messages, the user-
 	 * space first establishes the connection and then starts the pairing
@@ -668,13 +723,20 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
 		return ERR_PTR(-ENOMEM);
 
 	conn->dst_type = dst_type;
-
-	conn->out = true;
-	conn->link_mode |= HCI_LM_MASTER;
 	conn->sec_level = BT_SECURITY_LOW;
 	conn->pending_sec_level = sec_level;
 	conn->auth_type = auth_type;
 
+	hci_req_init(&req, hdev);
+
+	if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
+		hci_req_directed_advertising(&req, conn);
+		goto create_conn;
+	}
+
+	conn->out = true;
+	conn->link_mode |= HCI_LM_MASTER;
+
 	params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type);
 	if (params) {
 		conn->le_conn_min_interval = params->conn_min_interval;
@@ -684,8 +746,6 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
 		conn->le_conn_max_interval = hdev->le_conn_max_interval;
 	}
 
-	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. Also set the
 	 * HCI_LE_SCAN_INTERRUPTED flag so that the command complete
@@ -699,6 +759,7 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
 
 	hci_req_add_le_create_conn(&req, conn);
 
+create_conn:
 	err = hci_req_run(&req, create_le_conn_complete);
 	if (err) {
 		hci_conn_del(conn);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index b9f0b20c9a51..0181f368de42 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -991,10 +991,25 @@ static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
 	if (!sent)
 		return;
 
+	if (status)
+		return;
+
 	hci_dev_lock(hdev);
 
-	if (!status)
-		mgmt_advertising(hdev, *sent);
+	/* If we're doing connection initation as peripheral. Set a
+	 * timeout in case something goes wrong.
+	 */
+	if (*sent) {
+		struct hci_conn *conn;
+
+		conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
+		if (conn)
+			queue_delayed_work(hdev->workqueue,
+					   &conn->le_conn_timeout,
+					   HCI_LE_CONN_TIMEOUT);
+	}
+
+	mgmt_advertising(hdev, *sent);
 
 	hci_dev_unlock(hdev);
 }
-- 
1.8.5.3


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

* Re: [PATCH 3/4] Bluetooth: Merge ADV_IND/ADV_SCAN_IND and SCAN_RSP together
  2014-03-25  8:30 ` [PATCH 3/4] Bluetooth: Merge ADV_IND/ADV_SCAN_IND and SCAN_RSP together johan.hedberg
@ 2014-03-25  8:40   ` Marcel Holtmann
  0 siblings, 0 replies; 8+ messages in thread
From: Marcel Holtmann @ 2014-03-25  8:40 UTC (permalink / raw)
  To: Johan Hedberg; +Cc: linux-bluetooth

Hi Johan,

> To avoid too many events being sent to user space and to help parsing of
> all available remote device data it makes sense for us to wait for the
> scan response and send a single merged Device Found event to user space.
> 
> This patch adds a few new variables to hci_dev to track the last
> received ADV_IND/ADV_SCAN_IND, i.e. those which will cause a SCAN_REQ to
> be send in the case of active scanning. When the SCAN_RSP is received
> the pending data is passed together with the SCAN_RSP to the
> mgmt_device_found function which takes care of merging them into a
> single Device Found event.
> 
> We also need a bit of extra logic to handle situations where we don't
> receive a SCAN_RSP after caching some data. In such a scenario we simply
> have to send out the pending data as it is and then operate on the new
> report as if there was no pending data.
> 
> We also need to send out any pending data when scanning stops as
> well as ensure that the storage is empty at the start of a new active
> scanning session. These both cases are covered by the update to the
> hci_cc_le_set_scan_enable function in this patch.
> 
> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
> ---
> include/net/bluetooth/hci_core.h |  4 ++
> net/bluetooth/hci_event.c        | 99 +++++++++++++++++++++++++++++++++++++++-
> 2 files changed, 101 insertions(+), 2 deletions(-)
> 
> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> index a1b8eab8a47d..59b112397d39 100644
> --- a/include/net/bluetooth/hci_core.h
> +++ b/include/net/bluetooth/hci_core.h
> @@ -68,6 +68,10 @@ struct discovery_state {
> 	struct list_head	unknown;	/* Name state not known */
> 	struct list_head	resolve;	/* Name needs to be resolved */
> 	__u32			timestamp;
> +	bdaddr_t		last_adv_addr;
> +	u8			last_adv_addr_type;
> +	u8			last_adv_data[HCI_MAX_AD_LENGTH];
> +	u8			last_adv_data_len;
> };
> 
> struct hci_conn_hash {
> diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
> index 4a2c919d5908..b9f0b20c9a51 100644
> --- a/net/bluetooth/hci_event.c
> +++ b/net/bluetooth/hci_event.c
> @@ -1018,6 +1018,32 @@ static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
> 	hci_dev_unlock(hdev);
> }
> 
> +static bool has_pending_adv_report(struct hci_dev *hdev)
> +{
> +	struct discovery_state *d = &hdev->discovery;
> +
> +	return bacmp(&d->last_adv_addr, BDADDR_ANY);
> +}
> +
> +static void clear_pending_adv_report(struct hci_dev *hdev)
> +{
> +	struct discovery_state *d = &hdev->discovery;
> +
> +	bacpy(&d->last_adv_addr, BDADDR_ANY);
> +	d->last_adv_data_len = 0;
> +}
> +
> +static void store_pending_adv_report(struct hci_dev *hdev, bdaddr_t *bdaddr,
> +				     u8 bdaddr_type, u8 *data, u8 len)
> +{
> +	struct discovery_state *d = &hdev->discovery;
> +
> +	bacpy(&d->last_adv_addr, bdaddr);
> +	d->last_adv_addr_type = bdaddr_type;
> +	memcpy(d->last_adv_data, data, len);
> +	d->last_adv_data_len = len;
> +}
> +
> static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
> 				      struct sk_buff *skb)
> {
> @@ -1036,9 +1062,25 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
> 	switch (cp->enable) {
> 	case LE_SCAN_ENABLE:
> 		set_bit(HCI_LE_SCAN, &hdev->dev_flags);
> +		if (hdev->le_scan_type == LE_SCAN_ACTIVE)
> +			clear_pending_adv_report(hdev);
> 		break;
> 
> 	case LE_SCAN_DISABLE:
> +		/* We do this here instead of when setting DISCOVERY_STOPPED
> +		 * since the latter would potentially require waiting for
> +		 * inquiry to stop too.
> +		 */
> +		if (has_pending_adv_report(hdev)) {
> +			struct discovery_state *d = &hdev->discovery;
> +
> +			mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK,
> +						  d->last_adv_addr_type, NULL,
> +						  0, 0, 1, d->last_adv_data,
> +						  d->last_adv_data_len,
> +						  NULL, 0);

indentation is wrong here.

> +		}
> +
> 		/* Cancel this timer so that we don't try to disable scanning
> 		 * when it's already disabled.
> 		 */
> @@ -3964,6 +4006,8 @@ static void check_pending_le_conn(struct hci_dev *hdev, bdaddr_t *addr,
> static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
> 			       u8 bdaddr_type, s8 rssi, u8 *data, u8 len)
> {
> +	struct discovery_state *d = &hdev->discovery;
> +
> 	/* Passive scanning shouldn't trigger any device found events */
> 	if (hdev->le_scan_type == LE_SCAN_PASSIVE) {
> 		if (type == LE_ADV_IND || type == LE_ADV_DIRECT_IND)
> @@ -3971,8 +4015,59 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
> 		return;
> 	}
> 
> -	mgmt_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL, rssi, 0, 1,
> -			  data, len, NULL, 0);
> +	/* If there's nothing pending either store the data from this
> +	 * event or send an immediate device found event if the data
> +	 * should not be stored for later.
> +	 */
> +	if (!has_pending_adv_report(hdev)) {
> +		if (type == LE_ADV_IND || type == LE_ADV_SCAN_IND) {
> +			store_pending_adv_report(hdev, bdaddr, bdaddr_type,
> +						 data, len);
> +			return;
> +		}
> +
> +		mgmt_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL,
> +				  rssi, 0, 1, data, len, NULL, 0);
> +		return;
> +	}
> +
> +	/* If the pending data doesn't match this report or this isn't a
> +	 * scan response (e.g. we got a duplicate ADV_IND) then force
> +	 * sending of the pending data.
> +	 */
> +	if (type != LE_ADV_SCAN_RSP || bacmp(bdaddr, &d->last_adv_addr) ||
> +	    bdaddr_type != d->last_adv_addr_type) {
> +		/* Send out whatever is in the cache */
> +		mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK,
> +				  d->last_adv_addr_type, NULL, 0, 0, 1,
> +				  d->last_adv_data, d->last_adv_data_len,
> +				  NULL, 0);
> +
> +		/* If the new event should be cached store it there */

I can not parse this comment. What to cached store where ;)

> +		if (type == LE_ADV_IND || type == LE_ADV_SCAN_IND) {
> +			store_pending_adv_report(hdev, bdaddr, bdaddr_type,
> +						 data, len);
> +			return;
> +		}
> +
> +		/* The event can't be cached so clear the cache and send
> +		 * an immediate event based on this report.
> +		 */

The advertising reports can not be merged, so clear the pending report and send out the event. Or something like that.

> +		clear_pending_adv_report(hdev);
> +		mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK,
> +				  d->last_adv_addr_type, NULL, rssi, 0, 1,
> +				  data, len, NULL, 0);
> +		return;
> +	}
> +
> +	/* If we get here we've got a pending ADV_IND or ADV_SCAN_IND and
> +	 * the new event is a SCAN_RSP. We can therefore proceed with
> +	 * sending a merged device found event.
> +	 */
> +	mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK,
> +			  d->last_adv_addr_type, NULL, rssi, 0, 1, data, len,
> +			  d->last_adv_data, d->last_adv_data_len);
> +	clear_pending_adv_report(hdev);
> }

Regards

Marcel


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

* Re: [PATCH 2/4] Bluetooth: Add scan_rsp parameter to mgmt_device_found()
  2014-03-25  8:30 ` [PATCH 2/4] Bluetooth: Add scan_rsp parameter to mgmt_device_found() johan.hedberg
@ 2014-03-25  8:43   ` Marcel Holtmann
  0 siblings, 0 replies; 8+ messages in thread
From: Marcel Holtmann @ 2014-03-25  8:43 UTC (permalink / raw)
  To: Johan Hedberg; +Cc: linux-bluetooth

Hi Johan,

> In preparation for being able to merge ADV_IND/ADV_SCAN_IND and SCAN_RSP
> together into a single device found event add a second parameter to the
> mgmt_device_found function. For now all callers pass NULL as this
> parameters since we don't yet have storing of the last received
> advertising report.
> 
> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
> ---
> include/net/bluetooth/hci_core.h |  5 +++--
> net/bluetooth/hci_event.c        | 10 +++++-----
> net/bluetooth/mgmt.c             | 16 +++++++++++-----
> 3 files changed, 19 insertions(+), 12 deletions(-)

patch has been applied to bluetooth-next tree.

Regards

Marcel


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

* Re: [PATCH 1/4] Bluetooth: Don't send device found events during passive scanning
  2014-03-25  8:30 [PATCH 1/4] Bluetooth: Don't send device found events during passive scanning johan.hedberg
                   ` (2 preceding siblings ...)
  2014-03-25  8:30 ` [PATCH 4/4] Bluetooth: Add directed advertising support through connect() johan.hedberg
@ 2014-03-25  8:43 ` Marcel Holtmann
  3 siblings, 0 replies; 8+ messages in thread
From: Marcel Holtmann @ 2014-03-25  8:43 UTC (permalink / raw)
  To: Johan Hedberg; +Cc: linux-bluetooth

Hi Johan,

> Passive LE scanning is only used by the kernel-internal connection
> establishment procedure. It makes therefore little sense to send device
> found events to user space.
> 
> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
> ---
> net/bluetooth/hci_event.c | 8 ++++++--
> 1 file changed, 6 insertions(+), 2 deletions(-)

patch has been applied to bluetooth-next tree.

Regards

Marcel


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

* Re: [PATCH 4/4] Bluetooth: Add directed advertising support through connect()
  2014-03-25  8:30 ` [PATCH 4/4] Bluetooth: Add directed advertising support through connect() johan.hedberg
@ 2014-03-25  8:46   ` Marcel Holtmann
  0 siblings, 0 replies; 8+ messages in thread
From: Marcel Holtmann @ 2014-03-25  8:46 UTC (permalink / raw)
  To: Johan Hedberg; +Cc: linux-bluetooth

Hi Johan,

> When we're in peripheral mode (HCI_ADVERTISING flag is set) the most
> natural mapping of connect() is to perform directed advertising to the
> peer device.
> 
> This patch does the necessary changes to enable directed advertising and
> keeps the hci_conn state as BT_CONNECT in a similar way as is done for
> central or BR/EDR connection initiation.
> 
> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
> ---
> include/net/bluetooth/hci.h |  1 +
> net/bluetooth/hci_conn.c    | 77 ++++++++++++++++++++++++++++++++++++++++-----
> net/bluetooth/hci_event.c   | 19 +++++++++--
> 3 files changed, 87 insertions(+), 10 deletions(-)

patch has been applied to bluetooth-next tree.

Regards

Marcel


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

end of thread, other threads:[~2014-03-25  8:46 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-03-25  8:30 [PATCH 1/4] Bluetooth: Don't send device found events during passive scanning johan.hedberg
2014-03-25  8:30 ` [PATCH 2/4] Bluetooth: Add scan_rsp parameter to mgmt_device_found() johan.hedberg
2014-03-25  8:43   ` Marcel Holtmann
2014-03-25  8:30 ` [PATCH 3/4] Bluetooth: Merge ADV_IND/ADV_SCAN_IND and SCAN_RSP together johan.hedberg
2014-03-25  8:40   ` Marcel Holtmann
2014-03-25  8:30 ` [PATCH 4/4] Bluetooth: Add directed advertising support through connect() johan.hedberg
2014-03-25  8:46   ` Marcel Holtmann
2014-03-25  8:43 ` [PATCH 1/4] Bluetooth: Don't send device found events during passive scanning Marcel Holtmann

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox