Commit 8208f5a9 authored by Miao-chen Chou's avatar Miao-chen Chou Committed by Johan Hedberg

Bluetooth: Update background scan and report device based on advertisement monitors

This calls hci_update_background_scan() when there is any update on the
advertisement monitors. If there is at least one advertisement monitor,
the filtering policy of scan parameters should be 0x00. This also reports
device found mgmt events if there is at least one monitor.

The following cases were tested with btmgmt advmon-* commands.
(1) add a ADV monitor and observe that the passive scanning is
triggered.
(2) remove the last ADV monitor and observe that the passive scanning is
terminated.
(3) with a LE peripheral paired, repeat (1) and observe the passive
scanning continues.
(4) with a LE peripheral paired, repeat (2) and observe the passive
scanning continues.
(5) with a ADV monitor, suspend/resume the host and observe the passive
scanning continues.
Signed-off-by: default avatarMiao-chen Chou <mcchou@chromium.org>
Signed-off-by: default avatarMarcel Holtmann <marcel@holtmann.org>
Signed-off-by: default avatarJohan Hedberg <johan.hedberg@intel.com>
parent cdde92e2
...@@ -1284,6 +1284,7 @@ void hci_adv_monitors_clear(struct hci_dev *hdev); ...@@ -1284,6 +1284,7 @@ void hci_adv_monitors_clear(struct hci_dev *hdev);
void hci_free_adv_monitor(struct adv_monitor *monitor); void hci_free_adv_monitor(struct adv_monitor *monitor);
int hci_add_adv_monitor(struct hci_dev *hdev, struct adv_monitor *monitor); int hci_add_adv_monitor(struct hci_dev *hdev, struct adv_monitor *monitor);
int hci_remove_adv_monitor(struct hci_dev *hdev, u16 handle); int hci_remove_adv_monitor(struct hci_dev *hdev, u16 handle);
bool hci_is_adv_monitoring(struct hci_dev *hdev);
void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb); void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb);
......
...@@ -3005,6 +3005,8 @@ void hci_adv_monitors_clear(struct hci_dev *hdev) ...@@ -3005,6 +3005,8 @@ void hci_adv_monitors_clear(struct hci_dev *hdev)
hci_free_adv_monitor(monitor); hci_free_adv_monitor(monitor);
idr_destroy(&hdev->adv_monitors_idr); idr_destroy(&hdev->adv_monitors_idr);
hci_update_background_scan(hdev);
} }
void hci_free_adv_monitor(struct adv_monitor *monitor) void hci_free_adv_monitor(struct adv_monitor *monitor)
...@@ -3038,6 +3040,9 @@ int hci_add_adv_monitor(struct hci_dev *hdev, struct adv_monitor *monitor) ...@@ -3038,6 +3040,9 @@ int hci_add_adv_monitor(struct hci_dev *hdev, struct adv_monitor *monitor)
hdev->adv_monitors_cnt++; hdev->adv_monitors_cnt++;
monitor->handle = handle; monitor->handle = handle;
hci_update_background_scan(hdev);
return 0; return 0;
} }
...@@ -3069,9 +3074,17 @@ int hci_remove_adv_monitor(struct hci_dev *hdev, u16 handle) ...@@ -3069,9 +3074,17 @@ int hci_remove_adv_monitor(struct hci_dev *hdev, u16 handle)
idr_for_each(&hdev->adv_monitors_idr, &free_adv_monitor, hdev); idr_for_each(&hdev->adv_monitors_idr, &free_adv_monitor, hdev);
} }
hci_update_background_scan(hdev);
return 0; return 0;
} }
/* This function requires the caller holds hdev->lock */
bool hci_is_adv_monitoring(struct hci_dev *hdev)
{
return !idr_is_empty(&hdev->adv_monitors_idr);
}
struct bdaddr_list *hci_bdaddr_list_lookup(struct list_head *bdaddr_list, struct bdaddr_list *hci_bdaddr_list_lookup(struct list_head *bdaddr_list,
bdaddr_t *bdaddr, u8 type) bdaddr_t *bdaddr, u8 type)
{ {
......
...@@ -5447,14 +5447,15 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr, ...@@ -5447,14 +5447,15 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
/* Passive scanning shouldn't trigger any device found events, /* Passive scanning shouldn't trigger any device found events,
* except for devices marked as CONN_REPORT for which we do send * except for devices marked as CONN_REPORT for which we do send
* device found events. * device found events, or advertisement monitoring requested.
*/ */
if (hdev->le_scan_type == LE_SCAN_PASSIVE) { if (hdev->le_scan_type == LE_SCAN_PASSIVE) {
if (type == LE_ADV_DIRECT_IND) if (type == LE_ADV_DIRECT_IND)
return; return;
if (!hci_pend_le_action_lookup(&hdev->pend_le_reports, if (!hci_pend_le_action_lookup(&hdev->pend_le_reports,
bdaddr, bdaddr_type)) bdaddr, bdaddr_type) &&
idr_is_empty(&hdev->adv_monitors_idr))
return; return;
if (type == LE_ADV_NONCONN_IND || type == LE_ADV_SCAN_IND) if (type == LE_ADV_NONCONN_IND || type == LE_ADV_SCAN_IND)
......
...@@ -413,11 +413,15 @@ static void __hci_update_background_scan(struct hci_request *req) ...@@ -413,11 +413,15 @@ static void __hci_update_background_scan(struct hci_request *req)
*/ */
hci_discovery_filter_clear(hdev); hci_discovery_filter_clear(hdev);
BT_DBG("%s ADV monitoring is %s", hdev->name,
hci_is_adv_monitoring(hdev) ? "on" : "off");
if (list_empty(&hdev->pend_le_conns) && if (list_empty(&hdev->pend_le_conns) &&
list_empty(&hdev->pend_le_reports)) { list_empty(&hdev->pend_le_reports) &&
!hci_is_adv_monitoring(hdev)) {
/* If there is no pending LE connections or devices /* If there is no pending LE connections or devices
* to be scanned for, we should stop the background * to be scanned for or no ADV monitors, we should stop the
* scanning. * background scanning.
*/ */
/* If controller is not scanning we are done. */ /* If controller is not scanning we are done. */
...@@ -794,6 +798,13 @@ static u8 update_white_list(struct hci_request *req) ...@@ -794,6 +798,13 @@ static u8 update_white_list(struct hci_request *req)
return 0x00; return 0x00;
} }
/* Once the controller offloading of advertisement monitor is in place,
* the if condition should include the support of MSFT extension
* support.
*/
if (!idr_is_empty(&hdev->adv_monitors_idr))
return 0x00;
/* Select filter policy to use white list */ /* Select filter policy to use white list */
return 0x01; return 0x01;
} }
......
...@@ -8575,9 +8575,12 @@ void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, ...@@ -8575,9 +8575,12 @@ void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
if (!hci_discovery_active(hdev)) { if (!hci_discovery_active(hdev)) {
if (link_type == ACL_LINK) if (link_type == ACL_LINK)
return; return;
if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports)) if (link_type == LE_LINK &&
list_empty(&hdev->pend_le_reports) &&
!hci_is_adv_monitoring(hdev)) {
return; return;
} }
}
if (hdev->discovery.result_filtering) { if (hdev->discovery.result_filtering) {
/* We are using service discovery */ /* We are using service discovery */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment