hci_dev_unlock(hdev);
}
+static void hci_cc_set_event_filter(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ __u8 status = *((__u8 *)skb->data);
+ struct hci_cp_set_event_filter *cp;
+ void *sent;
+
+ BT_DBG("%s status 0x%2.2x", hdev->name, status);
+
+ if (status)
+ return;
+
+ sent = hci_sent_cmd_data(hdev, HCI_OP_SET_EVENT_FLT);
+ if (!sent)
+ return;
+
+ cp = (struct hci_cp_set_event_filter *)sent;
+
+ if (cp->flt_type == HCI_FLT_CLEAR_ALL)
+ hci_dev_clear_flag(hdev, HCI_EVENT_FILTER_CONFIGURED);
+ else
+ hci_dev_set_flag(hdev, HCI_EVENT_FILTER_CONFIGURED);
+}
+
static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
hci_cc_write_scan_enable(hdev, skb);
break;
+ case HCI_OP_SET_EVENT_FLT:
+ hci_cc_set_event_filter(hdev, skb);
+ break;
+
case HCI_OP_READ_CLASS_OF_DEV:
hci_cc_read_class_of_dev(hdev, skb);
break;
{
struct hci_cp_set_event_filter f;
- memset(&f, 0, sizeof(f));
- f.flt_type = HCI_FLT_CLEAR_ALL;
- hci_req_add(req, HCI_OP_SET_EVENT_FLT, 1, &f);
+ if (!hci_dev_test_flag(req->hdev, HCI_BREDR_ENABLED))
+ return;
- /* Update page scan state (since we may have modified it when setting
- * the event filter).
- */
- __hci_req_update_scan(req);
+ if (hci_dev_test_flag(req->hdev, HCI_EVENT_FILTER_CONFIGURED)) {
+ memset(&f, 0, sizeof(f));
+ f.flt_type = HCI_FLT_CLEAR_ALL;
+ hci_req_add(req, HCI_OP_SET_EVENT_FLT, 1, &f);
+ }
}
static void hci_req_set_event_filter(struct hci_request *req)
struct hci_cp_set_event_filter f;
struct hci_dev *hdev = req->hdev;
u8 scan = SCAN_DISABLED;
+ bool scanning = test_bit(HCI_PSCAN, &hdev->flags);
+
+ if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
+ return;
/* Always clear event filter when starting */
hci_req_clear_event_filter(req);
scan = SCAN_PAGE;
}
- if (scan)
+ if (scan && !scanning) {
set_bit(SUSPEND_SCAN_ENABLE, hdev->suspend_tasks);
- else
+ hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
+ } else if (!scan && scanning) {
set_bit(SUSPEND_SCAN_DISABLE, hdev->suspend_tasks);
-
- hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
+ hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
+ }
}
static void cancel_adv_timeout(struct hci_dev *hdev)
hdev->advertising_paused = true;
hdev->advertising_old_state = old_state;
- /* Disable page scan */
- page_scan = SCAN_DISABLED;
- hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &page_scan);
+
+ /* Disable page scan if enabled */
+ if (test_bit(HCI_PSCAN, &hdev->flags)) {
+ page_scan = SCAN_DISABLED;
+ hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1,
+ &page_scan);
+ set_bit(SUSPEND_SCAN_DISABLE, hdev->suspend_tasks);
+ }
/* Disable LE passive scan if enabled */
if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) {
/* Disable advertisement filters */
hci_req_add_set_adv_filter_enable(&req, false);
- /* Mark task needing completion */
- set_bit(SUSPEND_SCAN_DISABLE, hdev->suspend_tasks);
-
/* Prevent disconnects from causing scanning to be re-enabled */
hdev->scanning_paused = true;
hdev->suspended = false;
hdev->scanning_paused = false;
+ /* Clear any event filters and restore scan state */
hci_req_clear_event_filter(&req);
+ __hci_req_update_scan(&req);
+
/* Reset passive/background scanning to normal */
__hci_update_background_scan(&req);
/* Enable all of the advertisement filters */