|
|
|
@@ -382,53 +382,6 @@ void __hci_req_write_fast_connectable(struct hci_request *req, bool enable)
|
|
|
|
|
hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void start_interleave_scan(struct hci_dev *hdev)
|
|
|
|
|
{
|
|
|
|
|
hdev->interleave_scan_state = INTERLEAVE_SCAN_NO_FILTER;
|
|
|
|
|
queue_delayed_work(hdev->req_workqueue,
|
|
|
|
|
&hdev->interleave_scan, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool is_interleave_scanning(struct hci_dev *hdev)
|
|
|
|
|
{
|
|
|
|
|
return hdev->interleave_scan_state != INTERLEAVE_SCAN_NONE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void cancel_interleave_scan(struct hci_dev *hdev)
|
|
|
|
|
{
|
|
|
|
|
bt_dev_dbg(hdev, "cancelling interleave scan");
|
|
|
|
|
|
|
|
|
|
cancel_delayed_work_sync(&hdev->interleave_scan);
|
|
|
|
|
|
|
|
|
|
hdev->interleave_scan_state = INTERLEAVE_SCAN_NONE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Return true if interleave_scan wasn't started until exiting this function,
|
|
|
|
|
* otherwise, return false
|
|
|
|
|
*/
|
|
|
|
|
static bool __hci_update_interleaved_scan(struct hci_dev *hdev)
|
|
|
|
|
{
|
|
|
|
|
/* If there is at least one ADV monitors and one pending LE connection
|
|
|
|
|
* or one device to be scanned for, we should alternate between
|
|
|
|
|
* allowlist scan and one without any filters to save power.
|
|
|
|
|
*/
|
|
|
|
|
bool use_interleaving = hci_is_adv_monitoring(hdev) &&
|
|
|
|
|
!(list_empty(&hdev->pend_le_conns) &&
|
|
|
|
|
list_empty(&hdev->pend_le_reports));
|
|
|
|
|
bool is_interleaving = is_interleave_scanning(hdev);
|
|
|
|
|
|
|
|
|
|
if (use_interleaving && !is_interleaving) {
|
|
|
|
|
start_interleave_scan(hdev);
|
|
|
|
|
bt_dev_dbg(hdev, "starting interleave scan");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!use_interleaving && is_interleaving)
|
|
|
|
|
cancel_interleave_scan(hdev);
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 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.
|
|
|
|
@@ -501,7 +454,8 @@ static void __hci_update_background_scan(struct hci_request *req)
|
|
|
|
|
hci_req_add_le_scan_disable(req, false);
|
|
|
|
|
|
|
|
|
|
hci_req_add_le_passive_scan(req);
|
|
|
|
|
bt_dev_dbg(hdev, "starting background scanning");
|
|
|
|
|
|
|
|
|
|
BT_DBG("%s starting background scanning", hdev->name);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -902,17 +856,12 @@ static u8 update_white_list(struct hci_request *req)
|
|
|
|
|
return 0x00;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Use the allowlist unless the following conditions are all true:
|
|
|
|
|
* - We are not currently suspending
|
|
|
|
|
* - There are 1 or more ADV monitors registered
|
|
|
|
|
* - Interleaved scanning is not currently using the allowlist
|
|
|
|
|
*
|
|
|
|
|
* Once the controller offloading of advertisement monitor is in place,
|
|
|
|
|
* the above condition should include the support of MSFT extension
|
|
|
|
|
* support.
|
|
|
|
|
/* Once the controller offloading of advertisement monitor is in place,
|
|
|
|
|
* the if condition should include the support of MSFT extension
|
|
|
|
|
* support. If suspend is ongoing, whitelist should be the default to
|
|
|
|
|
* prevent waking by random advertisements.
|
|
|
|
|
*/
|
|
|
|
|
if (!idr_is_empty(&hdev->adv_monitors_idr) && !hdev->suspended &&
|
|
|
|
|
hdev->interleave_scan_state != INTERLEAVE_SCAN_ALLOWLIST)
|
|
|
|
|
if (!idr_is_empty(&hdev->adv_monitors_idr) && !hdev->suspended)
|
|
|
|
|
return 0x00;
|
|
|
|
|
|
|
|
|
|
/* Select filter policy to use white list */
|
|
|
|
@@ -1065,10 +1014,6 @@ void hci_req_add_le_passive_scan(struct hci_request *req)
|
|
|
|
|
&own_addr_type))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (__hci_update_interleaved_scan(hdev))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
bt_dev_dbg(hdev, "interleave state %d", hdev->interleave_scan_state);
|
|
|
|
|
/* Adding or removing entries from the white list must
|
|
|
|
|
* happen before enabling scanning. The controller does
|
|
|
|
|
* not allow white list modification while scanning.
|
|
|
|
@@ -1936,62 +1881,6 @@ unlock:
|
|
|
|
|
hci_dev_unlock(hdev);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int hci_req_add_le_interleaved_scan(struct hci_request *req,
|
|
|
|
|
unsigned long opt)
|
|
|
|
|
{
|
|
|
|
|
struct hci_dev *hdev = req->hdev;
|
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
|
|
hci_dev_lock(hdev);
|
|
|
|
|
|
|
|
|
|
if (hci_dev_test_flag(hdev, HCI_LE_SCAN))
|
|
|
|
|
hci_req_add_le_scan_disable(req, false);
|
|
|
|
|
hci_req_add_le_passive_scan(req);
|
|
|
|
|
|
|
|
|
|
switch (hdev->interleave_scan_state) {
|
|
|
|
|
case INTERLEAVE_SCAN_ALLOWLIST:
|
|
|
|
|
bt_dev_dbg(hdev, "next state: allowlist");
|
|
|
|
|
hdev->interleave_scan_state = INTERLEAVE_SCAN_NO_FILTER;
|
|
|
|
|
break;
|
|
|
|
|
case INTERLEAVE_SCAN_NO_FILTER:
|
|
|
|
|
bt_dev_dbg(hdev, "next state: no filter");
|
|
|
|
|
hdev->interleave_scan_state = INTERLEAVE_SCAN_ALLOWLIST;
|
|
|
|
|
break;
|
|
|
|
|
case INTERLEAVE_SCAN_NONE:
|
|
|
|
|
BT_ERR("unexpected error");
|
|
|
|
|
ret = -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
hci_dev_unlock(hdev);
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void interleave_scan_work(struct work_struct *work)
|
|
|
|
|
{
|
|
|
|
|
struct hci_dev *hdev = container_of(work, struct hci_dev,
|
|
|
|
|
interleave_scan.work);
|
|
|
|
|
u8 status;
|
|
|
|
|
unsigned long timeout;
|
|
|
|
|
|
|
|
|
|
if (hdev->interleave_scan_state == INTERLEAVE_SCAN_ALLOWLIST) {
|
|
|
|
|
timeout = msecs_to_jiffies(hdev->advmon_allowlist_duration);
|
|
|
|
|
} else if (hdev->interleave_scan_state == INTERLEAVE_SCAN_NO_FILTER) {
|
|
|
|
|
timeout = msecs_to_jiffies(hdev->advmon_no_filter_duration);
|
|
|
|
|
} else {
|
|
|
|
|
bt_dev_err(hdev, "unexpected error");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
hci_req_sync(hdev, hci_req_add_le_interleaved_scan, 0,
|
|
|
|
|
HCI_CMD_TIMEOUT, &status);
|
|
|
|
|
|
|
|
|
|
/* Don't continue interleaving if it was canceled */
|
|
|
|
|
if (is_interleave_scanning(hdev))
|
|
|
|
|
queue_delayed_work(hdev->req_workqueue,
|
|
|
|
|
&hdev->interleave_scan, timeout);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int hci_get_random_address(struct hci_dev *hdev, bool require_privacy,
|
|
|
|
|
bool use_rpa, struct adv_info *adv_instance,
|
|
|
|
|
u8 *own_addr_type, bdaddr_t *rand_addr)
|
|
|
|
@@ -3419,7 +3308,6 @@ void hci_request_setup(struct hci_dev *hdev)
|
|
|
|
|
INIT_DELAYED_WORK(&hdev->le_scan_disable, le_scan_disable_work);
|
|
|
|
|
INIT_DELAYED_WORK(&hdev->le_scan_restart, le_scan_restart_work);
|
|
|
|
|
INIT_DELAYED_WORK(&hdev->adv_instance_expire, adv_timeout_expire);
|
|
|
|
|
INIT_DELAYED_WORK(&hdev->interleave_scan, interleave_scan_work);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void hci_request_cancel_all(struct hci_dev *hdev)
|
|
|
|
@@ -3439,6 +3327,4 @@ void hci_request_cancel_all(struct hci_dev *hdev)
|
|
|
|
|
cancel_delayed_work_sync(&hdev->adv_instance_expire);
|
|
|
|
|
hdev->adv_instance_timeout = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cancel_interleave_scan(hdev);
|
|
|
|
|
}
|
|
|
|
|