@@ -448,7 +448,7 @@ async def passive_scan(
448448
449449 # this should be a unique path to allow multiple python interpreters
450450 # running bleak and multiple scanners within a single interpreter
451- monitor_path = f"/org/bleak/{ os .getpid ()} /{ id (monitor )} "
451+ monitor_path = f"/org/bleak/{ os .getpid ()} /{ AdvertisementMonitor . __name__ } { id (monitor )} "
452452
453453 reply = await self ._bus .call (
454454 Message (
@@ -471,10 +471,47 @@ async def passive_scan(
471471
472472 assert_reply (reply )
473473
474- # It is important to export after registering, otherwise BlueZ
475- # won't use the monitor
474+ # It is important to export AFTER registering, otherwise BlueZ won't use the monitor
476475 self ._bus .export (monitor_path , monitor )
477476
477+ # During export, MGMT command "Add Advertisement Patterns Monitor (0x0052)" is executed.
478+ # If Linux kernel is too old to support this command, MGMT event "Command Status (0x0002)"
479+ # is returned with "Status: Unknown Command (0x01)" - bleak cannot detect this error and
480+ # trying to scan would result in no devices ever reported, as Adv. Monitor was not registered.
481+ # Running bluetoothd with -d flag gives the following output for 'journalctl --unit=bluetooth -f':
482+ # bluetoothd[...]: Path /org/bleak/.../AdvertisementMonitor... reserved for Adv Monitor app :...
483+ # ...
484+ # bluetoothd[...]: src/shared/mgmt.c:send_request() [0x0000] command 0x0052
485+ # bluetoothd[...]: src/shared/mgmt.c:can_read_data() [0x0000] command 0x52 status: 0x01
486+ # bluetoothd[...]: Failed to Add Adv Patterns Monitor with status 0x01
487+ # bluetoothd[...]: src/adv_monitor.c:monitor_release() Calling Release() on Adv Monitor
488+ # of owner :... at path /org/bleak/.../AdvertisementMonitor...
489+ # bluetoothd[...]: Merged_pattern not found when removing monitor
490+ # ...
491+ # Note that `monitor.Release()` cannot be invoked if control is not passed to the event loop.
492+ # Rather than using asyncio.sleep(), read property to ensure that all queued D-Bus calls are executed.
493+ reply = await self ._bus .call (
494+ Message (
495+ destination = defs .BLUEZ_SERVICE ,
496+ path = adapter_path ,
497+ interface = defs .PROPERTIES_INTERFACE ,
498+ member = "Get" ,
499+ signature = "ss" ,
500+ body = [
501+ defs .ADVERTISEMENT_MONITOR_MANAGER_INTERFACE ,
502+ "SupportedFeatures" ,
503+ ],
504+ )
505+ )
506+ assert_reply (reply )
507+
508+ # Monitor might not be Activate-d yet, but for sure it shall not be Release-d
509+ if monitor .active is False :
510+ raise BleakError (
511+ "Advertising Monitor (required for passive scanning) is not supported by this kernel"
512+ " (Linux kernel >= 5.10 is required)"
513+ )
514+
478515 async def stop ():
479516 # need to remove callbacks first, otherwise we get TxPower
480517 # and RSSI properties removed during stop which causes
0 commit comments