1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Copyright (C) 2020 Google Corporation
4 */
5
6 #include <net/bluetooth/bluetooth.h>
7 #include <net/bluetooth/hci_core.h>
8 #include <net/bluetooth/mgmt.h>
9
10 #include "hci_request.h"
11 #include "mgmt_util.h"
12 #include "msft.h"
13
14 #define MSFT_RSSI_THRESHOLD_VALUE_MIN -127
15 #define MSFT_RSSI_THRESHOLD_VALUE_MAX 20
16 #define MSFT_RSSI_LOW_TIMEOUT_MAX 0x3C
17
18 #define MSFT_OP_READ_SUPPORTED_FEATURES 0x00
19 struct msft_cp_read_supported_features {
20 __u8 sub_opcode;
21 } __packed;
22
23 struct msft_rp_read_supported_features {
24 __u8 status;
25 __u8 sub_opcode;
26 __le64 features;
27 __u8 evt_prefix_len;
28 __u8 evt_prefix[];
29 } __packed;
30
31 #define MSFT_OP_LE_MONITOR_ADVERTISEMENT 0x03
32 #define MSFT_MONITOR_ADVERTISEMENT_TYPE_PATTERN 0x01
33 struct msft_le_monitor_advertisement_pattern {
34 __u8 length;
35 __u8 data_type;
36 __u8 start_byte;
37 __u8 pattern[];
38 };
39
40 struct msft_le_monitor_advertisement_pattern_data {
41 __u8 count;
42 __u8 data[];
43 };
44
45 struct msft_cp_le_monitor_advertisement {
46 __u8 sub_opcode;
47 __s8 rssi_high;
48 __s8 rssi_low;
49 __u8 rssi_low_interval;
50 __u8 rssi_sampling_period;
51 __u8 cond_type;
52 __u8 data[];
53 } __packed;
54
55 struct msft_rp_le_monitor_advertisement {
56 __u8 status;
57 __u8 sub_opcode;
58 __u8 handle;
59 } __packed;
60
61 #define MSFT_OP_LE_CANCEL_MONITOR_ADVERTISEMENT 0x04
62 struct msft_cp_le_cancel_monitor_advertisement {
63 __u8 sub_opcode;
64 __u8 handle;
65 } __packed;
66
67 struct msft_rp_le_cancel_monitor_advertisement {
68 __u8 status;
69 __u8 sub_opcode;
70 } __packed;
71
72 #define MSFT_OP_LE_SET_ADVERTISEMENT_FILTER_ENABLE 0x05
73 struct msft_cp_le_set_advertisement_filter_enable {
74 __u8 sub_opcode;
75 __u8 enable;
76 } __packed;
77
78 struct msft_rp_le_set_advertisement_filter_enable {
79 __u8 status;
80 __u8 sub_opcode;
81 } __packed;
82
83 struct msft_monitor_advertisement_handle_data {
84 __u8 msft_handle;
85 __u16 mgmt_handle;
86 struct list_head list;
87 };
88
89 struct msft_data {
90 __u64 features;
91 __u8 evt_prefix_len;
92 __u8 *evt_prefix;
93 struct list_head handle_map;
94 __u16 pending_add_handle;
95 __u16 pending_remove_handle;
96 __u8 reregistering;
97 __u8 suspending;
98 __u8 filter_enabled;
99 };
100
101 static int __msft_add_monitor_pattern(struct hci_dev *hdev,
102 struct adv_monitor *monitor);
103 static int __msft_remove_monitor(struct hci_dev *hdev,
104 struct adv_monitor *monitor, u16 handle);
105
msft_monitor_supported(struct hci_dev * hdev)106 bool msft_monitor_supported(struct hci_dev *hdev)
107 {
108 return !!(msft_get_features(hdev) & MSFT_FEATURE_MASK_LE_ADV_MONITOR);
109 }
110
read_supported_features(struct hci_dev * hdev,struct msft_data * msft)111 static bool read_supported_features(struct hci_dev *hdev,
112 struct msft_data *msft)
113 {
114 struct msft_cp_read_supported_features cp;
115 struct msft_rp_read_supported_features *rp;
116 struct sk_buff *skb;
117
118 cp.sub_opcode = MSFT_OP_READ_SUPPORTED_FEATURES;
119
120 skb = __hci_cmd_sync(hdev, hdev->msft_opcode, sizeof(cp), &cp,
121 HCI_CMD_TIMEOUT);
122 if (IS_ERR(skb)) {
123 bt_dev_err(hdev, "Failed to read MSFT supported features (%ld)",
124 PTR_ERR(skb));
125 return false;
126 }
127
128 if (skb->len < sizeof(*rp)) {
129 bt_dev_err(hdev, "MSFT supported features length mismatch");
130 goto failed;
131 }
132
133 rp = (struct msft_rp_read_supported_features *)skb->data;
134
135 if (rp->sub_opcode != MSFT_OP_READ_SUPPORTED_FEATURES)
136 goto failed;
137
138 if (rp->evt_prefix_len > 0) {
139 msft->evt_prefix = kmemdup(rp->evt_prefix, rp->evt_prefix_len,
140 GFP_KERNEL);
141 if (!msft->evt_prefix)
142 goto failed;
143 }
144
145 msft->evt_prefix_len = rp->evt_prefix_len;
146 msft->features = __le64_to_cpu(rp->features);
147
148 if (msft->features & MSFT_FEATURE_MASK_CURVE_VALIDITY)
149 hdev->msft_curve_validity = true;
150
151 kfree_skb(skb);
152 return true;
153
154 failed:
155 kfree_skb(skb);
156 return false;
157 }
158
159 /* This function requires the caller holds hdev->lock */
reregister_monitor(struct hci_dev * hdev,int handle)160 static void reregister_monitor(struct hci_dev *hdev, int handle)
161 {
162 struct adv_monitor *monitor;
163 struct msft_data *msft = hdev->msft_data;
164 int err;
165
166 while (1) {
167 monitor = idr_get_next(&hdev->adv_monitors_idr, &handle);
168 if (!monitor) {
169 /* All monitors have been reregistered */
170 msft->reregistering = false;
171 hci_update_background_scan(hdev);
172 return;
173 }
174
175 msft->pending_add_handle = (u16)handle;
176 err = __msft_add_monitor_pattern(hdev, monitor);
177
178 /* If success, we return and wait for monitor added callback */
179 if (!err)
180 return;
181
182 /* Otherwise remove the monitor and keep registering */
183 hci_free_adv_monitor(hdev, monitor);
184 handle++;
185 }
186 }
187
188 /* This function requires the caller holds hdev->lock */
remove_monitor_on_suspend(struct hci_dev * hdev,int handle)189 static void remove_monitor_on_suspend(struct hci_dev *hdev, int handle)
190 {
191 struct adv_monitor *monitor;
192 struct msft_data *msft = hdev->msft_data;
193 int err;
194
195 while (1) {
196 monitor = idr_get_next(&hdev->adv_monitors_idr, &handle);
197 if (!monitor) {
198 /* All monitors have been removed */
199 msft->suspending = false;
200 hci_update_background_scan(hdev);
201 return;
202 }
203
204 msft->pending_remove_handle = (u16)handle;
205 err = __msft_remove_monitor(hdev, monitor, handle);
206
207 /* If success, return and wait for monitor removed callback */
208 if (!err)
209 return;
210
211 /* Otherwise free the monitor and keep removing */
212 hci_free_adv_monitor(hdev, monitor);
213 handle++;
214 }
215 }
216
217 /* This function requires the caller holds hdev->lock */
msft_suspend(struct hci_dev * hdev)218 void msft_suspend(struct hci_dev *hdev)
219 {
220 struct msft_data *msft = hdev->msft_data;
221
222 if (!msft)
223 return;
224
225 if (msft_monitor_supported(hdev)) {
226 msft->suspending = true;
227 /* Quitely remove all monitors on suspend to avoid waking up
228 * the system.
229 */
230 remove_monitor_on_suspend(hdev, 0);
231 }
232 }
233
234 /* This function requires the caller holds hdev->lock */
msft_resume(struct hci_dev * hdev)235 void msft_resume(struct hci_dev *hdev)
236 {
237 struct msft_data *msft = hdev->msft_data;
238
239 if (!msft)
240 return;
241
242 if (msft_monitor_supported(hdev)) {
243 msft->reregistering = true;
244 /* Monitors are removed on suspend, so we need to add all
245 * monitors on resume.
246 */
247 reregister_monitor(hdev, 0);
248 }
249 }
250
msft_do_open(struct hci_dev * hdev)251 void msft_do_open(struct hci_dev *hdev)
252 {
253 struct msft_data *msft = hdev->msft_data;
254
255 if (hdev->msft_opcode == HCI_OP_NOP)
256 return;
257
258 if (!msft) {
259 bt_dev_err(hdev, "MSFT extension not registered");
260 return;
261 }
262
263 bt_dev_dbg(hdev, "Initialize MSFT extension");
264
265 /* Reset existing MSFT data before re-reading */
266 kfree(msft->evt_prefix);
267 msft->evt_prefix = NULL;
268 msft->evt_prefix_len = 0;
269 msft->features = 0;
270
271 if (!read_supported_features(hdev, msft)) {
272 hdev->msft_data = NULL;
273 kfree(msft);
274 return;
275 }
276
277 if (msft_monitor_supported(hdev)) {
278 msft->reregistering = true;
279 msft_set_filter_enable(hdev, true);
280 /* Monitors get removed on power off, so we need to explicitly
281 * tell the controller to re-monitor.
282 */
283 reregister_monitor(hdev, 0);
284 }
285 }
286
msft_do_close(struct hci_dev * hdev)287 void msft_do_close(struct hci_dev *hdev)
288 {
289 struct msft_data *msft = hdev->msft_data;
290 struct msft_monitor_advertisement_handle_data *handle_data, *tmp;
291 struct adv_monitor *monitor;
292
293 if (!msft)
294 return;
295
296 bt_dev_dbg(hdev, "Cleanup of MSFT extension");
297
298 /* The controller will silently remove all monitors on power off.
299 * Therefore, remove handle_data mapping and reset monitor state.
300 */
301 list_for_each_entry_safe(handle_data, tmp, &msft->handle_map, list) {
302 monitor = idr_find(&hdev->adv_monitors_idr,
303 handle_data->mgmt_handle);
304
305 if (monitor && monitor->state == ADV_MONITOR_STATE_OFFLOADED)
306 monitor->state = ADV_MONITOR_STATE_REGISTERED;
307
308 list_del(&handle_data->list);
309 kfree(handle_data);
310 }
311 }
312
msft_register(struct hci_dev * hdev)313 void msft_register(struct hci_dev *hdev)
314 {
315 struct msft_data *msft = NULL;
316
317 bt_dev_dbg(hdev, "Register MSFT extension");
318
319 msft = kzalloc(sizeof(*msft), GFP_KERNEL);
320 if (!msft) {
321 bt_dev_err(hdev, "Failed to register MSFT extension");
322 return;
323 }
324
325 INIT_LIST_HEAD(&msft->handle_map);
326 hdev->msft_data = msft;
327 }
328
msft_unregister(struct hci_dev * hdev)329 void msft_unregister(struct hci_dev *hdev)
330 {
331 struct msft_data *msft = hdev->msft_data;
332
333 if (!msft)
334 return;
335
336 bt_dev_dbg(hdev, "Unregister MSFT extension");
337
338 hdev->msft_data = NULL;
339
340 kfree(msft->evt_prefix);
341 kfree(msft);
342 }
343
msft_vendor_evt(struct hci_dev * hdev,struct sk_buff * skb)344 void msft_vendor_evt(struct hci_dev *hdev, struct sk_buff *skb)
345 {
346 struct msft_data *msft = hdev->msft_data;
347 u8 event;
348
349 if (!msft)
350 return;
351
352 /* When the extension has defined an event prefix, check that it
353 * matches, and otherwise just return.
354 */
355 if (msft->evt_prefix_len > 0) {
356 if (skb->len < msft->evt_prefix_len)
357 return;
358
359 if (memcmp(skb->data, msft->evt_prefix, msft->evt_prefix_len))
360 return;
361
362 skb_pull(skb, msft->evt_prefix_len);
363 }
364
365 /* Every event starts at least with an event code and the rest of
366 * the data is variable and depends on the event code.
367 */
368 if (skb->len < 1)
369 return;
370
371 event = *skb->data;
372 skb_pull(skb, 1);
373
374 bt_dev_dbg(hdev, "MSFT vendor event %u", event);
375 }
376
msft_get_features(struct hci_dev * hdev)377 __u64 msft_get_features(struct hci_dev *hdev)
378 {
379 struct msft_data *msft = hdev->msft_data;
380
381 return msft ? msft->features : 0;
382 }
383
384 /* is_mgmt = true matches the handle exposed to userspace via mgmt.
385 * is_mgmt = false matches the handle used by the msft controller.
386 * This function requires the caller holds hdev->lock
387 */
msft_find_handle_data(struct hci_dev * hdev,u16 handle,bool is_mgmt)388 static struct msft_monitor_advertisement_handle_data *msft_find_handle_data
389 (struct hci_dev *hdev, u16 handle, bool is_mgmt)
390 {
391 struct msft_monitor_advertisement_handle_data *entry;
392 struct msft_data *msft = hdev->msft_data;
393
394 list_for_each_entry(entry, &msft->handle_map, list) {
395 if (is_mgmt && entry->mgmt_handle == handle)
396 return entry;
397 if (!is_mgmt && entry->msft_handle == handle)
398 return entry;
399 }
400
401 return NULL;
402 }
403
msft_le_monitor_advertisement_cb(struct hci_dev * hdev,u8 status,u16 opcode,struct sk_buff * skb)404 static void msft_le_monitor_advertisement_cb(struct hci_dev *hdev,
405 u8 status, u16 opcode,
406 struct sk_buff *skb)
407 {
408 struct msft_rp_le_monitor_advertisement *rp;
409 struct adv_monitor *monitor;
410 struct msft_monitor_advertisement_handle_data *handle_data;
411 struct msft_data *msft = hdev->msft_data;
412
413 hci_dev_lock(hdev);
414
415 monitor = idr_find(&hdev->adv_monitors_idr, msft->pending_add_handle);
416 if (!monitor) {
417 bt_dev_err(hdev, "msft add advmon: monitor %u is not found!",
418 msft->pending_add_handle);
419 status = HCI_ERROR_UNSPECIFIED;
420 goto unlock;
421 }
422
423 if (status)
424 goto unlock;
425
426 rp = (struct msft_rp_le_monitor_advertisement *)skb->data;
427 if (skb->len < sizeof(*rp)) {
428 status = HCI_ERROR_UNSPECIFIED;
429 goto unlock;
430 }
431
432 handle_data = kmalloc(sizeof(*handle_data), GFP_KERNEL);
433 if (!handle_data) {
434 status = HCI_ERROR_UNSPECIFIED;
435 goto unlock;
436 }
437
438 handle_data->mgmt_handle = monitor->handle;
439 handle_data->msft_handle = rp->handle;
440 INIT_LIST_HEAD(&handle_data->list);
441 list_add(&handle_data->list, &msft->handle_map);
442
443 monitor->state = ADV_MONITOR_STATE_OFFLOADED;
444
445 unlock:
446 if (status && monitor)
447 hci_free_adv_monitor(hdev, monitor);
448
449 /* If in restart/reregister sequence, keep registering. */
450 if (msft->reregistering)
451 reregister_monitor(hdev, msft->pending_add_handle + 1);
452
453 hci_dev_unlock(hdev);
454
455 if (!msft->reregistering)
456 hci_add_adv_patterns_monitor_complete(hdev, status);
457 }
458
msft_le_cancel_monitor_advertisement_cb(struct hci_dev * hdev,u8 status,u16 opcode,struct sk_buff * skb)459 static void msft_le_cancel_monitor_advertisement_cb(struct hci_dev *hdev,
460 u8 status, u16 opcode,
461 struct sk_buff *skb)
462 {
463 struct msft_cp_le_cancel_monitor_advertisement *cp;
464 struct msft_rp_le_cancel_monitor_advertisement *rp;
465 struct adv_monitor *monitor;
466 struct msft_monitor_advertisement_handle_data *handle_data;
467 struct msft_data *msft = hdev->msft_data;
468 int err;
469 bool pending;
470
471 if (status)
472 goto done;
473
474 rp = (struct msft_rp_le_cancel_monitor_advertisement *)skb->data;
475 if (skb->len < sizeof(*rp)) {
476 status = HCI_ERROR_UNSPECIFIED;
477 goto done;
478 }
479
480 hci_dev_lock(hdev);
481
482 cp = hci_sent_cmd_data(hdev, hdev->msft_opcode);
483 handle_data = msft_find_handle_data(hdev, cp->handle, false);
484
485 if (handle_data) {
486 monitor = idr_find(&hdev->adv_monitors_idr,
487 handle_data->mgmt_handle);
488
489 if (monitor && monitor->state == ADV_MONITOR_STATE_OFFLOADED)
490 monitor->state = ADV_MONITOR_STATE_REGISTERED;
491
492 /* Do not free the monitor if it is being removed due to
493 * suspend. It will be re-monitored on resume.
494 */
495 if (monitor && !msft->suspending)
496 hci_free_adv_monitor(hdev, monitor);
497
498 list_del(&handle_data->list);
499 kfree(handle_data);
500 }
501
502 /* If in suspend/remove sequence, keep removing. */
503 if (msft->suspending)
504 remove_monitor_on_suspend(hdev,
505 msft->pending_remove_handle + 1);
506
507 /* If remove all monitors is required, we need to continue the process
508 * here because the earlier it was paused when waiting for the
509 * response from controller.
510 */
511 if (msft->pending_remove_handle == 0) {
512 pending = hci_remove_all_adv_monitor(hdev, &err);
513 if (pending) {
514 hci_dev_unlock(hdev);
515 return;
516 }
517
518 if (err)
519 status = HCI_ERROR_UNSPECIFIED;
520 }
521
522 hci_dev_unlock(hdev);
523
524 done:
525 if (!msft->suspending)
526 hci_remove_adv_monitor_complete(hdev, status);
527 }
528
msft_le_set_advertisement_filter_enable_cb(struct hci_dev * hdev,u8 status,u16 opcode,struct sk_buff * skb)529 static void msft_le_set_advertisement_filter_enable_cb(struct hci_dev *hdev,
530 u8 status, u16 opcode,
531 struct sk_buff *skb)
532 {
533 struct msft_cp_le_set_advertisement_filter_enable *cp;
534 struct msft_rp_le_set_advertisement_filter_enable *rp;
535 struct msft_data *msft = hdev->msft_data;
536
537 rp = (struct msft_rp_le_set_advertisement_filter_enable *)skb->data;
538 if (skb->len < sizeof(*rp))
539 return;
540
541 /* Error 0x0C would be returned if the filter enabled status is
542 * already set to whatever we were trying to set.
543 * Although the default state should be disabled, some controller set
544 * the initial value to enabled. Because there is no way to know the
545 * actual initial value before sending this command, here we also treat
546 * error 0x0C as success.
547 */
548 if (status != 0x00 && status != 0x0C)
549 return;
550
551 hci_dev_lock(hdev);
552
553 cp = hci_sent_cmd_data(hdev, hdev->msft_opcode);
554 msft->filter_enabled = cp->enable;
555
556 if (status == 0x0C)
557 bt_dev_warn(hdev, "MSFT filter_enable is already %s",
558 cp->enable ? "on" : "off");
559
560 hci_dev_unlock(hdev);
561 }
562
msft_monitor_rssi_valid(struct adv_monitor * monitor)563 static bool msft_monitor_rssi_valid(struct adv_monitor *monitor)
564 {
565 struct adv_rssi_thresholds *r = &monitor->rssi;
566
567 if (r->high_threshold < MSFT_RSSI_THRESHOLD_VALUE_MIN ||
568 r->high_threshold > MSFT_RSSI_THRESHOLD_VALUE_MAX ||
569 r->low_threshold < MSFT_RSSI_THRESHOLD_VALUE_MIN ||
570 r->low_threshold > MSFT_RSSI_THRESHOLD_VALUE_MAX)
571 return false;
572
573 /* High_threshold_timeout is not supported,
574 * once high_threshold is reached, events are immediately reported.
575 */
576 if (r->high_threshold_timeout != 0)
577 return false;
578
579 if (r->low_threshold_timeout > MSFT_RSSI_LOW_TIMEOUT_MAX)
580 return false;
581
582 /* Sampling period from 0x00 to 0xFF are all allowed */
583 return true;
584 }
585
msft_monitor_pattern_valid(struct adv_monitor * monitor)586 static bool msft_monitor_pattern_valid(struct adv_monitor *monitor)
587 {
588 return msft_monitor_rssi_valid(monitor);
589 /* No additional check needed for pattern-based monitor */
590 }
591
592 /* This function requires the caller holds hdev->lock */
__msft_add_monitor_pattern(struct hci_dev * hdev,struct adv_monitor * monitor)593 static int __msft_add_monitor_pattern(struct hci_dev *hdev,
594 struct adv_monitor *monitor)
595 {
596 struct msft_cp_le_monitor_advertisement *cp;
597 struct msft_le_monitor_advertisement_pattern_data *pattern_data;
598 struct msft_le_monitor_advertisement_pattern *pattern;
599 struct adv_pattern *entry;
600 struct hci_request req;
601 struct msft_data *msft = hdev->msft_data;
602 size_t total_size = sizeof(*cp) + sizeof(*pattern_data);
603 ptrdiff_t offset = 0;
604 u8 pattern_count = 0;
605 int err = 0;
606
607 if (!msft_monitor_pattern_valid(monitor))
608 return -EINVAL;
609
610 list_for_each_entry(entry, &monitor->patterns, list) {
611 pattern_count++;
612 total_size += sizeof(*pattern) + entry->length;
613 }
614
615 cp = kmalloc(total_size, GFP_KERNEL);
616 if (!cp)
617 return -ENOMEM;
618
619 cp->sub_opcode = MSFT_OP_LE_MONITOR_ADVERTISEMENT;
620 cp->rssi_high = monitor->rssi.high_threshold;
621 cp->rssi_low = monitor->rssi.low_threshold;
622 cp->rssi_low_interval = (u8)monitor->rssi.low_threshold_timeout;
623 cp->rssi_sampling_period = monitor->rssi.sampling_period;
624
625 cp->cond_type = MSFT_MONITOR_ADVERTISEMENT_TYPE_PATTERN;
626
627 pattern_data = (void *)cp->data;
628 pattern_data->count = pattern_count;
629
630 list_for_each_entry(entry, &monitor->patterns, list) {
631 pattern = (void *)(pattern_data->data + offset);
632 /* the length also includes data_type and offset */
633 pattern->length = entry->length + 2;
634 pattern->data_type = entry->ad_type;
635 pattern->start_byte = entry->offset;
636 memcpy(pattern->pattern, entry->value, entry->length);
637 offset += sizeof(*pattern) + entry->length;
638 }
639
640 hci_req_init(&req, hdev);
641 hci_req_add(&req, hdev->msft_opcode, total_size, cp);
642 err = hci_req_run_skb(&req, msft_le_monitor_advertisement_cb);
643 kfree(cp);
644
645 if (!err)
646 msft->pending_add_handle = monitor->handle;
647
648 return err;
649 }
650
651 /* This function requires the caller holds hdev->lock */
msft_add_monitor_pattern(struct hci_dev * hdev,struct adv_monitor * monitor)652 int msft_add_monitor_pattern(struct hci_dev *hdev, struct adv_monitor *monitor)
653 {
654 struct msft_data *msft = hdev->msft_data;
655
656 if (!msft)
657 return -EOPNOTSUPP;
658
659 if (msft->reregistering || msft->suspending)
660 return -EBUSY;
661
662 return __msft_add_monitor_pattern(hdev, monitor);
663 }
664
665 /* This function requires the caller holds hdev->lock */
__msft_remove_monitor(struct hci_dev * hdev,struct adv_monitor * monitor,u16 handle)666 static int __msft_remove_monitor(struct hci_dev *hdev,
667 struct adv_monitor *monitor, u16 handle)
668 {
669 struct msft_cp_le_cancel_monitor_advertisement cp;
670 struct msft_monitor_advertisement_handle_data *handle_data;
671 struct hci_request req;
672 struct msft_data *msft = hdev->msft_data;
673 int err = 0;
674
675 handle_data = msft_find_handle_data(hdev, monitor->handle, true);
676
677 /* If no matched handle, just remove without telling controller */
678 if (!handle_data)
679 return -ENOENT;
680
681 cp.sub_opcode = MSFT_OP_LE_CANCEL_MONITOR_ADVERTISEMENT;
682 cp.handle = handle_data->msft_handle;
683
684 hci_req_init(&req, hdev);
685 hci_req_add(&req, hdev->msft_opcode, sizeof(cp), &cp);
686 err = hci_req_run_skb(&req, msft_le_cancel_monitor_advertisement_cb);
687
688 if (!err)
689 msft->pending_remove_handle = handle;
690
691 return err;
692 }
693
694 /* This function requires the caller holds hdev->lock */
msft_remove_monitor(struct hci_dev * hdev,struct adv_monitor * monitor,u16 handle)695 int msft_remove_monitor(struct hci_dev *hdev, struct adv_monitor *monitor,
696 u16 handle)
697 {
698 struct msft_data *msft = hdev->msft_data;
699
700 if (!msft)
701 return -EOPNOTSUPP;
702
703 if (msft->reregistering || msft->suspending)
704 return -EBUSY;
705
706 return __msft_remove_monitor(hdev, monitor, handle);
707 }
708
msft_req_add_set_filter_enable(struct hci_request * req,bool enable)709 void msft_req_add_set_filter_enable(struct hci_request *req, bool enable)
710 {
711 struct hci_dev *hdev = req->hdev;
712 struct msft_cp_le_set_advertisement_filter_enable cp;
713
714 cp.sub_opcode = MSFT_OP_LE_SET_ADVERTISEMENT_FILTER_ENABLE;
715 cp.enable = enable;
716
717 hci_req_add(req, hdev->msft_opcode, sizeof(cp), &cp);
718 }
719
msft_set_filter_enable(struct hci_dev * hdev,bool enable)720 int msft_set_filter_enable(struct hci_dev *hdev, bool enable)
721 {
722 struct hci_request req;
723 struct msft_data *msft = hdev->msft_data;
724 int err;
725
726 if (!msft)
727 return -EOPNOTSUPP;
728
729 hci_req_init(&req, hdev);
730 msft_req_add_set_filter_enable(&req, enable);
731 err = hci_req_run_skb(&req, msft_le_set_advertisement_filter_enable_cb);
732
733 return err;
734 }
735
msft_curve_validity(struct hci_dev * hdev)736 bool msft_curve_validity(struct hci_dev *hdev)
737 {
738 return hdev->msft_curve_validity;
739 }
740