Skip to content

Commit 3368aa3

Browse files
liveusrVudentz
authored andcommitted
Bluetooth: msft: Handle MSFT Monitor Device Event
Whenever the controller starts/stops monitoring a bt device, it sends MSFT Monitor Device event. Add handler to read this vendor event. Test performed: - Verified by logs that the MSFT Monitor Device event is received from the controller whenever it starts/stops monitoring a device. Signed-off-by: Manish Mandlik <mmandlik@google.com> Reviewed-by: Miao-chen Chou <mcchou@google.com> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
1 parent 3afee21 commit 3368aa3

File tree

3 files changed

+162
-8
lines changed

3 files changed

+162
-8
lines changed

include/net/bluetooth/hci_core.h

+11
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,15 @@ struct adv_info {
258258

259259
#define HCI_ADV_TX_POWER_NO_PREFERENCE 0x7F
260260

261+
struct monitored_device {
262+
struct list_head list;
263+
264+
bdaddr_t bdaddr;
265+
__u8 addr_type;
266+
__u16 handle;
267+
bool notified;
268+
};
269+
261270
struct adv_pattern {
262271
struct list_head list;
263272
__u8 ad_type;
@@ -591,6 +600,8 @@ struct hci_dev {
591600

592601
struct delayed_work interleave_scan;
593602

603+
struct list_head monitored_devices;
604+
594605
#if IS_ENABLED(CONFIG_BT_LEDS)
595606
struct led_trigger *power_led;
596607
#endif

net/bluetooth/hci_core.c

+1
Original file line numberDiff line numberDiff line change
@@ -2503,6 +2503,7 @@ struct hci_dev *hci_alloc_dev_priv(int sizeof_priv)
25032503
INIT_LIST_HEAD(&hdev->conn_hash.list);
25042504
INIT_LIST_HEAD(&hdev->adv_instances);
25052505
INIT_LIST_HEAD(&hdev->blocked_keys);
2506+
INIT_LIST_HEAD(&hdev->monitored_devices);
25062507

25072508
INIT_LIST_HEAD(&hdev->local_codecs);
25082509
INIT_WORK(&hdev->rx_work, hci_rx_work);

net/bluetooth/msft.c

+150-8
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,14 @@ struct msft_rp_le_set_advertisement_filter_enable {
8080
__u8 sub_opcode;
8181
} __packed;
8282

83+
#define MSFT_EV_LE_MONITOR_DEVICE 0x02
84+
struct msft_ev_le_monitor_device {
85+
__u8 addr_type;
86+
bdaddr_t bdaddr;
87+
__u8 monitor_handle;
88+
__u8 monitor_state;
89+
} __packed;
90+
8391
struct msft_monitor_advertisement_handle_data {
8492
__u8 msft_handle;
8593
__u16 mgmt_handle;
@@ -204,6 +212,30 @@ static struct msft_monitor_advertisement_handle_data *msft_find_handle_data
204212
return NULL;
205213
}
206214

215+
/* This function requires the caller holds hdev->lock */
216+
static int msft_monitor_device_del(struct hci_dev *hdev, __u16 mgmt_handle,
217+
bdaddr_t *bdaddr, __u8 addr_type)
218+
{
219+
struct monitored_device *dev, *tmp;
220+
int count = 0;
221+
222+
list_for_each_entry_safe(dev, tmp, &hdev->monitored_devices, list) {
223+
/* mgmt_handle == 0 indicates remove all devices, whereas,
224+
* bdaddr == NULL indicates remove all devices matching the
225+
* mgmt_handle.
226+
*/
227+
if ((!mgmt_handle || dev->handle == mgmt_handle) &&
228+
(!bdaddr || (!bacmp(bdaddr, &dev->bdaddr) &&
229+
addr_type == dev->addr_type))) {
230+
list_del(&dev->list);
231+
kfree(dev);
232+
count++;
233+
}
234+
}
235+
236+
return count;
237+
}
238+
207239
static void msft_le_monitor_advertisement_cb(struct hci_dev *hdev,
208240
u8 status, u16 opcode,
209241
struct sk_buff *skb)
@@ -294,6 +326,10 @@ static void msft_le_cancel_monitor_advertisement_cb(struct hci_dev *hdev,
294326
if (monitor && !msft->suspending)
295327
hci_free_adv_monitor(hdev, monitor);
296328

329+
/* Clear any monitored devices by this Adv Monitor */
330+
msft_monitor_device_del(hdev, handle_data->mgmt_handle, NULL,
331+
0);
332+
297333
list_del(&handle_data->list);
298334
kfree(handle_data);
299335
}
@@ -557,6 +593,13 @@ void msft_do_close(struct hci_dev *hdev)
557593
list_del(&handle_data->list);
558594
kfree(handle_data);
559595
}
596+
597+
hci_dev_lock(hdev);
598+
599+
/* Clear any devices that are being monitored */
600+
msft_monitor_device_del(hdev, 0, NULL, 0);
601+
602+
hci_dev_unlock(hdev);
560603
}
561604

562605
void msft_register(struct hci_dev *hdev)
@@ -590,10 +633,97 @@ void msft_unregister(struct hci_dev *hdev)
590633
kfree(msft);
591634
}
592635

636+
/* This function requires the caller holds hdev->lock */
637+
static void msft_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr,
638+
__u8 addr_type, __u16 mgmt_handle)
639+
{
640+
struct monitored_device *dev;
641+
642+
dev = kmalloc(sizeof(*dev), GFP_KERNEL);
643+
if (!dev) {
644+
bt_dev_err(hdev, "MSFT vendor event %u: no memory",
645+
MSFT_EV_LE_MONITOR_DEVICE);
646+
return;
647+
}
648+
649+
bacpy(&dev->bdaddr, bdaddr);
650+
dev->addr_type = addr_type;
651+
dev->handle = mgmt_handle;
652+
dev->notified = false;
653+
654+
INIT_LIST_HEAD(&dev->list);
655+
list_add(&dev->list, &hdev->monitored_devices);
656+
}
657+
658+
/* This function requires the caller holds hdev->lock */
659+
static void msft_device_lost(struct hci_dev *hdev, bdaddr_t *bdaddr,
660+
__u8 addr_type, __u16 mgmt_handle)
661+
{
662+
if (!msft_monitor_device_del(hdev, mgmt_handle, bdaddr, addr_type)) {
663+
bt_dev_err(hdev, "MSFT vendor event %u: dev %pMR not in list",
664+
MSFT_EV_LE_MONITOR_DEVICE, bdaddr);
665+
}
666+
}
667+
668+
static void *msft_skb_pull(struct hci_dev *hdev, struct sk_buff *skb,
669+
u8 ev, size_t len)
670+
{
671+
void *data;
672+
673+
data = skb_pull_data(skb, len);
674+
if (!data)
675+
bt_dev_err(hdev, "Malformed MSFT vendor event: 0x%02x", ev);
676+
677+
return data;
678+
}
679+
680+
/* This function requires the caller holds hdev->lock */
681+
static void msft_monitor_device_evt(struct hci_dev *hdev, struct sk_buff *skb)
682+
{
683+
struct msft_ev_le_monitor_device *ev;
684+
struct msft_monitor_advertisement_handle_data *handle_data;
685+
u8 addr_type;
686+
687+
ev = msft_skb_pull(hdev, skb, MSFT_EV_LE_MONITOR_DEVICE, sizeof(*ev));
688+
if (!ev)
689+
return;
690+
691+
bt_dev_dbg(hdev,
692+
"MSFT vendor event 0x%02x: handle 0x%04x state %d addr %pMR",
693+
MSFT_EV_LE_MONITOR_DEVICE, ev->monitor_handle,
694+
ev->monitor_state, &ev->bdaddr);
695+
696+
handle_data = msft_find_handle_data(hdev, ev->monitor_handle, false);
697+
698+
switch (ev->addr_type) {
699+
case ADDR_LE_DEV_PUBLIC:
700+
addr_type = BDADDR_LE_PUBLIC;
701+
break;
702+
703+
case ADDR_LE_DEV_RANDOM:
704+
addr_type = BDADDR_LE_RANDOM;
705+
break;
706+
707+
default:
708+
bt_dev_err(hdev,
709+
"MSFT vendor event 0x%02x: unknown addr type 0x%02x",
710+
MSFT_EV_LE_MONITOR_DEVICE, ev->addr_type);
711+
return;
712+
}
713+
714+
if (ev->monitor_state)
715+
msft_device_found(hdev, &ev->bdaddr, addr_type,
716+
handle_data->mgmt_handle);
717+
else
718+
msft_device_lost(hdev, &ev->bdaddr, addr_type,
719+
handle_data->mgmt_handle);
720+
}
721+
593722
void msft_vendor_evt(struct hci_dev *hdev, void *data, struct sk_buff *skb)
594723
{
595724
struct msft_data *msft = hdev->msft_data;
596-
u8 event;
725+
u8 *evt_prefix;
726+
u8 *evt;
597727

598728
if (!msft)
599729
return;
@@ -602,13 +732,12 @@ void msft_vendor_evt(struct hci_dev *hdev, void *data, struct sk_buff *skb)
602732
* matches, and otherwise just return.
603733
*/
604734
if (msft->evt_prefix_len > 0) {
605-
if (skb->len < msft->evt_prefix_len)
735+
evt_prefix = msft_skb_pull(hdev, skb, 0, msft->evt_prefix_len);
736+
if (!evt_prefix)
606737
return;
607738

608-
if (memcmp(skb->data, msft->evt_prefix, msft->evt_prefix_len))
739+
if (memcmp(evt_prefix, msft->evt_prefix, msft->evt_prefix_len))
609740
return;
610-
611-
skb_pull(skb, msft->evt_prefix_len);
612741
}
613742

614743
/* Every event starts at least with an event code and the rest of
@@ -617,10 +746,23 @@ void msft_vendor_evt(struct hci_dev *hdev, void *data, struct sk_buff *skb)
617746
if (skb->len < 1)
618747
return;
619748

620-
event = *skb->data;
621-
skb_pull(skb, 1);
749+
evt = msft_skb_pull(hdev, skb, 0, sizeof(*evt));
750+
if (!evt)
751+
return;
752+
753+
hci_dev_lock(hdev);
754+
755+
switch (*evt) {
756+
case MSFT_EV_LE_MONITOR_DEVICE:
757+
msft_monitor_device_evt(hdev, skb);
758+
break;
622759

623-
bt_dev_dbg(hdev, "MSFT vendor event %u", event);
760+
default:
761+
bt_dev_dbg(hdev, "MSFT vendor event 0x%02x", *evt);
762+
break;
763+
}
764+
765+
hci_dev_unlock(hdev);
624766
}
625767

626768
__u64 msft_get_features(struct hci_dev *hdev)

0 commit comments

Comments
 (0)