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

Commit 2cf22218 authored by Johan Hedberg's avatar Johan Hedberg Committed by Marcel Holtmann
Browse files

Bluetooth: Add hci_request support for hci_update_background_scan



Many places using hci_update_background_scan() try to synchronize
whatever they're doing with the help of hci_request callbacks. However,
since the hci_update_background_scan() function hasn't so far accepted a
hci_request pointer any commands triggered by it have been left out by
the synchronization. This patch modifies the API in a similar way as was
done for hci_update_page_scan, i.e. there's a variant that takes a
hci_request and another one that takes a hci_dev.

Signed-off-by: default avatarJohan Hedberg <johan.hedberg@intel.com>
Signed-off-by: default avatarMarcel Holtmann <marcel@holtmann.org>
parent 0857dd3b
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -930,8 +930,6 @@ struct hci_conn_params *hci_pend_le_action_lookup(struct list_head *list,
						  bdaddr_t *addr,
						  u8 addr_type);

void hci_update_background_scan(struct hci_dev *hdev);

void hci_uuids_clear(struct hci_dev *hdev);

void hci_link_keys_clear(struct hci_dev *hdev);
+0 −89
Original line number Diff line number Diff line
@@ -5312,95 +5312,6 @@ static void hci_cmd_work(struct work_struct *work)
	}
}

static void update_background_scan_complete(struct hci_dev *hdev, u8 status)
{
	if (status)
		BT_DBG("HCI request failed to update background scanning: "
		       "status 0x%2.2x", status);
}

/* This function controls the background scanning based on hdev->pend_le_conns
 * list. If there are pending LE connection we start the background scanning,
 * otherwise we stop it.
 *
 * This function requires the caller holds hdev->lock.
 */
void hci_update_background_scan(struct hci_dev *hdev)
{
	struct hci_request req;
	struct hci_conn *conn;
	int err;

	if (!test_bit(HCI_UP, &hdev->flags) ||
	    test_bit(HCI_INIT, &hdev->flags) ||
	    test_bit(HCI_SETUP, &hdev->dev_flags) ||
	    test_bit(HCI_CONFIG, &hdev->dev_flags) ||
	    test_bit(HCI_AUTO_OFF, &hdev->dev_flags) ||
	    test_bit(HCI_UNREGISTER, &hdev->dev_flags))
		return;

	/* No point in doing scanning if LE support hasn't been enabled */
	if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
		return;

	/* If discovery is active don't interfere with it */
	if (hdev->discovery.state != DISCOVERY_STOPPED)
		return;

	/* Reset RSSI and UUID filters when starting background scanning
	 * since these filters are meant for service discovery only.
	 *
	 * The Start Discovery and Start Service Discovery operations
	 * ensure to set proper values for RSSI threshold and UUID
	 * filter list. So it is safe to just reset them here.
	 */
	hci_discovery_filter_clear(hdev);

	hci_req_init(&req, hdev);

	if (list_empty(&hdev->pend_le_conns) &&
	    list_empty(&hdev->pend_le_reports)) {
		/* If there is no pending LE connections or devices
		 * to be scanned for, we should stop the background
		 * scanning.
		 */

		/* If controller is not scanning we are done. */
		if (!test_bit(HCI_LE_SCAN, &hdev->dev_flags))
			return;

		hci_req_add_le_scan_disable(&req);

		BT_DBG("%s stopping background scanning", hdev->name);
	} else {
		/* If there is at least one pending LE connection, we should
		 * keep the background scan running.
		 */

		/* If controller is connecting, we should not start scanning
		 * since some controllers are not able to scan and connect at
		 * the same time.
		 */
		conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
		if (conn)
			return;

		/* If controller is currently scanning, we stop it to ensure we
		 * don't miss any advertising (due to duplicates filter).
		 */
		if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
			hci_req_add_le_scan_disable(&req);

		hci_req_add_le_passive_scan(&req);

		BT_DBG("%s starting background scanning", hdev->name);
	}

	err = hci_req_run(&req, update_background_scan_complete);
	if (err)
		BT_ERR("Failed to run HCI request: err %d", err);
}

static bool disconnected_whitelist_entries(struct hci_dev *hdev)
{
	struct bdaddr_list *b;
+96 −0
Original line number Diff line number Diff line
@@ -395,3 +395,99 @@ int hci_update_random_address(struct hci_request *req, bool require_privacy,

	return 0;
}

/* This function controls the background scanning based on hdev->pend_le_conns
 * list. If there are pending LE connection we start the background scanning,
 * otherwise we stop it.
 *
 * This function requires the caller holds hdev->lock.
 */
void __hci_update_background_scan(struct hci_request *req)
{
	struct hci_dev *hdev = req->hdev;
	struct hci_conn *conn;

	if (!test_bit(HCI_UP, &hdev->flags) ||
	    test_bit(HCI_INIT, &hdev->flags) ||
	    test_bit(HCI_SETUP, &hdev->dev_flags) ||
	    test_bit(HCI_CONFIG, &hdev->dev_flags) ||
	    test_bit(HCI_AUTO_OFF, &hdev->dev_flags) ||
	    test_bit(HCI_UNREGISTER, &hdev->dev_flags))
		return;

	/* No point in doing scanning if LE support hasn't been enabled */
	if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
		return;

	/* If discovery is active don't interfere with it */
	if (hdev->discovery.state != DISCOVERY_STOPPED)
		return;

	/* Reset RSSI and UUID filters when starting background scanning
	 * since these filters are meant for service discovery only.
	 *
	 * The Start Discovery and Start Service Discovery operations
	 * ensure to set proper values for RSSI threshold and UUID
	 * filter list. So it is safe to just reset them here.
	 */
	hci_discovery_filter_clear(hdev);

	if (list_empty(&hdev->pend_le_conns) &&
	    list_empty(&hdev->pend_le_reports)) {
		/* If there is no pending LE connections or devices
		 * to be scanned for, we should stop the background
		 * scanning.
		 */

		/* If controller is not scanning we are done. */
		if (!test_bit(HCI_LE_SCAN, &hdev->dev_flags))
			return;

		hci_req_add_le_scan_disable(req);

		BT_DBG("%s stopping background scanning", hdev->name);
	} else {
		/* If there is at least one pending LE connection, we should
		 * keep the background scan running.
		 */

		/* If controller is connecting, we should not start scanning
		 * since some controllers are not able to scan and connect at
		 * the same time.
		 */
		conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
		if (conn)
			return;

		/* If controller is currently scanning, we stop it to ensure we
		 * don't miss any advertising (due to duplicates filter).
		 */
		if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
			hci_req_add_le_scan_disable(req);

		hci_req_add_le_passive_scan(req);

		BT_DBG("%s starting background scanning", hdev->name);
	}
}

static void update_background_scan_complete(struct hci_dev *hdev, u8 status)
{
	if (status)
		BT_DBG("HCI request failed to update background scanning: "
		       "status 0x%2.2x", status);
}

void hci_update_background_scan(struct hci_dev *hdev)
{
	int err;
	struct hci_request req;

	hci_req_init(&req, hdev);

	__hci_update_background_scan(&req);

	err = hci_req_run(&req, update_background_scan_complete);
	if (err && err != -ENODATA)
		BT_ERR("Failed to run HCI request: err %d", err);
}
+3 −0
Original line number Diff line number Diff line
@@ -49,3 +49,6 @@ void __hci_update_page_scan(struct hci_request *req);

int hci_update_random_address(struct hci_request *req, bool require_privacy,
			      u8 *own_addr_type);

void hci_update_background_scan(struct hci_dev *hdev);
void __hci_update_background_scan(struct hci_request *req);
+6 −6
Original line number Diff line number Diff line
@@ -2228,9 +2228,8 @@ static void le_enable_complete(struct hci_dev *hdev, u8 status)
		hci_req_init(&req, hdev);
		update_adv_data(&req);
		update_scan_rsp_data(&req);
		__hci_update_background_scan(&req);
		hci_req_run(&req, NULL);

		hci_update_background_scan(hdev);
	}

unlock:
@@ -6038,8 +6037,9 @@ void mgmt_index_removed(struct hci_dev *hdev)
}

/* This function requires the caller holds hdev->lock */
static void restart_le_actions(struct hci_dev *hdev)
static void restart_le_actions(struct hci_request *req)
{
	struct hci_dev *hdev = req->hdev;
	struct hci_conn_params *p;

	list_for_each_entry(p, &hdev->le_conn_params, list) {
@@ -6061,7 +6061,7 @@ static void restart_le_actions(struct hci_dev *hdev)
		}
	}

	hci_update_background_scan(hdev);
	__hci_update_background_scan(req);
}

static void powered_complete(struct hci_dev *hdev, u8 status)
@@ -6072,8 +6072,6 @@ static void powered_complete(struct hci_dev *hdev, u8 status)

	hci_dev_lock(hdev);

	restart_le_actions(hdev);

	mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);

	new_settings(hdev, match.sk);
@@ -6131,6 +6129,8 @@ static int powered_update_hci(struct hci_dev *hdev)

		if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
			enable_advertising(&req);

		restart_le_actions(&req);
	}

	link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);