Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5e0452c0 authored by Andre Guedes's avatar Andre Guedes Committed by Johan Hedberg
Browse files

Bluetooth: Interleaved discovery support



This patch adds interleaved discovery support to MGMT Start
Discovery command.

In case interleaved discovery is not supported (not a dual mode
device), we perform BR/EDR or LE-only discovery according to the
device capabilities.

Signed-off-by: default avatarAndre Guedes <andre.guedes@openbossa.org>
Acked-by: default avatarMarcel Holtmann <marcel@holtmann.org>
Signed-off-by: default avatarJohan Hedberg <johan.hedberg@intel.com>
parent 343f935b
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -716,6 +716,7 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
#define lmp_ssp_capable(dev)       ((dev)->features[6] & LMP_SIMPLE_PAIR)
#define lmp_no_flush_capable(dev)  ((dev)->features[6] & LMP_NO_FLUSH)
#define lmp_le_capable(dev)        ((dev)->features[4] & LMP_LE)
#define lmp_bredr_capable(dev)     (!((dev)->features[4] & LMP_NO_BREDR))

/* ----- Extended LMP capabilities ----- */
#define lmp_host_le_capable(dev)   ((dev)->host_features[0] & LMP_HOST_LE)
@@ -1019,6 +1020,7 @@ int mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status);
int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status);
int mgmt_discovering(struct hci_dev *hdev, u8 discovering);
int mgmt_interleaved_discovery(struct hci_dev *hdev);
int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);

+9 −4
Original line number Diff line number Diff line
@@ -1090,11 +1090,16 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,

		clear_bit(HCI_LE_SCAN, &hdev->dev_flags);

		schedule_delayed_work(&hdev->adv_work, ADV_CLEAR_TIMEOUT);

		if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED) {
			mgmt_interleaved_discovery(hdev);
		} else {
			hci_dev_lock(hdev);
			hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
			hci_dev_unlock(hdev);
		}

		schedule_delayed_work(&hdev->adv_work, ADV_CLEAR_TIMEOUT);
		break;

	default:
+46 −1
Original line number Diff line number Diff line
@@ -108,8 +108,10 @@ static const u16 mgmt_events[] = {
#define LE_SCAN_WIN			0x12
#define LE_SCAN_INT			0x12
#define LE_SCAN_TIMEOUT_LE_ONLY		10240	/* TGAP(gen_disc_scan_min) */
#define LE_SCAN_TIMEOUT_BREDR_LE	5120	/* TGAP(100)/2 */

#define INQUIRY_LEN_BREDR		0x08	/* TGAP(100) */
#define INQUIRY_LEN_BREDR_LE		0x04	/* TGAP(100)/2 */

#define SERVICE_CACHE_TIMEOUT (5 * 1000)

@@ -2153,6 +2155,46 @@ static int remove_remote_oob_data(struct sock *sk, u16 index,
	return err;
}

static int discovery(struct hci_dev *hdev)
{
	int err;

	if (lmp_host_le_capable(hdev)) {
		if (lmp_bredr_capable(hdev)) {
			err = hci_le_scan(hdev, LE_SCAN_TYPE,
						LE_SCAN_INT, LE_SCAN_WIN,
						LE_SCAN_TIMEOUT_BREDR_LE);
		} else {
			hdev->discovery.type = DISCOV_TYPE_LE;
			err = hci_le_scan(hdev, LE_SCAN_TYPE,
						LE_SCAN_INT, LE_SCAN_WIN,
						LE_SCAN_TIMEOUT_LE_ONLY);
		}
	} else {
		hdev->discovery.type = DISCOV_TYPE_BREDR;
		err = hci_do_inquiry(hdev, INQUIRY_LEN_BREDR);
	}

	return err;
}

int mgmt_interleaved_discovery(struct hci_dev *hdev)
{
	int err;

	BT_DBG("%s", hdev->name);

	hci_dev_lock(hdev);

	err = hci_do_inquiry(hdev, INQUIRY_LEN_BREDR_LE);
	if (err < 0)
		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);

	hci_dev_unlock(hdev);

	return err;
}

static int start_discovery(struct sock *sk, u16 index,
						void *data, u16 len)
{
@@ -2196,7 +2238,6 @@ static int start_discovery(struct sock *sk, u16 index,

	switch (hdev->discovery.type) {
	case DISCOV_TYPE_BREDR:
	case DISCOV_TYPE_INTERLEAVED:
		err = hci_do_inquiry(hdev, INQUIRY_LEN_BREDR);
		break;

@@ -2205,6 +2246,10 @@ static int start_discovery(struct sock *sk, u16 index,
					LE_SCAN_WIN, LE_SCAN_TIMEOUT_LE_ONLY);
		break;

	case DISCOV_TYPE_INTERLEAVED:
		err = discovery(hdev);
		break;

	default:
		err = -EINVAL;
	}