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

Commit 07d2334a authored by Jakub Pawlowski's avatar Jakub Pawlowski Committed by Johan Hedberg
Browse files

Bluetooth: Add simultaneous dual mode scan



When doing scan through mgmt api, some controllers can do both le and
classic scan at same time. They can be distinguished by
HCI_QUIRK_SIMULTANEOUS_DISCOVERY set.

This patch enables them to use this feature when doing dual mode scan.
Instead of doing le, then classic scan, both scans are run at once.

Signed-off-by: default avatarJakub Pawlowski <jpawlowski@google.com>
Signed-off-by: default avatarJohan Hedberg <johan.hedberg@intel.com>
parent 812abb13
Loading
Loading
Loading
Loading
+19 −5
Original line number Diff line number Diff line
@@ -2902,12 +2902,26 @@ static void le_scan_disable_work_complete(struct hci_dev *hdev, u8 status,

		hci_dev_lock(hdev);

		if (test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY,
			     &hdev->quirks)) {
			/* If we were running LE only scan, change discovery
			 * state. If we were running both LE and BR/EDR inquiry
			 * simultaneously, and BR/EDR inquiry is already
			 * finished, stop discovery, otherwise BR/EDR inquiry
			 * will stop discovery when finished.
			 */
			if (!test_bit(HCI_INQUIRY, &hdev->flags))
				hci_discovery_set_state(hdev,
							DISCOVERY_STOPPED);
		} else {
			hci_inquiry_cache_flush(hdev);

			err = hci_req_run(&req, inquiry_complete);
			if (err) {
				BT_ERR("Inquiry request failed: err %d", err);
			hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
				hci_discovery_set_state(hdev,
							DISCOVERY_STOPPED);
			}
		}

		hci_dev_unlock(hdev);
+20 −2
Original line number Diff line number Diff line
@@ -2126,6 +2126,15 @@ static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
		goto unlock;

	if (list_empty(&discov->resolve)) {
		/* When BR/EDR inquiry is active and no LE scanning is in
		 * progress, then change discovery state to indicate completion.
		 *
		 * When running LE scanning and BR/EDR inquiry simultaneously
		 * and the LE scan already finished, then change the discovery
		 * state to indicate completion.
		 */
		if (!hci_dev_test_flag(hdev, HCI_LE_SCAN) ||
		    !test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks))
			hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
		goto unlock;
	}
@@ -2135,6 +2144,15 @@ static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
		e->name_state = NAME_PENDING;
		hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
	} else {
		/* When BR/EDR inquiry is active and no LE scanning is in
		 * progress, then change discovery state to indicate completion.
		 *
		 * When running LE scanning and BR/EDR inquiry simultaneously
		 * and the LE scan already finished, then change the discovery
		 * state to indicate completion.
		 */
		if (!hci_dev_test_flag(hdev, HCI_LE_SCAN) ||
		    !test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks))
			hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
	}

+31 −3
Original line number Diff line number Diff line
@@ -1408,9 +1408,10 @@ static bool hci_stop_discovery(struct hci_request *req)

	switch (hdev->discovery.state) {
	case DISCOVERY_FINDING:
		if (test_bit(HCI_INQUIRY, &hdev->flags)) {
		if (test_bit(HCI_INQUIRY, &hdev->flags))
			hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
		} else {

		if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) {
			cancel_delayed_work(&hdev->le_scan_disable);
			hci_req_add_le_scan_disable(req);
		}
@@ -4019,6 +4020,22 @@ static bool trigger_discovery(struct hci_request *req, u8 *status)
		break;

	case DISCOV_TYPE_INTERLEAVED:
		if (test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY,
			     &hdev->quirks)) {
			/* During simultaneous discovery, we double LE scan
			 * interval. We must leave some time for the controller
			 * to do BR/EDR inquiry.
			 */
			if (!trigger_le_scan(req, DISCOV_LE_SCAN_INT * 2,
					     status))
				return false;

			if (!trigger_bredr_inquiry(req, status))
				return false;

			return true;
		}

		if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
			*status = MGMT_STATUS_NOT_SUPPORTED;
			return false;
@@ -4072,6 +4089,17 @@ static void start_discovery_complete(struct hci_dev *hdev, u8 status,
		timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
		break;
	case DISCOV_TYPE_INTERLEAVED:
		 /* When running simultaneous discovery, the LE scanning time
		 * should occupy the whole discovery time sine BR/EDR inquiry
		 * and LE scanning are scheduled by the controller.
		 *
		 * For interleaving discovery in comparison, BR/EDR inquiry
		 * and LE scanning are done sequentially with separate
		 * timeouts.
		 */
		if (test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks))
			timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
		else
			timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
		break;
	case DISCOV_TYPE_BREDR: