diff mbox series

[v2] bluetooth: Add support to handle MSFT Monitor Device event

Message ID 20211013060746.v2.1.Ic0a40b84dee3825302890aaea690e73165c71820@changeid (mailing list archive)
State Awaiting Upstream
Delegated to: Netdev Maintainers
Headers show
Series [v2] bluetooth: Add support to handle MSFT Monitor Device event | expand

Checks

Context Check Description
netdev/cover_letter success Single patches do not need cover letters
netdev/fixes_present success Fixes tag not required for -next series
netdev/patch_count success Link
netdev/tree_selection success Guessed tree name to be net-next
netdev/subject_prefix warning Target tree name not specified in the subject
netdev/cc_maintainers success CCed 7 of 7 maintainers
netdev/source_inline success Was 0 now: 0
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/module_param success Was 0 now: 0
netdev/build_32bit fail Errors and warnings before: 33 this patch: 35
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/verify_fixes success No Fixes tag
netdev/checkpatch warning WARNING: Possible unnecessary 'out of memory' message
netdev/build_allmodconfig_warn fail Errors and warnings before: 33 this patch: 35
netdev/header_inline success No static functions without inline keyword in header files

Commit Message

Manish Mandlik Oct. 13, 2021, 1:12 p.m. UTC
MSFT Monitor Device event indicates that the controller has either
started or stopped monitoring a Bluetooth device. This event is used by
the bluetoothd to notify clients with DeviceFound/DeviceLost.

Whenever the controller starts monitoring a device, 'Device Tracked'
flag in the 'Device Found' event is set and 'Monitor_Handle' indicates
the matched monitor id. When the controller stops monitoring the device,
the 'Device Lost' event is sent to the bluetoothd.

Test performed:
- verified by logs that Monitor Device is received from the controller
  and sent to the bluetoothd when the controller starts/stops monitoring
  a bluetooth device.

Signed-off-by: Manish Mandlik <mmandlik@google.com>
---
Hello Bt-Maintainers,

As mentioned in the bluez patch series [1], we need to capture the 'MSFT
Monitor Device' from the controller and pass it to the bluetoothd.

This is required to further optimize the power consumption by avoiding
handling of RSSI thresholds and timeouts in the user space and let the
controller do the RSSI tracking.

This patch adds support to read HCI_VS_MSFT_LE_Monitor_Device_Event,
adds a flag in Device Found event to indicate device is being tracked,
introduces a new MGMT event MGMT_EV_ADV_MONITOR_DEVICE_LOST to indicate
that the controller has stopped tracking that particular device.

Please let me know what you think about this or if you have any further
questions.

[1] https://patchwork.kernel.org/project/bluetooth/list/?series=562679

Thanks,
Manish.

Changes in v2:
- Instead of creating a new 'Device Tracking' event, add a flag 'Device
  Tracked' in the existing 'Device Found' event and add a new 'Device
  Lost' event to indicate that the controller has stopped tracking that
  device.

 include/net/bluetooth/hci_core.h |  11 ++++
 include/net/bluetooth/mgmt.h     |   8 +++
 net/bluetooth/hci_core.c         |  12 ++++
 net/bluetooth/mgmt.c             |  39 +++++++++++-
 net/bluetooth/msft.c             | 103 ++++++++++++++++++++++++-------
 5 files changed, 151 insertions(+), 22 deletions(-)

Comments

kernel test robot Oct. 13, 2021, 4:04 p.m. UTC | #1
Hi Manish,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on bluetooth-next/master]
[also build test ERROR on next-20211013]
[cannot apply to bluetooth/master v5.15-rc5]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Manish-Mandlik/bluetooth-Add-support-to-handle-MSFT-Monitor-Device-event/20211013-211504
base:   https://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git master
config: sh-allmodconfig (attached as .config)
compiler: sh4-linux-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/8c24f97d82e241c5605046401a106ace240d1a5d
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Manish-Mandlik/bluetooth-Add-support-to-handle-MSFT-Monitor-Device-event/20211013-211504
        git checkout 8c24f97d82e241c5605046401a106ace240d1a5d
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross ARCH=sh 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   In file included from net/bluetooth/msft.c:6:
   net/bluetooth/msft.c: In function 'msft_monitor_device_evt':
>> include/net/bluetooth/bluetooth.h:212:16: error: format '%u' expects a matching 'unsigned int' argument [-Werror=format=]
     212 |         BT_ERR("%s: " fmt, (hdev)->name, ##__VA_ARGS__)
         |                ^~~~~~
   include/net/bluetooth/bluetooth.h:199:40: note: in definition of macro 'BT_ERR'
     199 | #define BT_ERR(fmt, ...)        bt_err(fmt "\n", ##__VA_ARGS__)
         |                                        ^~~
   net/bluetooth/msft.c:397:25: note: in expansion of macro 'bt_dev_err'
     397 |                         bt_dev_err(hdev, "MSFT vendor event %u: no memory");
         |                         ^~~~~~~~~~
   cc1: all warnings being treated as errors


vim +212 include/net/bluetooth/bluetooth.h

^1da177e4c3f41 Linus Torvalds 2005-04-16  206  
6f558b70fb39fc Loic Poulain   2015-08-30  207  #define bt_dev_info(hdev, fmt, ...)				\
6f558b70fb39fc Loic Poulain   2015-08-30  208  	BT_INFO("%s: " fmt, (hdev)->name, ##__VA_ARGS__)
594b31ea7dc610 Frederic Danis 2015-09-23  209  #define bt_dev_warn(hdev, fmt, ...)				\
594b31ea7dc610 Frederic Danis 2015-09-23  210  	BT_WARN("%s: " fmt, (hdev)->name, ##__VA_ARGS__)
6f558b70fb39fc Loic Poulain   2015-08-30  211  #define bt_dev_err(hdev, fmt, ...)				\
6f558b70fb39fc Loic Poulain   2015-08-30 @212  	BT_ERR("%s: " fmt, (hdev)->name, ##__VA_ARGS__)
6f558b70fb39fc Loic Poulain   2015-08-30  213  #define bt_dev_dbg(hdev, fmt, ...)				\
6f558b70fb39fc Loic Poulain   2015-08-30  214  	BT_DBG("%s: " fmt, (hdev)->name, ##__VA_ARGS__)
6f558b70fb39fc Loic Poulain   2015-08-30  215  

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
kernel test robot Oct. 13, 2021, 4:57 p.m. UTC | #2
Hi Manish,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on bluetooth-next/master]
[also build test WARNING on next-20211013]
[cannot apply to bluetooth/master v5.15-rc5]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Manish-Mandlik/bluetooth-Add-support-to-handle-MSFT-Monitor-Device-event/20211013-211504
base:   https://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git master
config: x86_64-randconfig-a014-20211013 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-22) 9.3.0
reproduce (this is a W=1 build):
        # https://github.com/0day-ci/linux/commit/8c24f97d82e241c5605046401a106ace240d1a5d
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Manish-Mandlik/bluetooth-Add-support-to-handle-MSFT-Monitor-Device-event/20211013-211504
        git checkout 8c24f97d82e241c5605046401a106ace240d1a5d
        # save the attached .config to linux build tree
        make W=1 ARCH=x86_64 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

   In file included from net/bluetooth/msft.c:6:
   net/bluetooth/msft.c: In function 'msft_monitor_device_evt':
>> include/net/bluetooth/bluetooth.h:212:9: warning: format '%u' expects a matching 'unsigned int' argument [-Wformat=]
     212 |  BT_ERR("%s: " fmt, (hdev)->name, ##__VA_ARGS__)
         |         ^~~~~~
   include/net/bluetooth/bluetooth.h:199:33: note: in definition of macro 'BT_ERR'
     199 | #define BT_ERR(fmt, ...) bt_err(fmt "\n", ##__VA_ARGS__)
         |                                 ^~~
   net/bluetooth/msft.c:397:4: note: in expansion of macro 'bt_dev_err'
     397 |    bt_dev_err(hdev, "MSFT vendor event %u: no memory");
         |    ^~~~~~~~~~
   net/bluetooth/msft.c:397:41: note: format string is defined here
     397 |    bt_dev_err(hdev, "MSFT vendor event %u: no memory");
         |                                        ~^
         |                                         |
         |                                         unsigned int


vim +212 include/net/bluetooth/bluetooth.h

^1da177e4c3f41 Linus Torvalds 2005-04-16  206  
6f558b70fb39fc Loic Poulain   2015-08-30  207  #define bt_dev_info(hdev, fmt, ...)				\
6f558b70fb39fc Loic Poulain   2015-08-30  208  	BT_INFO("%s: " fmt, (hdev)->name, ##__VA_ARGS__)
594b31ea7dc610 Frederic Danis 2015-09-23  209  #define bt_dev_warn(hdev, fmt, ...)				\
594b31ea7dc610 Frederic Danis 2015-09-23  210  	BT_WARN("%s: " fmt, (hdev)->name, ##__VA_ARGS__)
6f558b70fb39fc Loic Poulain   2015-08-30  211  #define bt_dev_err(hdev, fmt, ...)				\
6f558b70fb39fc Loic Poulain   2015-08-30 @212  	BT_ERR("%s: " fmt, (hdev)->name, ##__VA_ARGS__)
6f558b70fb39fc Loic Poulain   2015-08-30  213  #define bt_dev_dbg(hdev, fmt, ...)				\
6f558b70fb39fc Loic Poulain   2015-08-30  214  	BT_DBG("%s: " fmt, (hdev)->name, ##__VA_ARGS__)
6f558b70fb39fc Loic Poulain   2015-08-30  215  

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
kernel test robot Oct. 14, 2021, 4:02 a.m. UTC | #3
Hi Manish,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on bluetooth-next/master]
[also build test WARNING on next-20211013]
[cannot apply to bluetooth/master v5.15-rc5]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Manish-Mandlik/bluetooth-Add-support-to-handle-MSFT-Monitor-Device-event/20211013-211504
base:   https://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git master
config: sparc64-randconfig-s032-20211013 (attached as .config)
compiler: sparc64-linux-gcc (GCC) 11.2.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # apt-get install sparse
        # sparse version: v0.6.4-dirty
        # https://github.com/0day-ci/linux/commit/8c24f97d82e241c5605046401a106ace240d1a5d
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Manish-Mandlik/bluetooth-Add-support-to-handle-MSFT-Monitor-Device-event/20211013-211504
        git checkout 8c24f97d82e241c5605046401a106ace240d1a5d
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=sparc64 SHELL=/bin/bash net/bluetooth/

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>


sparse warnings: (new ones prefixed by >>)
   net/bluetooth/mgmt.c:3647:29: sparse: sparse: restricted __le16 degrades to integer
   net/bluetooth/mgmt.c:4352:9: sparse: sparse: cast to restricted __le32
   net/bluetooth/mgmt.c:4352:9: sparse: sparse: cast to restricted __le32
   net/bluetooth/mgmt.c:4352:9: sparse: sparse: cast to restricted __le32
   net/bluetooth/mgmt.c:4352:9: sparse: sparse: cast to restricted __le32
   net/bluetooth/mgmt.c:4352:9: sparse: sparse: cast to restricted __le32
   net/bluetooth/mgmt.c:4352:9: sparse: sparse: cast to restricted __le32
>> net/bluetooth/mgmt.c:9712:43: sparse: sparse: invalid assignment: |=
>> net/bluetooth/mgmt.c:9712:43: sparse:    left side has type restricted __le32
>> net/bluetooth/mgmt.c:9712:43: sparse:    right side has type int

vim +9712 net/bluetooth/mgmt.c

  9620	
  9621	void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
  9622			       u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
  9623			       u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
  9624	{
  9625		char buf[512];
  9626		struct monitored_device *dev, *tmp_dev;
  9627		struct mgmt_ev_device_found *ev = (void *)buf;
  9628		size_t ev_size;
  9629		bool monitored = false;
  9630	
  9631		/* Don't send events for a non-kernel initiated discovery. With
  9632		 * LE one exception is if we have pend_le_reports > 0 in which
  9633		 * case we're doing passive scanning and want these events.
  9634		 */
  9635		if (!hci_discovery_active(hdev)) {
  9636			if (link_type == ACL_LINK)
  9637				return;
  9638			if (link_type == LE_LINK &&
  9639			    list_empty(&hdev->pend_le_reports) &&
  9640			    !hci_is_adv_monitoring(hdev)) {
  9641				return;
  9642			}
  9643		}
  9644	
  9645		if (hdev->discovery.result_filtering) {
  9646			/* We are using service discovery */
  9647			if (!is_filter_match(hdev, rssi, eir, eir_len, scan_rsp,
  9648					     scan_rsp_len))
  9649				return;
  9650		}
  9651	
  9652		if (hdev->discovery.limited) {
  9653			/* Check for limited discoverable bit */
  9654			if (dev_class) {
  9655				if (!(dev_class[1] & 0x20))
  9656					return;
  9657			} else {
  9658				u8 *flags = eir_get_data(eir, eir_len, EIR_FLAGS, NULL);
  9659				if (!flags || !(flags[0] & LE_AD_LIMITED))
  9660					return;
  9661			}
  9662		}
  9663	
  9664		/* Make sure that the buffer is big enough. The 5 extra bytes
  9665		 * are for the potential CoD field.
  9666		 */
  9667		if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
  9668			return;
  9669	
  9670		memset(buf, 0, sizeof(buf));
  9671	
  9672		/* In case of device discovery with BR/EDR devices (pre 1.2), the
  9673		 * RSSI value was reported as 0 when not available. This behavior
  9674		 * is kept when using device discovery. This is required for full
  9675		 * backwards compatibility with the API.
  9676		 *
  9677		 * However when using service discovery, the value 127 will be
  9678		 * returned when the RSSI is not available.
  9679		 */
  9680		if (rssi == HCI_RSSI_INVALID && !hdev->discovery.report_invalid_rssi &&
  9681		    link_type == ACL_LINK)
  9682			rssi = 0;
  9683	
  9684		bacpy(&ev->addr.bdaddr, bdaddr);
  9685		ev->addr.type = link_to_bdaddr(link_type, addr_type);
  9686		ev->rssi = rssi;
  9687		ev->flags = cpu_to_le32(flags);
  9688	
  9689		if (eir_len > 0)
  9690			/* Copy EIR or advertising data into event */
  9691			memcpy(ev->eir, eir, eir_len);
  9692	
  9693		if (dev_class && !eir_get_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
  9694					       NULL))
  9695			eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
  9696						  dev_class, 3);
  9697	
  9698		if (scan_rsp_len > 0)
  9699			/* Append scan response data to event */
  9700			memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
  9701	
  9702		ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
  9703		ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
  9704	
  9705		if (!list_empty(&hdev->monitored_devices)) {
  9706			/* An advertisement could match multiple advertisement monitors.
  9707			 * Send the Device Found event once for all matched monitors.
  9708			 */
  9709			list_for_each_entry_safe(dev, tmp_dev, &hdev->monitored_devices,
  9710						 list) {
  9711				if (!bacmp(&dev->bdaddr, &ev->addr.bdaddr)) {
> 9712					ev->flags |= MGMT_DEV_FOUND_MONITORING;
  9713					ev->monitor_handle = cpu_to_le16(dev->handle);
  9714	
  9715					list_del(&dev->list);
  9716					kfree(dev);
  9717	
  9718					mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev,
  9719						   ev_size, NULL);
  9720					monitored = true;
  9721				}
  9722			}
  9723		}
  9724	
  9725		if (!monitored)
  9726			mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
  9727	}
  9728	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
diff mbox series

Patch

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index dd8840e70e25..36c50e36a594 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -256,6 +256,14 @@  struct adv_info {
 
 #define HCI_ADV_TX_POWER_NO_PREFERENCE 0x7F
 
+struct monitored_device {
+	struct list_head list;
+
+	bdaddr_t bdaddr;
+	__u8     addr_type;
+	__u16    handle;
+};
+
 struct adv_pattern {
 	struct list_head list;
 	__u8 ad_type;
@@ -548,6 +556,7 @@  struct hci_dev {
 	struct list_head	pend_le_reports;
 	struct list_head	blocked_keys;
 	struct list_head	local_codecs;
+	struct list_head	monitored_devices;
 
 	struct hci_dev_stats	stat;
 
@@ -1842,6 +1851,8 @@  void mgmt_adv_monitor_removed(struct hci_dev *hdev, u16 handle);
 int mgmt_phy_configuration_changed(struct hci_dev *hdev, struct sock *skip);
 int mgmt_add_adv_patterns_monitor_complete(struct hci_dev *hdev, u8 status);
 int mgmt_remove_adv_monitor_complete(struct hci_dev *hdev, u8 status);
+void mgmt_adv_monitor_device_lost(struct hci_dev *hdev, u16 handle,
+				  bdaddr_t *addr, u8 addr_type);
 
 u8 hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, u16 latency,
 		      u16 to_multiplier);
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 23a0524061b7..3d0472b3ebdc 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -940,12 +940,14 @@  struct mgmt_ev_auth_failed {
 #define MGMT_DEV_FOUND_LEGACY_PAIRING  0x02
 #define MGMT_DEV_FOUND_NOT_CONNECTABLE 0x04
 #define MGMT_DEV_FOUND_INITIATED_CONN  0x08
+#define MGMT_DEV_FOUND_MONITORING      0x10
 
 #define MGMT_EV_DEVICE_FOUND		0x0012
 struct mgmt_ev_device_found {
 	struct mgmt_addr_info addr;
 	__s8	rssi;
 	__le32	flags;
+	__le16  monitor_handle;
 	__le16	eir_len;
 	__u8	eir[];
 } __packed;
@@ -1103,3 +1105,9 @@  struct mgmt_ev_controller_resume {
 #define MGMT_WAKE_REASON_NON_BT_WAKE		0x0
 #define MGMT_WAKE_REASON_UNEXPECTED		0x1
 #define MGMT_WAKE_REASON_REMOTE_WAKE		0x2
+
+#define MGMT_EV_ADV_MONITOR_DEVICE_LOST		0x002f
+struct mgmt_ev_adv_monitor_device_lost {
+	__le16 monitor_handle;
+	struct mgmt_addr_info addr;
+} __packed;
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 98533def61a3..e3e4a60b74e1 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1600,6 +1600,16 @@  static void hci_pend_le_actions_clear(struct hci_dev *hdev)
 	BT_DBG("All LE pending actions cleared");
 }
 
+static void hci_monitored_devices_clear(struct hci_dev *hdev)
+{
+	struct monitored_device *dev, *tmp;
+
+	list_for_each_entry_safe(dev, tmp, &hdev->monitored_devices, list) {
+		list_del(&dev->list);
+		kfree(dev);
+	}
+}
+
 int hci_dev_do_close(struct hci_dev *hdev)
 {
 	bool auto_off;
@@ -1670,6 +1680,7 @@  int hci_dev_do_close(struct hci_dev *hdev)
 	hci_inquiry_cache_flush(hdev);
 	hci_pend_le_actions_clear(hdev);
 	hci_conn_hash_flush(hdev);
+	hci_monitored_devices_clear(hdev);
 	hci_dev_unlock(hdev);
 
 	smp_unregister(hdev);
@@ -3738,6 +3749,7 @@  struct hci_dev *hci_alloc_dev_priv(int sizeof_priv)
 	INIT_LIST_HEAD(&hdev->conn_hash.list);
 	INIT_LIST_HEAD(&hdev->adv_instances);
 	INIT_LIST_HEAD(&hdev->blocked_keys);
+	INIT_LIST_HEAD(&hdev->monitored_devices);
 
 	INIT_LIST_HEAD(&hdev->local_codecs);
 	INIT_WORK(&hdev->rx_work, hci_rx_work);
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 44683443300c..fe69554b80ce 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -173,6 +173,7 @@  static const u16 mgmt_events[] = {
 	MGMT_EV_ADV_MONITOR_REMOVED,
 	MGMT_EV_CONTROLLER_SUSPEND,
 	MGMT_EV_CONTROLLER_RESUME,
+	MGMT_EV_ADV_MONITOR_DEVICE_LOST,
 };
 
 static const u16 mgmt_untrusted_commands[] = {
@@ -4396,6 +4397,19 @@  static int set_device_flags(struct sock *sk, struct hci_dev *hdev, void *data,
 				 &cp->addr, sizeof(cp->addr));
 }
 
+void mgmt_adv_monitor_device_lost(struct hci_dev *hdev, u16 handle,
+				  bdaddr_t *addr, u8 addr_type)
+{
+	struct mgmt_ev_adv_monitor_device_lost ev;
+
+	ev.monitor_handle = cpu_to_le16(handle);
+	bacpy(&ev.addr.bdaddr, addr);
+	ev.addr.type = addr_type;
+
+	mgmt_event(MGMT_EV_ADV_MONITOR_DEVICE_LOST, hdev, &ev, sizeof(ev),
+		   NULL);
+}
+
 static void mgmt_adv_monitor_added(struct sock *sk, struct hci_dev *hdev,
 				   u16 handle)
 {
@@ -9609,8 +9623,10 @@  void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
 		       u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
 {
 	char buf[512];
+	struct monitored_device *dev, *tmp_dev;
 	struct mgmt_ev_device_found *ev = (void *)buf;
 	size_t ev_size;
+	bool monitored = false;
 
 	/* Don't send events for a non-kernel initiated discovery. With
 	 * LE one exception is if we have pend_le_reports > 0 in which
@@ -9686,7 +9702,28 @@  void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
 	ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
 	ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
 
-	mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
+	if (!list_empty(&hdev->monitored_devices)) {
+		/* An advertisement could match multiple advertisement monitors.
+		 * Send the Device Found event once for all matched monitors.
+		 */
+		list_for_each_entry_safe(dev, tmp_dev, &hdev->monitored_devices,
+					 list) {
+			if (!bacmp(&dev->bdaddr, &ev->addr.bdaddr)) {
+				ev->flags |= MGMT_DEV_FOUND_MONITORING;
+				ev->monitor_handle = cpu_to_le16(dev->handle);
+
+				list_del(&dev->list);
+				kfree(dev);
+
+				mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev,
+					   ev_size, NULL);
+				monitored = true;
+			}
+		}
+	}
+
+	if (!monitored)
+		mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
 }
 
 void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
diff --git a/net/bluetooth/msft.c b/net/bluetooth/msft.c
index 255cffa554ee..2f88136bf816 100644
--- a/net/bluetooth/msft.c
+++ b/net/bluetooth/msft.c
@@ -80,6 +80,14 @@  struct msft_rp_le_set_advertisement_filter_enable {
 	__u8 sub_opcode;
 } __packed;
 
+#define MSFT_EV_LE_MONITOR_DEVICE	0x02
+struct msft_ev_le_monitor_device {
+	__u8     addr_type;
+	bdaddr_t bdaddr;
+	__u8     monitor_handle;
+	__u8     monitor_state;
+} __packed;
+
 struct msft_monitor_advertisement_handle_data {
 	__u8  msft_handle;
 	__u16 mgmt_handle;
@@ -103,6 +111,26 @@  static int __msft_add_monitor_pattern(struct hci_dev *hdev,
 static int __msft_remove_monitor(struct hci_dev *hdev,
 				 struct adv_monitor *monitor, u16 handle);
 
+/* is_mgmt = true matches the handle exposed to userspace via mgmt.
+ * is_mgmt = false matches the handle used by the msft controller.
+ * This function requires the caller holds hdev->lock
+ */
+static struct msft_monitor_advertisement_handle_data *msft_find_handle_data
+				(struct hci_dev *hdev, u16 handle, bool is_mgmt)
+{
+	struct msft_monitor_advertisement_handle_data *entry;
+	struct msft_data *msft = hdev->msft_data;
+
+	list_for_each_entry(entry, &msft->handle_map, list) {
+		if (is_mgmt && entry->mgmt_handle == handle)
+			return entry;
+		if (!is_mgmt && entry->msft_handle == handle)
+			return entry;
+	}
+
+	return NULL;
+}
+
 bool msft_monitor_supported(struct hci_dev *hdev)
 {
 	return !!(msft_get_features(hdev) & MSFT_FEATURE_MASK_LE_ADV_MONITOR);
@@ -341,6 +369,47 @@  void msft_unregister(struct hci_dev *hdev)
 	kfree(msft);
 }
 
+/* This function requires the caller holds hdev->lock */
+static void msft_monitor_device_evt(struct hci_dev *hdev, struct sk_buff *skb)
+{
+	struct msft_ev_le_monitor_device *ev = (void *)skb->data;
+	struct msft_monitor_advertisement_handle_data *handle_data;
+	struct monitored_device *dev;
+
+	if (skb->len < sizeof(*ev)) {
+		bt_dev_err(hdev,
+			   "MSFT vendor event %u: insufficient data (len: %u)",
+			   MSFT_EV_LE_MONITOR_DEVICE, skb->len);
+		return;
+	}
+	skb_pull(skb, sizeof(*ev));
+
+	bt_dev_dbg(hdev,
+		   "MSFT vendor event %u: handle 0x%04x state %d addr %pMR",
+		   MSFT_EV_LE_MONITOR_DEVICE, ev->monitor_handle,
+		   ev->monitor_state, &ev->bdaddr);
+
+	handle_data = msft_find_handle_data(hdev, ev->monitor_handle, false);
+
+	if (ev->monitor_state) {
+		dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+		if (!dev) {
+			bt_dev_err(hdev, "MSFT vendor event %u: no memory");
+			return;
+		}
+
+		bacpy(&dev->bdaddr, &ev->bdaddr);
+		dev->addr_type = ev->addr_type;
+		dev->handle = handle_data->mgmt_handle;
+
+		INIT_LIST_HEAD(&dev->list);
+		list_add(&dev->list, &hdev->monitored_devices);
+	} else {
+		mgmt_adv_monitor_device_lost(hdev, handle_data->mgmt_handle,
+					     &ev->bdaddr, ev->addr_type);
+	}
+}
+
 void msft_vendor_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	struct msft_data *msft = hdev->msft_data;
@@ -368,37 +437,29 @@  void msft_vendor_evt(struct hci_dev *hdev, struct sk_buff *skb)
 	if (skb->len < 1)
 		return;
 
+	hci_dev_lock(hdev);
+
 	event = *skb->data;
 	skb_pull(skb, 1);
 
-	bt_dev_dbg(hdev, "MSFT vendor event %u", event);
-}
+	switch (event) {
+	case MSFT_EV_LE_MONITOR_DEVICE:
+		msft_monitor_device_evt(hdev, skb);
+		break;
 
-__u64 msft_get_features(struct hci_dev *hdev)
-{
-	struct msft_data *msft = hdev->msft_data;
+	default:
+		bt_dev_dbg(hdev, "MSFT vendor event %u", event);
+		break;
+	}
 
-	return msft ? msft->features : 0;
+	hci_dev_unlock(hdev);
 }
 
-/* is_mgmt = true matches the handle exposed to userspace via mgmt.
- * is_mgmt = false matches the handle used by the msft controller.
- * This function requires the caller holds hdev->lock
- */
-static struct msft_monitor_advertisement_handle_data *msft_find_handle_data
-				(struct hci_dev *hdev, u16 handle, bool is_mgmt)
+__u64 msft_get_features(struct hci_dev *hdev)
 {
-	struct msft_monitor_advertisement_handle_data *entry;
 	struct msft_data *msft = hdev->msft_data;
 
-	list_for_each_entry(entry, &msft->handle_map, list) {
-		if (is_mgmt && entry->mgmt_handle == handle)
-			return entry;
-		if (!is_mgmt && entry->msft_handle == handle)
-			return entry;
-	}
-
-	return NULL;
+	return msft ? msft->features : 0;
 }
 
 static void msft_le_monitor_advertisement_cb(struct hci_dev *hdev,