From aa402e5e8c7cbd2e774a924f5e67113d97c53402 Mon Sep 17 00:00:00 2001 From: Jakub Janata Date: Wed, 30 Sep 2026 14:31:18 +0200 Subject: [PATCH] feat(winrtble): allow overriding Coded PHY support On some adapters that report Coded PHY support, scanning with UseCodedPhy enabled drops most 1M PHY advertisements: only frequent random-address beacons get through, while ordinary devices (named devices, peripherals with a public address advertising every ~2 s) are never reported, even right next to the PC. The same machine finds them with UseCodedPhy disabled. Add Adapter::set_coded_phy_supported on Windows to override the detected support. SetUseCodedPhy is now called on every scan, since the watcher is reused and the value can change between scans. Behavior is unchanged unless the override is used. --- src/winrtble/adapter.rs | 10 ++++++++++ src/winrtble/ble/watcher.rs | 18 +++++++++++------- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/winrtble/adapter.rs b/src/winrtble/adapter.rs index a7348f8d..a7e33140 100644 --- a/src/winrtble/adapter.rs +++ b/src/winrtble/adapter.rs @@ -128,6 +128,16 @@ impl Adapter { _state_handler: state_handler, }) } + + /// Overrides whether the adapter is treated as supporting the Coded (long-range) PHY. + /// With `false`, scans never request Coded PHY. Some adapters that report support stop + /// delivering most 1M PHY advertisements with it enabled. Takes effect on the next + /// [`Central::start_scan`]. + pub fn set_coded_phy_supported(&self, supported: bool) -> Result<()> { + let mut watcher = self.watcher.lock().map_err(Into::::into)?; + watcher.set_coded_phy_supported(supported); + Ok(()) + } } #[cfg(test)] diff --git a/src/winrtble/ble/watcher.rs b/src/winrtble/ble/watcher.rs index c9564087..683faa57 100644 --- a/src/winrtble/ble/watcher.rs +++ b/src/winrtble/ble/watcher.rs @@ -25,9 +25,10 @@ pub type AdvertisementEventHandler = pub struct BLEWatcher { watcher: BluetoothLEAdvertisementWatcher, received_token: Option, - /// Whether the adapter reports Coded (long-range) PHY support. Only - /// then is `UseCodedPhy` requested: the setter succeeds on any adapter, - /// and on one without Coded PHY the scan starts but never reports. + /// Whether the adapter reports Coded (long-range) PHY support, unless + /// overridden by `Adapter::set_coded_phy_supported`. Only then is + /// `UseCodedPhy` requested: the setter succeeds on any adapter, and on + /// one without Coded PHY the scan starts but never reports. coded_phy_supported: bool, } @@ -65,6 +66,10 @@ impl BLEWatcher { }) } + pub fn set_coded_phy_supported(&mut self, supported: bool) { + self.coded_phy_supported = supported; + } + pub fn start( &mut self, filter: ScanFilter, @@ -87,10 +92,9 @@ impl BLEWatcher { // adapter supports it. `SetUseCodedPhy(true)` is accepted (and // `Start` succeeds) on adapters without Coded PHY as well, and the // scan then delivers no advertisements at all, so the capability - // check is the guard rather than the setter's result. - if self.coded_phy_supported { - let _ = self.watcher.SetUseCodedPhy(true); - } + // check is the guard rather than the setter's result. Set it on every + // scan: the watcher is reused and the flag can change between scans. + let _ = self.watcher.SetUseCodedPhy(self.coded_phy_supported); debug!( "extended scanning enabled; coded PHY {}", if self.coded_phy_supported {