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: Johan Hedberg <johan.hedberg@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
This commit is contained in:
parent
0857dd3bed
commit
2cf22218b0
5 changed files with 105 additions and 97 deletions
|
@ -930,8 +930,6 @@ struct hci_conn_params *hci_pend_le_action_lookup(struct list_head *list,
|
||||||
bdaddr_t *addr,
|
bdaddr_t *addr,
|
||||||
u8 addr_type);
|
u8 addr_type);
|
||||||
|
|
||||||
void hci_update_background_scan(struct hci_dev *hdev);
|
|
||||||
|
|
||||||
void hci_uuids_clear(struct hci_dev *hdev);
|
void hci_uuids_clear(struct hci_dev *hdev);
|
||||||
|
|
||||||
void hci_link_keys_clear(struct hci_dev *hdev);
|
void hci_link_keys_clear(struct hci_dev *hdev);
|
||||||
|
|
|
@ -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)
|
static bool disconnected_whitelist_entries(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
struct bdaddr_list *b;
|
struct bdaddr_list *b;
|
||||||
|
|
|
@ -395,3 +395,99 @@ int hci_update_random_address(struct hci_request *req, bool require_privacy,
|
||||||
|
|
||||||
return 0;
|
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);
|
||||||
|
}
|
||||||
|
|
|
@ -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,
|
int hci_update_random_address(struct hci_request *req, bool require_privacy,
|
||||||
u8 *own_addr_type);
|
u8 *own_addr_type);
|
||||||
|
|
||||||
|
void hci_update_background_scan(struct hci_dev *hdev);
|
||||||
|
void __hci_update_background_scan(struct hci_request *req);
|
||||||
|
|
|
@ -2228,9 +2228,8 @@ static void le_enable_complete(struct hci_dev *hdev, u8 status)
|
||||||
hci_req_init(&req, hdev);
|
hci_req_init(&req, hdev);
|
||||||
update_adv_data(&req);
|
update_adv_data(&req);
|
||||||
update_scan_rsp_data(&req);
|
update_scan_rsp_data(&req);
|
||||||
|
__hci_update_background_scan(&req);
|
||||||
hci_req_run(&req, NULL);
|
hci_req_run(&req, NULL);
|
||||||
|
|
||||||
hci_update_background_scan(hdev);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unlock:
|
unlock:
|
||||||
|
@ -6038,8 +6037,9 @@ void mgmt_index_removed(struct hci_dev *hdev)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function requires the caller holds hdev->lock */
|
/* 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;
|
struct hci_conn_params *p;
|
||||||
|
|
||||||
list_for_each_entry(p, &hdev->le_conn_params, list) {
|
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)
|
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);
|
hci_dev_lock(hdev);
|
||||||
|
|
||||||
restart_le_actions(hdev);
|
|
||||||
|
|
||||||
mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
|
mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
|
||||||
|
|
||||||
new_settings(hdev, match.sk);
|
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))
|
if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
|
||||||
enable_advertising(&req);
|
enable_advertising(&req);
|
||||||
|
|
||||||
|
restart_le_actions(&req);
|
||||||
}
|
}
|
||||||
|
|
||||||
link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
|
link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
|
||||||
|
|
Loading…
Reference in a new issue