Skip to content

Commit 8540f6c

Browse files
holtmannJohan Hedberg
authored andcommitted
Bluetooth: Add support for using controller white list filtering
The Bluetooth controller can use a white list filter when scanning to avoid waking up the host for devices that are of no interest. Devices marked as reporting, direct connection (incoming) or general connection are now added to the controller white list. The update of the white list happens just before enabling passive scanning. In case the white list is full and can not hold all devices, the white list is not used and the filter policy set to accept all advertisements. Using the white list for scanning allows for power saving with controllers that do not handle the duplicate filtering correctly. Signed-off-by: Marcel Holtmann <[email protected]> Signed-off-by: Johan Hedberg <[email protected]>
1 parent 4b9e7e7 commit 8540f6c

File tree

1 file changed

+96
-0
lines changed

1 file changed

+96
-0
lines changed

net/bluetooth/hci_core.c

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5406,12 +5406,101 @@ void hci_req_add_le_scan_disable(struct hci_request *req)
54065406
hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp);
54075407
}
54085408

5409+
static void add_to_white_list(struct hci_request *req,
5410+
struct hci_conn_params *params)
5411+
{
5412+
struct hci_cp_le_add_to_white_list cp;
5413+
5414+
cp.bdaddr_type = params->addr_type;
5415+
bacpy(&cp.bdaddr, &params->addr);
5416+
5417+
hci_req_add(req, HCI_OP_LE_ADD_TO_WHITE_LIST, sizeof(cp), &cp);
5418+
}
5419+
5420+
static u8 update_white_list(struct hci_request *req)
5421+
{
5422+
struct hci_dev *hdev = req->hdev;
5423+
struct hci_conn_params *params;
5424+
struct bdaddr_list *b;
5425+
uint8_t white_list_entries = 0;
5426+
5427+
/* Go through the current white list programmed into the
5428+
* controller one by one and check if that address is still
5429+
* in the list of pending connections or list of devices to
5430+
* report. If not present in either list, then queue the
5431+
* command to remove it from the controller.
5432+
*/
5433+
list_for_each_entry(b, &hdev->le_white_list, list) {
5434+
struct hci_cp_le_del_from_white_list cp;
5435+
5436+
if (hci_pend_le_action_lookup(&hdev->pend_le_conns,
5437+
&b->bdaddr, b->bdaddr_type) ||
5438+
hci_pend_le_action_lookup(&hdev->pend_le_reports,
5439+
&b->bdaddr, b->bdaddr_type)) {
5440+
white_list_entries++;
5441+
continue;
5442+
}
5443+
5444+
cp.bdaddr_type = b->bdaddr_type;
5445+
bacpy(&cp.bdaddr, &b->bdaddr);
5446+
5447+
hci_req_add(req, HCI_OP_LE_DEL_FROM_WHITE_LIST,
5448+
sizeof(cp), &cp);
5449+
}
5450+
5451+
/* Since all no longer valid white list entries have been
5452+
* removed, walk through the list of pending connections
5453+
* and ensure that any new device gets programmed into
5454+
* the controller.
5455+
*
5456+
* If the list of the devices is larger than the list of
5457+
* available white list entries in the controller, then
5458+
* just abort and return filer policy value to not use the
5459+
* white list.
5460+
*/
5461+
list_for_each_entry(params, &hdev->pend_le_conns, action) {
5462+
if (hci_bdaddr_list_lookup(&hdev->le_white_list,
5463+
&params->addr, params->addr_type))
5464+
continue;
5465+
5466+
if (white_list_entries >= hdev->le_white_list_size) {
5467+
/* Select filter policy to accept all advertising */
5468+
return 0x00;
5469+
}
5470+
5471+
white_list_entries++;
5472+
add_to_white_list(req, params);
5473+
}
5474+
5475+
/* After adding all new pending connections, walk through
5476+
* the list of pending reports and also add these to the
5477+
* white list if there is still space.
5478+
*/
5479+
list_for_each_entry(params, &hdev->pend_le_reports, action) {
5480+
if (hci_bdaddr_list_lookup(&hdev->le_white_list,
5481+
&params->addr, params->addr_type))
5482+
continue;
5483+
5484+
if (white_list_entries >= hdev->le_white_list_size) {
5485+
/* Select filter policy to accept all advertising */
5486+
return 0x00;
5487+
}
5488+
5489+
white_list_entries++;
5490+
add_to_white_list(req, params);
5491+
}
5492+
5493+
/* Select filter policy to use white list */
5494+
return 0x01;
5495+
}
5496+
54095497
void hci_req_add_le_passive_scan(struct hci_request *req)
54105498
{
54115499
struct hci_cp_le_set_scan_param param_cp;
54125500
struct hci_cp_le_set_scan_enable enable_cp;
54135501
struct hci_dev *hdev = req->hdev;
54145502
u8 own_addr_type;
5503+
u8 filter_policy;
54155504

54165505
/* Set require_privacy to false since no SCAN_REQ are send
54175506
* during passive scanning. Not using an unresolvable address
@@ -5422,11 +5511,18 @@ void hci_req_add_le_passive_scan(struct hci_request *req)
54225511
if (hci_update_random_address(req, false, &own_addr_type))
54235512
return;
54245513

5514+
/* Adding or removing entries from the white list must
5515+
* happen before enabling scanning. The controller does
5516+
* not allow white list modification while scanning.
5517+
*/
5518+
filter_policy = update_white_list(req);
5519+
54255520
memset(&param_cp, 0, sizeof(param_cp));
54265521
param_cp.type = LE_SCAN_PASSIVE;
54275522
param_cp.interval = cpu_to_le16(hdev->le_scan_interval);
54285523
param_cp.window = cpu_to_le16(hdev->le_scan_window);
54295524
param_cp.own_address_type = own_addr_type;
5525+
param_cp.filter_policy = filter_policy;
54305526
hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
54315527
&param_cp);
54325528

0 commit comments

Comments
 (0)