Lines Matching +full:vendor +full:- +full:extension

1 // SPDX-License-Identifier: GPL-2.0-only
13 #define MSFT_RSSI_THRESHOLD_VALUE_MIN -127
150 skb = __hci_cmd_sync(hdev, hdev->msft_opcode, sizeof(cp), &cp, in read_supported_features()
158 if (skb->len < sizeof(*rp)) { in read_supported_features()
163 rp = (struct msft_rp_read_supported_features *)skb->data; in read_supported_features()
165 if (rp->sub_opcode != MSFT_OP_READ_SUPPORTED_FEATURES) in read_supported_features()
168 if (rp->evt_prefix_len > 0) { in read_supported_features()
169 msft->evt_prefix = kmemdup(rp->evt_prefix, rp->evt_prefix_len, in read_supported_features()
171 if (!msft->evt_prefix) in read_supported_features()
175 msft->evt_prefix_len = rp->evt_prefix_len; in read_supported_features()
176 msft->features = __le64_to_cpu(rp->features); in read_supported_features()
178 if (msft->features & MSFT_FEATURE_MASK_CURVE_VALIDITY) in read_supported_features()
179 hdev->msft_curve_validity = true; in read_supported_features()
191 * This function requires the caller holds hdev->lock
197 struct msft_data *msft = hdev->msft_data; in msft_find_handle_data()
199 list_for_each_entry(entry, &msft->handle_map, list) { in msft_find_handle_data()
200 if (is_mgmt && entry->mgmt_handle == handle) in msft_find_handle_data()
202 if (!is_mgmt && entry->msft_handle == handle) in msft_find_handle_data()
209 /* This function requires the caller holds msft->filter_lock */
215 struct msft_data *msft = hdev->msft_data; in msft_find_address_data()
217 list_for_each_entry(entry, &msft->address_filters, list) { in msft_find_address_data()
218 if (entry->pattern_handle == pattern_handle && in msft_find_address_data()
219 addr_type == entry->addr_type && in msft_find_address_data()
220 !bacmp(addr, &entry->bdaddr)) in msft_find_address_data()
227 /* This function requires the caller holds hdev->lock */
235 list_for_each_entry_safe(dev, tmp, &hdev->monitored_devices, list) { in msft_monitor_device_del()
240 if ((!mgmt_handle || dev->handle == mgmt_handle) && in msft_monitor_device_del()
241 (!bdaddr || (!bacmp(bdaddr, &dev->bdaddr) && in msft_monitor_device_del()
242 addr_type == dev->addr_type))) { in msft_monitor_device_del()
243 if (notify && dev->notified) { in msft_monitor_device_del()
244 mgmt_adv_monitor_device_lost(hdev, dev->handle, in msft_monitor_device_del()
245 &dev->bdaddr, in msft_monitor_device_del()
246 dev->addr_type); in msft_monitor_device_del()
249 list_del(&dev->list); in msft_monitor_device_del()
264 struct msft_data *msft = hdev->msft_data; in msft_le_monitor_advertisement_cb()
269 rp = (struct msft_rp_le_monitor_advertisement *)skb->data; in msft_le_monitor_advertisement_cb()
270 if (skb->len < sizeof(*rp)) { in msft_le_monitor_advertisement_cb()
275 status = rp->status; in msft_le_monitor_advertisement_cb()
285 handle_data->mgmt_handle = monitor->handle; in msft_le_monitor_advertisement_cb()
286 handle_data->msft_handle = rp->handle; in msft_le_monitor_advertisement_cb()
287 handle_data->cond_type = MSFT_MONITOR_ADVERTISEMENT_TYPE_PATTERN; in msft_le_monitor_advertisement_cb()
288 INIT_LIST_HEAD(&handle_data->list); in msft_le_monitor_advertisement_cb()
289 list_add(&handle_data->list, &msft->handle_map); in msft_le_monitor_advertisement_cb()
291 monitor->state = ADV_MONITOR_STATE_OFFLOADED; in msft_le_monitor_advertisement_cb()
307 struct msft_data *msft = hdev->msft_data; in msft_remove_addr_filters_sync()
314 mutex_lock(&msft->filter_lock); in msft_remove_addr_filters_sync()
316 list_for_each_entry_safe(address_filter, n, &msft->address_filters, in msft_remove_addr_filters_sync()
318 if (address_filter->pattern_handle != handle) in msft_remove_addr_filters_sync()
321 list_del(&address_filter->list); in msft_remove_addr_filters_sync()
327 if (address_filter->state == AF_STATE_ADDING) { in msft_remove_addr_filters_sync()
328 address_filter->state = AF_STATE_REMOVING; in msft_remove_addr_filters_sync()
336 if (address_filter->state == AF_STATE_REMOVING) in msft_remove_addr_filters_sync()
339 list_add_tail(&address_filter->list, &head); in msft_remove_addr_filters_sync()
342 mutex_unlock(&msft->filter_lock); in msft_remove_addr_filters_sync()
345 list_del(&address_filter->list); in msft_remove_addr_filters_sync()
348 cp.handle = address_filter->msft_handle; in msft_remove_addr_filters_sync()
350 skb = __hci_cmd_sync(hdev, hdev->msft_opcode, sizeof(cp), &cp, in msft_remove_addr_filters_sync()
360 &address_filter->bdaddr); in msft_remove_addr_filters_sync()
373 struct msft_data *msft = hdev->msft_data; in msft_le_cancel_monitor_advertisement_cb()
377 rp = (struct msft_rp_le_cancel_monitor_advertisement *)skb->data; in msft_le_cancel_monitor_advertisement_cb()
378 if (skb->len < sizeof(*rp)) { in msft_le_cancel_monitor_advertisement_cb()
383 status = rp->status; in msft_le_cancel_monitor_advertisement_cb()
389 handle_data = msft_find_handle_data(hdev, monitor->handle, true); in msft_le_cancel_monitor_advertisement_cb()
392 if (monitor->state == ADV_MONITOR_STATE_OFFLOADED) in msft_le_cancel_monitor_advertisement_cb()
393 monitor->state = ADV_MONITOR_STATE_REGISTERED; in msft_le_cancel_monitor_advertisement_cb()
396 * suspend. It will be re-monitored on resume. in msft_le_cancel_monitor_advertisement_cb()
398 if (!msft->suspending) { in msft_le_cancel_monitor_advertisement_cb()
402 msft_monitor_device_del(hdev, handle_data->mgmt_handle, in msft_le_cancel_monitor_advertisement_cb()
406 msft_handle = handle_data->msft_handle; in msft_le_cancel_monitor_advertisement_cb()
408 list_del(&handle_data->list); in msft_le_cancel_monitor_advertisement_cb()
430 handle_data = msft_find_handle_data(hdev, monitor->handle, true); in msft_remove_monitor_sync()
434 return -ENOENT; in msft_remove_monitor_sync()
437 cp.handle = handle_data->msft_handle; in msft_remove_monitor_sync()
439 skb = __hci_cmd_sync(hdev, hdev->msft_opcode, sizeof(cp), &cp, in msft_remove_monitor_sync()
444 return msft_le_cancel_monitor_advertisement_cb(hdev, hdev->msft_opcode, in msft_remove_monitor_sync()
451 struct msft_data *msft = hdev->msft_data; in msft_suspend_sync()
458 msft->suspending = true; in msft_suspend_sync()
461 monitor = idr_get_next(&hdev->adv_monitors_idr, &handle); in msft_suspend_sync()
471 msft->suspending = false; in msft_suspend_sync()
478 struct adv_rssi_thresholds *r = &monitor->rssi; in msft_monitor_rssi_valid()
480 if (r->high_threshold < MSFT_RSSI_THRESHOLD_VALUE_MIN || in msft_monitor_rssi_valid()
481 r->high_threshold > MSFT_RSSI_THRESHOLD_VALUE_MAX || in msft_monitor_rssi_valid()
482 r->low_threshold < MSFT_RSSI_THRESHOLD_VALUE_MIN || in msft_monitor_rssi_valid()
483 r->low_threshold > MSFT_RSSI_THRESHOLD_VALUE_MAX) in msft_monitor_rssi_valid()
489 if (r->high_threshold_timeout != 0) in msft_monitor_rssi_valid()
492 if (r->low_threshold_timeout > MSFT_RSSI_LOW_TIMEOUT_MAX) in msft_monitor_rssi_valid()
502 /* No additional check needed for pattern-based monitor */ in msft_monitor_pattern_valid()
520 return -EINVAL; in msft_add_monitor_sync()
522 list_for_each_entry(entry, &monitor->patterns, list) { in msft_add_monitor_sync()
524 total_size += sizeof(*pattern) + entry->length; in msft_add_monitor_sync()
529 return -ENOMEM; in msft_add_monitor_sync()
531 cp->sub_opcode = MSFT_OP_LE_MONITOR_ADVERTISEMENT; in msft_add_monitor_sync()
532 cp->rssi_high = monitor->rssi.high_threshold; in msft_add_monitor_sync()
533 cp->rssi_low = monitor->rssi.low_threshold; in msft_add_monitor_sync()
534 cp->rssi_low_interval = (u8)monitor->rssi.low_threshold_timeout; in msft_add_monitor_sync()
535 cp->rssi_sampling_period = monitor->rssi.sampling_period; in msft_add_monitor_sync()
537 cp->cond_type = MSFT_MONITOR_ADVERTISEMENT_TYPE_PATTERN; in msft_add_monitor_sync()
539 pattern_data = (void *)cp->data; in msft_add_monitor_sync()
540 pattern_data->count = pattern_count; in msft_add_monitor_sync()
542 list_for_each_entry(entry, &monitor->patterns, list) { in msft_add_monitor_sync()
543 pattern = (void *)(pattern_data->data + offset); in msft_add_monitor_sync()
545 pattern->length = entry->length + 2; in msft_add_monitor_sync()
546 pattern->data_type = entry->ad_type; in msft_add_monitor_sync()
547 pattern->start_byte = entry->offset; in msft_add_monitor_sync()
548 memcpy(pattern->pattern, entry->value, entry->length); in msft_add_monitor_sync()
549 offset += sizeof(*pattern) + entry->length; in msft_add_monitor_sync()
552 skb = __hci_cmd_sync(hdev, hdev->msft_opcode, total_size, cp, in msft_add_monitor_sync()
560 err = msft_le_monitor_advertisement_cb(hdev, hdev->msft_opcode, in msft_add_monitor_sync()
565 handle_data = msft_find_handle_data(hdev, monitor->handle, true); in msft_add_monitor_sync()
567 err = -ENODATA; in msft_add_monitor_sync()
571 handle_data->rssi_high = cp->rssi_high; in msft_add_monitor_sync()
572 handle_data->rssi_low = cp->rssi_low; in msft_add_monitor_sync()
573 handle_data->rssi_low_interval = cp->rssi_low_interval; in msft_add_monitor_sync()
574 handle_data->rssi_sampling_period = cp->rssi_sampling_period; in msft_add_monitor_sync()
585 struct msft_data *msft = hdev->msft_data; in reregister_monitor()
591 msft->resuming = true; in reregister_monitor()
594 monitor = idr_get_next(&hdev->adv_monitors_idr, &handle); in reregister_monitor()
604 msft->resuming = false; in reregister_monitor()
610 struct msft_data *msft = hdev->msft_data; in msft_resume_sync()
620 hdev->advmon_pend_notify = false; in msft_resume_sync()
633 struct msft_data *msft = hdev->msft_data; in msft_do_open()
635 if (hdev->msft_opcode == HCI_OP_NOP) in msft_do_open()
639 bt_dev_err(hdev, "MSFT extension not registered"); in msft_do_open()
643 bt_dev_dbg(hdev, "Initialize MSFT extension"); in msft_do_open()
645 /* Reset existing MSFT data before re-reading */ in msft_do_open()
646 kfree(msft->evt_prefix); in msft_do_open()
647 msft->evt_prefix = NULL; in msft_do_open()
648 msft->evt_prefix_len = 0; in msft_do_open()
649 msft->features = 0; in msft_do_open()
652 hdev->msft_data = NULL; in msft_do_open()
658 msft->resuming = true; in msft_do_open()
661 * tell the controller to re-monitor. in msft_do_open()
669 struct msft_data *msft = hdev->msft_data; in msft_do_close()
677 bt_dev_dbg(hdev, "Cleanup of MSFT extension"); in msft_do_close()
682 list_for_each_entry_safe(handle_data, tmp, &msft->handle_map, list) { in msft_do_close()
683 monitor = idr_find(&hdev->adv_monitors_idr, in msft_do_close()
684 handle_data->mgmt_handle); in msft_do_close()
686 if (monitor && monitor->state == ADV_MONITOR_STATE_OFFLOADED) in msft_do_close()
687 monitor->state = ADV_MONITOR_STATE_REGISTERED; in msft_do_close()
689 list_del(&handle_data->list); in msft_do_close()
693 mutex_lock(&msft->filter_lock); in msft_do_close()
694 list_for_each_entry_safe(address_filter, n, &msft->address_filters, in msft_do_close()
696 list_del(&address_filter->list); in msft_do_close()
699 mutex_unlock(&msft->filter_lock); in msft_do_close()
704 hdev->advmon_pend_notify = false; in msft_do_close()
714 struct msft_data *msft = hdev->msft_data; in msft_cancel_address_filter_sync()
720 return -EINVAL; in msft_cancel_address_filter_sync()
724 if (!test_bit(HCI_UP, &hdev->flags)) in msft_cancel_address_filter_sync()
727 mutex_lock(&msft->filter_lock); in msft_cancel_address_filter_sync()
728 list_del(&address_filter->list); in msft_cancel_address_filter_sync()
729 mutex_unlock(&msft->filter_lock); in msft_cancel_address_filter_sync()
732 cp.handle = address_filter->msft_handle; in msft_cancel_address_filter_sync()
734 skb = __hci_cmd_sync(hdev, hdev->msft_opcode, sizeof(cp), &cp, in msft_cancel_address_filter_sync()
738 &address_filter->bdaddr); in msft_cancel_address_filter_sync()
745 &address_filter->bdaddr); in msft_cancel_address_filter_sync()
757 bt_dev_dbg(hdev, "Register MSFT extension"); in msft_register()
761 bt_dev_err(hdev, "Failed to register MSFT extension"); in msft_register()
765 INIT_LIST_HEAD(&msft->handle_map); in msft_register()
766 INIT_LIST_HEAD(&msft->address_filters); in msft_register()
767 hdev->msft_data = msft; in msft_register()
768 mutex_init(&msft->filter_lock); in msft_register()
773 struct msft_data *msft = hdev->msft_data; in msft_release()
778 bt_dev_dbg(hdev, "Unregister MSFT extension"); in msft_release()
780 hdev->msft_data = NULL; in msft_release()
782 kfree(msft->evt_prefix); in msft_release()
783 mutex_destroy(&msft->filter_lock); in msft_release()
787 /* This function requires the caller holds hdev->lock */
795 bt_dev_err(hdev, "MSFT vendor event %u: no memory", in msft_device_found()
800 bacpy(&dev->bdaddr, bdaddr); in msft_device_found()
801 dev->addr_type = addr_type; in msft_device_found()
802 dev->handle = mgmt_handle; in msft_device_found()
803 dev->notified = false; in msft_device_found()
805 INIT_LIST_HEAD(&dev->list); in msft_device_found()
806 list_add(&dev->list, &hdev->monitored_devices); in msft_device_found()
807 hdev->advmon_pend_notify = true; in msft_device_found()
810 /* This function requires the caller holds hdev->lock */
816 bt_dev_err(hdev, "MSFT vendor event %u: dev %pMR not in list", in msft_device_lost()
828 bt_dev_err(hdev, "Malformed MSFT vendor event: 0x%02x", ev); in msft_skb_pull()
838 struct msft_data *msft = hdev->msft_data; in msft_add_address_filter_sync()
845 return -EINVAL; in msft_add_address_filter_sync()
849 if (!test_bit(HCI_UP, &hdev->flags)) in msft_add_address_filter_sync()
850 return -ENODEV; in msft_add_address_filter_sync()
860 if (address_filter->state == AF_STATE_REMOVING) { in msft_add_address_filter_sync()
861 mutex_lock(&msft->filter_lock); in msft_add_address_filter_sync()
862 list_del(&address_filter->list); in msft_add_address_filter_sync()
863 mutex_unlock(&msft->filter_lock); in msft_add_address_filter_sync()
869 sizeof(address_filter->addr_type) + in msft_add_address_filter_sync()
870 sizeof(address_filter->bdaddr); in msft_add_address_filter_sync()
878 cp->sub_opcode = MSFT_OP_LE_MONITOR_ADVERTISEMENT; in msft_add_address_filter_sync()
879 cp->rssi_high = address_filter->rssi_high; in msft_add_address_filter_sync()
880 cp->rssi_low = address_filter->rssi_low; in msft_add_address_filter_sync()
881 cp->rssi_low_interval = address_filter->rssi_low_interval; in msft_add_address_filter_sync()
882 cp->rssi_sampling_period = address_filter->rssi_sampling_period; in msft_add_address_filter_sync()
883 cp->cond_type = MSFT_MONITOR_ADVERTISEMENT_TYPE_ADDR; in msft_add_address_filter_sync()
884 cp->data[0] = address_filter->addr_type; in msft_add_address_filter_sync()
885 memcpy(&cp->data[1], &address_filter->bdaddr, in msft_add_address_filter_sync()
886 sizeof(address_filter->bdaddr)); in msft_add_address_filter_sync()
888 skb = __hci_cmd_sync(hdev, hdev->msft_opcode, size, cp, in msft_add_address_filter_sync()
894 &address_filter->bdaddr); in msft_add_address_filter_sync()
901 if (!rp || rp->sub_opcode != MSFT_OP_LE_MONITOR_ADVERTISEMENT || in msft_add_address_filter_sync()
902 rp->status) in msft_add_address_filter_sync()
906 mutex_lock(&msft->filter_lock); in msft_add_address_filter_sync()
910 &address_filter->bdaddr); in msft_add_address_filter_sync()
911 list_del(&address_filter->list); in msft_add_address_filter_sync()
914 address_filter->state = AF_STATE_ADDED; in msft_add_address_filter_sync()
915 address_filter->msft_handle = rp->handle; in msft_add_address_filter_sync()
917 &address_filter->bdaddr); in msft_add_address_filter_sync()
919 mutex_unlock(&msft->filter_lock); in msft_add_address_filter_sync()
926 /* This function requires the caller holds msft->filter_lock */
932 struct msft_data *msft = hdev->msft_data; in msft_add_address_filter()
939 address_filter->state = AF_STATE_ADDING; in msft_add_address_filter()
940 address_filter->msft_handle = 0xff; in msft_add_address_filter()
941 address_filter->pattern_handle = handle_data->msft_handle; in msft_add_address_filter()
942 address_filter->mgmt_handle = handle_data->mgmt_handle; in msft_add_address_filter()
943 address_filter->rssi_high = handle_data->rssi_high; in msft_add_address_filter()
944 address_filter->rssi_low = handle_data->rssi_low; in msft_add_address_filter()
945 address_filter->rssi_low_interval = handle_data->rssi_low_interval; in msft_add_address_filter()
946 address_filter->rssi_sampling_period = handle_data->rssi_sampling_period; in msft_add_address_filter()
947 address_filter->addr_type = addr_type; in msft_add_address_filter()
948 bacpy(&address_filter->bdaddr, bdaddr); in msft_add_address_filter()
954 list_add_tail(&address_filter->list, &msft->address_filters); in msft_add_address_filter()
960 list_del(&address_filter->list); in msft_add_address_filter()
966 &address_filter->bdaddr); in msft_add_address_filter()
971 /* This function requires the caller holds hdev->lock */
977 struct msft_data *msft = hdev->msft_data; in msft_monitor_device_evt()
986 "MSFT vendor event 0x%02x: handle 0x%04x state %d addr %pMR", in msft_monitor_device_evt()
987 MSFT_EV_LE_MONITOR_DEVICE, ev->monitor_handle, in msft_monitor_device_evt()
988 ev->monitor_state, &ev->bdaddr); in msft_monitor_device_evt()
990 handle_data = msft_find_handle_data(hdev, ev->monitor_handle, false); in msft_monitor_device_evt()
992 if (!test_bit(HCI_QUIRK_USE_MSFT_EXT_ADDRESS_FILTER, &hdev->quirks)) { in msft_monitor_device_evt()
995 mgmt_handle = handle_data->mgmt_handle; in msft_monitor_device_evt()
1005 address_filter = msft_find_address_data(hdev, ev->addr_type, in msft_monitor_device_evt()
1006 &ev->bdaddr, in msft_monitor_device_evt()
1007 handle_data->msft_handle); in msft_monitor_device_evt()
1011 if (ev->monitor_state && handle_data->cond_type == in msft_monitor_device_evt()
1013 msft_add_address_filter(hdev, ev->addr_type, in msft_monitor_device_evt()
1014 &ev->bdaddr, handle_data); in msft_monitor_device_evt()
1022 list_for_each_entry(n, &msft->address_filters, list) { in msft_monitor_device_evt()
1023 if (n->state == AF_STATE_ADDED && in msft_monitor_device_evt()
1024 n->msft_handle == ev->monitor_handle) { in msft_monitor_device_evt()
1025 mgmt_handle = n->mgmt_handle; in msft_monitor_device_evt()
1033 &ev->bdaddr, ev->monitor_handle, ev->monitor_state); in msft_monitor_device_evt()
1038 switch (ev->addr_type) { in msft_monitor_device_evt()
1049 "MSFT vendor event 0x%02x: unknown addr type 0x%02x", in msft_monitor_device_evt()
1050 MSFT_EV_LE_MONITOR_DEVICE, ev->addr_type); in msft_monitor_device_evt()
1054 if (ev->monitor_state) { in msft_monitor_device_evt()
1055 msft_device_found(hdev, &ev->bdaddr, addr_type, mgmt_handle); in msft_monitor_device_evt()
1057 if (address_filter && address_filter->state == AF_STATE_ADDED) { in msft_monitor_device_evt()
1058 address_filter->state = AF_STATE_REMOVING; in msft_monitor_device_evt()
1064 msft_device_lost(hdev, &ev->bdaddr, addr_type, mgmt_handle); in msft_monitor_device_evt()
1070 struct msft_data *msft = hdev->msft_data; in msft_vendor_evt()
1077 /* When the extension has defined an event prefix, check that it in msft_vendor_evt()
1080 if (msft->evt_prefix_len > 0) { in msft_vendor_evt()
1081 evt_prefix = msft_skb_pull(hdev, skb, 0, msft->evt_prefix_len); in msft_vendor_evt()
1085 if (memcmp(evt_prefix, msft->evt_prefix, msft->evt_prefix_len)) in msft_vendor_evt()
1092 if (skb->len < 1) in msft_vendor_evt()
1103 mutex_lock(&msft->filter_lock); in msft_vendor_evt()
1105 mutex_unlock(&msft->filter_lock); in msft_vendor_evt()
1109 bt_dev_dbg(hdev, "MSFT vendor event 0x%02x", *evt); in msft_vendor_evt()
1118 struct msft_data *msft = hdev->msft_data; in msft_get_features()
1120 return msft ? msft->features : 0; in msft_get_features()
1128 struct msft_data *msft = hdev->msft_data; in msft_le_set_advertisement_filter_enable_cb()
1142 msft->filter_enabled = cp->enable; in msft_le_set_advertisement_filter_enable_cb()
1146 cp->enable ? "on" : "off"); in msft_le_set_advertisement_filter_enable_cb()
1154 struct msft_data *msft = hdev->msft_data; in msft_add_monitor_pattern()
1157 return -EOPNOTSUPP; in msft_add_monitor_pattern()
1159 if (msft->resuming || msft->suspending) in msft_add_monitor_pattern()
1160 return -EBUSY; in msft_add_monitor_pattern()
1168 struct msft_data *msft = hdev->msft_data; in msft_remove_monitor()
1171 return -EOPNOTSUPP; in msft_remove_monitor()
1173 if (msft->resuming || msft->suspending) in msft_remove_monitor()
1174 return -EBUSY; in msft_remove_monitor()
1182 struct msft_data *msft = hdev->msft_data; in msft_set_filter_enable()
1186 return -EOPNOTSUPP; in msft_set_filter_enable()
1190 err = __hci_cmd_sync_status(hdev, hdev->msft_opcode, sizeof(cp), &cp, in msft_set_filter_enable()
1200 return hdev->msft_curve_validity; in msft_curve_validity()