linux-bluetooth.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/2] Bluetooth: Add support for Start Limited Discovery
@ 2016-01-05 11:19 Johan Hedberg
  2016-01-05 11:19 ` [PATCH v2 1/2] Bluetooth: Change eir_has_data_type() to more generic eir_get_data() Johan Hedberg
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Johan Hedberg @ 2016-01-05 11:19 UTC (permalink / raw)
  To: linux-bluetooth

v2: Use u16 instead of uint16_t for start_discovery_internal()

Hi,

These two patches implement support for the Start Limited Discovery mgmt
command (that's been specified a long time ago but no-one picked up the
task to implement it so far).

Johan

---
Johan Hedberg (2):
      Bluetooth: Change eir_has_data_type() to more generic eir_get_data()
      Bluetooth: Add support for Start Limited Discovery command

 include/net/bluetooth/hci_core.h | 31 +++++++++++++++-------
 include/net/bluetooth/mgmt.h     |  2 ++
 net/bluetooth/hci_event.c        |  6 ++---
 net/bluetooth/hci_request.c	  | 11 +++++---
 net/bluetooth/mgmt.c             | 56 ++++++++++++++++++++++++++++++++-------
 5 files changed, 80 insertions(+), 26 deletions(-)


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

* [PATCH v2 1/2] Bluetooth: Change eir_has_data_type() to more generic eir_get_data()
  2016-01-05 11:19 [PATCH v2 0/2] Bluetooth: Add support for Start Limited Discovery Johan Hedberg
@ 2016-01-05 11:19 ` Johan Hedberg
  2016-01-05 11:19 ` [PATCH v2 2/2] Bluetooth: Add support for Start Limited Discovery command Johan Hedberg
  2016-01-05 16:05 ` [PATCH v2 0/2] Bluetooth: Add support for Start Limited Discovery Marcel Holtmann
  2 siblings, 0 replies; 4+ messages in thread
From: Johan Hedberg @ 2016-01-05 11:19 UTC (permalink / raw)
  To: linux-bluetooth

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

To make the EIR parsing helper more general purpose, make it return
the found data and its length rather than just saying whether the data
was present or not.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
 include/net/bluetooth/hci_core.h | 30 ++++++++++++++++++++----------
 net/bluetooth/hci_event.c        |  6 +++---
 net/bluetooth/mgmt.c             |  3 ++-
 3 files changed, 25 insertions(+), 14 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index c95e0326c41a..372e2a7c4ada 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -1283,31 +1283,41 @@ static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status,
 	mutex_unlock(&hci_cb_list_lock);
 }
 
-static inline bool eir_has_data_type(u8 *data, size_t data_len, u8 type)
+static inline void *eir_get_data(u8 *eir, size_t eir_len, u8 type,
+				 size_t *data_len)
 {
 	size_t parsed = 0;
 
-	if (data_len < 2)
-		return false;
+	if (eir_len < 2)
+		return NULL;
 
-	while (parsed < data_len - 1) {
-		u8 field_len = data[0];
+	while (parsed < eir_len - 1) {
+		u8 field_len = eir[0];
 
 		if (field_len == 0)
 			break;
 
 		parsed += field_len + 1;
 
-		if (parsed > data_len)
+		if (parsed > eir_len)
 			break;
 
-		if (data[1] == type)
-			return true;
+		if (eir[1] != type) {
+			eir += field_len + 1;
+			continue;
+		}
+
+		/* Zero length data */
+		if (field_len == 1)
+			return NULL;
 
-		data += field_len + 1;
+		if (data_len)
+			*data_len = field_len - 1;
+
+		return &eir[2];
 	}
 
-	return false;
+	return NULL;
 }
 
 static inline bool hci_bdaddr_is_rpa(bdaddr_t *bdaddr, u8 addr_type)
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 7554da5b7a8f..c162af5d16bf 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -3833,9 +3833,9 @@ static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
 		data.ssp_mode		= 0x01;
 
 		if (hci_dev_test_flag(hdev, HCI_MGMT))
-			name_known = eir_has_data_type(info->data,
-						       sizeof(info->data),
-						       EIR_NAME_COMPLETE);
+			name_known = eir_get_data(info->data,
+						  sizeof(info->data),
+						  EIR_NAME_COMPLETE, NULL);
 		else
 			name_known = true;
 
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 621f6fdd0dd1..3297a4ecc05e 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -7266,7 +7266,8 @@ void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
 		/* Copy EIR or advertising data into event */
 		memcpy(ev->eir, eir, eir_len);
 
-	if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
+	if (dev_class && !eir_get_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
+				       NULL))
 		eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
 					  dev_class, 3);
 
-- 
2.5.0


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

* [PATCH v2 2/2] Bluetooth: Add support for Start Limited Discovery command
  2016-01-05 11:19 [PATCH v2 0/2] Bluetooth: Add support for Start Limited Discovery Johan Hedberg
  2016-01-05 11:19 ` [PATCH v2 1/2] Bluetooth: Change eir_has_data_type() to more generic eir_get_data() Johan Hedberg
@ 2016-01-05 11:19 ` Johan Hedberg
  2016-01-05 16:05 ` [PATCH v2 0/2] Bluetooth: Add support for Start Limited Discovery Marcel Holtmann
  2 siblings, 0 replies; 4+ messages in thread
From: Johan Hedberg @ 2016-01-05 11:19 UTC (permalink / raw)
  To: linux-bluetooth

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

This patch implements the mgmt Start Limited Discovery command. Most
of existing Start Discovery code is reused since the only difference
is the presence of a 'limited' flag as part of the discovery state.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
 include/net/bluetooth/hci_core.h |  1 +
 include/net/bluetooth/mgmt.h     |  2 ++
 net/bluetooth/hci_request.c      | 11 ++++++---
 net/bluetooth/mgmt.c             | 53 +++++++++++++++++++++++++++++++++-------
 4 files changed, 55 insertions(+), 12 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 372e2a7c4ada..d4f82edb5cff 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -77,6 +77,7 @@ struct discovery_state {
 	u8			last_adv_data_len;
 	bool			report_invalid_rssi;
 	bool			result_filtering;
+	bool			limited;
 	s8			rssi;
 	u16			uuid_count;
 	u8			(*uuids)[16];
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index af17774c9416..ea73e0826aa7 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -584,6 +584,8 @@ struct mgmt_rp_get_adv_size_info {
 	__u8	max_scan_rsp_len;
 } __packed;
 
+#define MGMT_OP_START_LIMITED_DISCOVERY	0x0041
+
 #define MGMT_EV_CMD_COMPLETE		0x0001
 struct mgmt_ev_cmd_complete {
 	__le16	opcode;
diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c
index 9997c31ef987..794299c4673a 100644
--- a/net/bluetooth/hci_request.c
+++ b/net/bluetooth/hci_request.c
@@ -1737,8 +1737,8 @@ static int le_scan_disable(struct hci_request *req, unsigned long opt)
 static int bredr_inquiry(struct hci_request *req, unsigned long opt)
 {
 	u8 length = opt;
-	/* General inquiry access code (GIAC) */
-	u8 lap[3] = { 0x33, 0x8b, 0x9e };
+	u8 giac[3] = { 0x33, 0x8b, 0x9e };
+	u8 liac[3] = { 0x00, 0x8b, 0x9e };
 	struct hci_cp_inquiry cp;
 
 	BT_DBG("%s", req->hdev->name);
@@ -1748,7 +1748,12 @@ static int bredr_inquiry(struct hci_request *req, unsigned long opt)
 	hci_dev_unlock(req->hdev);
 
 	memset(&cp, 0, sizeof(cp));
-	memcpy(&cp.lap, lap, sizeof(cp.lap));
+
+	if (req->hdev->discovery.limited)
+		memcpy(&cp.lap, liac, sizeof(cp.lap));
+	else
+		memcpy(&cp.lap, giac, sizeof(cp.lap));
+
 	cp.length = length;
 
 	hci_req_add(req, HCI_OP_INQUIRY, sizeof(cp), &cp);
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 3297a4ecc05e..5a5089cb6570 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -103,6 +103,7 @@ static const u16 mgmt_commands[] = {
 	MGMT_OP_ADD_ADVERTISING,
 	MGMT_OP_REMOVE_ADVERTISING,
 	MGMT_OP_GET_ADV_SIZE_INFO,
+	MGMT_OP_START_LIMITED_DISCOVERY,
 };
 
 static const u16 mgmt_events[] = {
@@ -3283,6 +3284,9 @@ void mgmt_start_discovery_complete(struct hci_dev *hdev, u8 status)
 	if (!cmd)
 		cmd = pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev);
 
+	if (!cmd)
+		cmd = pending_find(MGMT_OP_START_LIMITED_DISCOVERY, hdev);
+
 	if (cmd) {
 		cmd->cmd_complete(cmd, mgmt_status(status));
 		mgmt_pending_remove(cmd);
@@ -3318,8 +3322,8 @@ static bool discovery_type_is_valid(struct hci_dev *hdev, uint8_t type,
 	return true;
 }
 
-static int start_discovery(struct sock *sk, struct hci_dev *hdev,
-			   void *data, u16 len)
+static int start_discovery_internal(struct sock *sk, struct hci_dev *hdev,
+				    u16 op, void *data, u16 len)
 {
 	struct mgmt_cp_start_discovery *cp = data;
 	struct mgmt_pending_cmd *cmd;
@@ -3331,7 +3335,7 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
 	hci_dev_lock(hdev);
 
 	if (!hdev_is_powered(hdev)) {
-		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
+		err = mgmt_cmd_complete(sk, hdev->id, op,
 					MGMT_STATUS_NOT_POWERED,
 					&cp->type, sizeof(cp->type));
 		goto failed;
@@ -3339,15 +3343,14 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
 
 	if (hdev->discovery.state != DISCOVERY_STOPPED ||
 	    hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
-		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
-					MGMT_STATUS_BUSY, &cp->type,
-					sizeof(cp->type));
+		err = mgmt_cmd_complete(sk, hdev->id, op, MGMT_STATUS_BUSY,
+					&cp->type, sizeof(cp->type));
 		goto failed;
 	}
 
 	if (!discovery_type_is_valid(hdev, cp->type, &status)) {
-		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
-					status, &cp->type, sizeof(cp->type));
+		err = mgmt_cmd_complete(sk, hdev->id, op, status,
+					&cp->type, sizeof(cp->type));
 		goto failed;
 	}
 
@@ -3358,8 +3361,12 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
 
 	hdev->discovery.type = cp->type;
 	hdev->discovery.report_invalid_rssi = false;
+	if (op == MGMT_OP_START_LIMITED_DISCOVERY)
+		hdev->discovery.limited = true;
+	else
+		hdev->discovery.limited = false;
 
-	cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, data, len);
+	cmd = mgmt_pending_add(sk, op, hdev, data, len);
 	if (!cmd) {
 		err = -ENOMEM;
 		goto failed;
@@ -3376,6 +3383,21 @@ failed:
 	return err;
 }
 
+static int start_discovery(struct sock *sk, struct hci_dev *hdev,
+			   void *data, u16 len)
+{
+	return start_discovery_internal(sk, hdev, MGMT_OP_START_DISCOVERY,
+					data, len);
+}
+
+static int start_limited_discovery(struct sock *sk, struct hci_dev *hdev,
+				   void *data, u16 len)
+{
+	return start_discovery_internal(sk, hdev,
+					MGMT_OP_START_LIMITED_DISCOVERY,
+					data, len);
+}
+
 static int service_discovery_cmd_complete(struct mgmt_pending_cmd *cmd,
 					  u8 status)
 {
@@ -6313,6 +6335,7 @@ static const struct hci_mgmt_handler mgmt_handlers[] = {
 						HCI_MGMT_VAR_LEN },
 	{ remove_advertising,	   MGMT_REMOVE_ADVERTISING_SIZE },
 	{ get_adv_size_info,       MGMT_GET_ADV_SIZE_INFO_SIZE },
+	{ start_limited_discovery, MGMT_START_DISCOVERY_SIZE },
 };
 
 void mgmt_index_added(struct hci_dev *hdev)
@@ -7237,6 +7260,18 @@ void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
 			return;
 	}
 
+	if (hdev->discovery.limited) {
+		/* Check for limited discoverable bit */
+		if (dev_class) {
+			if (!(dev_class[1] & 0x20))
+				return;
+		} else {
+			u8 *flags = eir_get_data(eir, eir_len, EIR_FLAGS, NULL);
+			if (!flags || !(flags[0] & LE_AD_LIMITED))
+				return;
+		}
+	}
+
 	/* Make sure that the buffer is big enough. The 5 extra bytes
 	 * are for the potential CoD field.
 	 */
-- 
2.5.0


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

* Re: [PATCH v2 0/2] Bluetooth: Add support for Start Limited Discovery
  2016-01-05 11:19 [PATCH v2 0/2] Bluetooth: Add support for Start Limited Discovery Johan Hedberg
  2016-01-05 11:19 ` [PATCH v2 1/2] Bluetooth: Change eir_has_data_type() to more generic eir_get_data() Johan Hedberg
  2016-01-05 11:19 ` [PATCH v2 2/2] Bluetooth: Add support for Start Limited Discovery command Johan Hedberg
@ 2016-01-05 16:05 ` Marcel Holtmann
  2 siblings, 0 replies; 4+ messages in thread
From: Marcel Holtmann @ 2016-01-05 16:05 UTC (permalink / raw)
  To: Johan Hedberg; +Cc: linux-bluetooth

Hi Johan,

> These two patches implement support for the Start Limited Discovery mgmt
> command (that's been specified a long time ago but no-one picked up the
> task to implement it so far).
> 
> Johan
> 
> ---
> Johan Hedberg (2):
>      Bluetooth: Change eir_has_data_type() to more generic eir_get_data()
>      Bluetooth: Add support for Start Limited Discovery command
> 
> include/net/bluetooth/hci_core.h | 31 +++++++++++++++-------
> include/net/bluetooth/mgmt.h     |  2 ++
> net/bluetooth/hci_event.c        |  6 ++---
> net/bluetooth/hci_request.c	  | 11 +++++---
> net/bluetooth/mgmt.c             | 56 ++++++++++++++++++++++++++++++++-------
> 5 files changed, 80 insertions(+), 26 deletions(-)

both patches have been applied to bluetooth-next tree.

Regards

Marcel


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

end of thread, other threads:[~2016-01-05 16:05 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-01-05 11:19 [PATCH v2 0/2] Bluetooth: Add support for Start Limited Discovery Johan Hedberg
2016-01-05 11:19 ` [PATCH v2 1/2] Bluetooth: Change eir_has_data_type() to more generic eir_get_data() Johan Hedberg
2016-01-05 11:19 ` [PATCH v2 2/2] Bluetooth: Add support for Start Limited Discovery command Johan Hedberg
2016-01-05 16:05 ` [PATCH v2 0/2] Bluetooth: Add support for Start Limited Discovery Marcel Holtmann

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