[PATCH] Bluetooth: Add support for entering limited discoverable mode

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The limited discoverable mode should be used when a device is only
discoverable for a certain amount of time and after that it returns
back into being non-discoverable.

The management interface allows to specify a timeout parameter when
makeing a device discoverable. If such a timeout is specified or
changed, enter limited discoverable mode. Otherwise enter general
discoverable mode.

Devices in limited discoverable mode can still be found by the
general discovery procedure. It is mandatory that a device sets
both GIAC and LIAC when entering limited discoverable mode.

Signed-off-by: Marcel Holtmann <marcel@xxxxxxxxxxxx>
---
 include/net/bluetooth/hci.h |  6 ++++++
 net/bluetooth/mgmt.c        | 41 +++++++++++++++++++++++++++++++++++++----
 2 files changed, 43 insertions(+), 4 deletions(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index b096f5f..ab96f3b 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -823,6 +823,12 @@ struct hci_rp_read_num_supported_iac {
 
 #define HCI_OP_READ_CURRENT_IAC_LAP	0x0c39
 
+#define HCI_OP_WRITE_CURRENT_IAC_LAP	0x0c3a
+struct hci_cp_write_current_iac_lap {
+	__u8	num_iac;
+	__u8	iac_lap[6];
+} __packed;
+
 #define HCI_OP_WRITE_INQUIRY_MODE	0x0c45
 
 #define HCI_MAX_EIR_LENGTH		240
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 861e389..cba15da 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1041,6 +1041,8 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
 	}
 
 	if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
+		u16 current_timeout = hdev->discov_timeout;
+
 		if (hdev->discov_timeout > 0) {
 			cancel_delayed_work(&hdev->discov_off);
 			hdev->discov_timeout = 0;
@@ -1052,8 +1054,16 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
 				msecs_to_jiffies(hdev->discov_timeout * 1000));
 		}
 
-		err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
-		goto failed;
+		/* A change in timeout means that the device is switching
+		 * from one discoverable mode to another. In that case
+		 * the IAC LAP needs to be changed.
+		 */
+		if ((current_timeout > 0 && timeout > 0) ||
+		    (current_timeout == 0 && timeout == 0)) {
+			err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE,
+						hdev);
+			goto failed;
+		}
 	}
 
 	cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
@@ -1066,10 +1076,33 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
 
 	scan = SCAN_PAGE;
 
-	if (cp->val)
+	if (cp->val) {
+		struct hci_cp_write_current_iac_lap cp;
+
+		if (timeout > 0) {
+			/* Limited discoverable mode */
+			cp.num_iac = 2;
+			cp.iac_lap[0] = 0x00;	/* LIAC */
+			cp.iac_lap[1] = 0x8b;
+			cp.iac_lap[2] = 0x9e;
+			cp.iac_lap[3] = 0x33;	/* GIAC */
+			cp.iac_lap[4] = 0x8b;
+			cp.iac_lap[5] = 0x9e;
+		} else {
+			/* General discoverable mode */
+			cp.num_iac = 1;
+			cp.iac_lap[0] = 0x33;	/* GIAC */
+			cp.iac_lap[1] = 0x8b;
+			cp.iac_lap[2] = 0x9e;
+		}
+
+		hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
+			    (cp.num_iac * 3) + 1, &cp);
+
 		scan |= SCAN_INQUIRY;
-	else
+	} else {
 		cancel_delayed_work(&hdev->discov_off);
+	}
 
 	hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
 
-- 
1.8.3.1

--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux