diff options
Diffstat (limited to 'net/bluetooth/hci_request.c')
-rw-r--r-- | net/bluetooth/hci_request.c | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c index eba83a2a6556..e49f682f1550 100644 --- a/net/bluetooth/hci_request.c +++ b/net/bluetooth/hci_request.c | |||
@@ -395,3 +395,99 @@ int hci_update_random_address(struct hci_request *req, bool require_privacy, | |||
395 | 395 | ||
396 | return 0; | 396 | return 0; |
397 | } | 397 | } |
398 | |||
399 | /* This function controls the background scanning based on hdev->pend_le_conns | ||
400 | * list. If there are pending LE connection we start the background scanning, | ||
401 | * otherwise we stop it. | ||
402 | * | ||
403 | * This function requires the caller holds hdev->lock. | ||
404 | */ | ||
405 | void __hci_update_background_scan(struct hci_request *req) | ||
406 | { | ||
407 | struct hci_dev *hdev = req->hdev; | ||
408 | struct hci_conn *conn; | ||
409 | |||
410 | if (!test_bit(HCI_UP, &hdev->flags) || | ||
411 | test_bit(HCI_INIT, &hdev->flags) || | ||
412 | test_bit(HCI_SETUP, &hdev->dev_flags) || | ||
413 | test_bit(HCI_CONFIG, &hdev->dev_flags) || | ||
414 | test_bit(HCI_AUTO_OFF, &hdev->dev_flags) || | ||
415 | test_bit(HCI_UNREGISTER, &hdev->dev_flags)) | ||
416 | return; | ||
417 | |||
418 | /* No point in doing scanning if LE support hasn't been enabled */ | ||
419 | if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) | ||
420 | return; | ||
421 | |||
422 | /* If discovery is active don't interfere with it */ | ||
423 | if (hdev->discovery.state != DISCOVERY_STOPPED) | ||
424 | return; | ||
425 | |||
426 | /* Reset RSSI and UUID filters when starting background scanning | ||
427 | * since these filters are meant for service discovery only. | ||
428 | * | ||
429 | * The Start Discovery and Start Service Discovery operations | ||
430 | * ensure to set proper values for RSSI threshold and UUID | ||
431 | * filter list. So it is safe to just reset them here. | ||
432 | */ | ||
433 | hci_discovery_filter_clear(hdev); | ||
434 | |||
435 | if (list_empty(&hdev->pend_le_conns) && | ||
436 | list_empty(&hdev->pend_le_reports)) { | ||
437 | /* If there is no pending LE connections or devices | ||
438 | * to be scanned for, we should stop the background | ||
439 | * scanning. | ||
440 | */ | ||
441 | |||
442 | /* If controller is not scanning we are done. */ | ||
443 | if (!test_bit(HCI_LE_SCAN, &hdev->dev_flags)) | ||
444 | return; | ||
445 | |||
446 | hci_req_add_le_scan_disable(req); | ||
447 | |||
448 | BT_DBG("%s stopping background scanning", hdev->name); | ||
449 | } else { | ||
450 | /* If there is at least one pending LE connection, we should | ||
451 | * keep the background scan running. | ||
452 | */ | ||
453 | |||
454 | /* If controller is connecting, we should not start scanning | ||
455 | * since some controllers are not able to scan and connect at | ||
456 | * the same time. | ||
457 | */ | ||
458 | conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); | ||
459 | if (conn) | ||
460 | return; | ||
461 | |||
462 | /* If controller is currently scanning, we stop it to ensure we | ||
463 | * don't miss any advertising (due to duplicates filter). | ||
464 | */ | ||
465 | if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) | ||
466 | hci_req_add_le_scan_disable(req); | ||
467 | |||
468 | hci_req_add_le_passive_scan(req); | ||
469 | |||
470 | BT_DBG("%s starting background scanning", hdev->name); | ||
471 | } | ||
472 | } | ||
473 | |||
474 | static void update_background_scan_complete(struct hci_dev *hdev, u8 status) | ||
475 | { | ||
476 | if (status) | ||
477 | BT_DBG("HCI request failed to update background scanning: " | ||
478 | "status 0x%2.2x", status); | ||
479 | } | ||
480 | |||
481 | void hci_update_background_scan(struct hci_dev *hdev) | ||
482 | { | ||
483 | int err; | ||
484 | struct hci_request req; | ||
485 | |||
486 | hci_req_init(&req, hdev); | ||
487 | |||
488 | __hci_update_background_scan(&req); | ||
489 | |||
490 | err = hci_req_run(&req, update_background_scan_complete); | ||
491 | if (err && err != -ENODATA) | ||
492 | BT_ERR("Failed to run HCI request: err %d", err); | ||
493 | } | ||