Loading system/gd/rust/linux/client/src/command_handler.rs +10 −7 Original line number Diff line number Diff line Loading @@ -9,7 +9,9 @@ use bt_topshim::btif::{BtConnectionState, BtStatus, BtTransport}; use bt_topshim::profiles::gatt::LePhy; use btstack::bluetooth::{BluetoothDevice, IBluetooth, IBluetoothQA}; use btstack::bluetooth_adv::{AdvertiseData, AdvertisingSetParameters}; use btstack::bluetooth_gatt::{IBluetoothGatt, RSSISettings, ScanSettings, ScanType}; use btstack::bluetooth_gatt::{ IBluetoothGatt, ScanFilter, ScanFilterCondition, ScanSettings, ScanType, }; use btstack::socket_manager::{IBluetoothSocketManager, SocketResult}; use btstack::uuid::{Profile, UuidHelper, UuidWrapper}; use manager_service::iface_bluetooth_manager::IBluetoothManager; Loading Loading @@ -866,13 +868,14 @@ impl CommandHandler { self.context.lock().unwrap().gatt_dbus.as_mut().unwrap().start_scan( id, // TODO(b/217274432): Construct real settings and filters. ScanSettings { interval: 0, window: 0, rssi_settings: RSSISettings { high_threshold: 0, low_threshold: 0 }, scan_type: ScanType::Active, ScanSettings { interval: 0, window: 0, scan_type: ScanType::Active }, ScanFilter { condition: ScanFilterCondition::Patterns(vec![]), rssi_low_threshold: 0, rssi_low_timeout: 0, rssi_high_threshold: 0, rssi_sampling_period: 0, }, vec![], ); self.context.lock().unwrap().active_scanner_ids.insert(id); } else { Loading system/gd/rust/linux/client/src/dbus_iface.rs +94 −10 Original line number Diff line number Diff line Loading @@ -16,7 +16,8 @@ use btstack::bluetooth_adv::{ use btstack::bluetooth_gatt::{ BluetoothGattCharacteristic, BluetoothGattDescriptor, BluetoothGattService, GattWriteRequestStatus, GattWriteType, IBluetoothGatt, IBluetoothGattCallback, IScannerCallback, RSSISettings, ScanFilter, ScanResult, ScanSettings, ScanType, IScannerCallback, ScanFilter, ScanFilterCondition, ScanFilterPattern, ScanResult, ScanSettings, ScanType, }; use btstack::socket_manager::{ BluetoothServerSocket, BluetoothSocket, CallbackId, IBluetoothSocketManager, Loading Loading @@ -134,22 +135,105 @@ pub struct BluetoothDeviceDBus { name: String, } #[dbus_propmap(RSSISettings)] pub struct RSSISettingsDBus { low_threshold: i32, high_threshold: i32, } #[dbus_propmap(ScanSettings)] struct ScanSettingsDBus { interval: i32, window: i32, scan_type: ScanType, rssi_settings: RSSISettings, } #[dbus_propmap(ScanFilterPattern)] struct ScanFilterPatternDBus { start_position: u8, ad_type: u8, content: Vec<u8>, } // Manually converts enum variant from/into D-Bus. // // The ScanFilterCondition enum variant is represented as a D-Bus dictionary with one and only one // member which key determines which variant it refers to and the value determines the data. // // For example, ScanFilterCondition::Patterns(data: Vec<u8>) is represented as: // array [ // dict entry( // string "patterns" // variant array [ ... ] // ) // ] // // And ScanFilterCondition::All is represented as: // array [ // dict entry( // string "all" // variant string "unit" // ) // ] // // If enum variant is used many times, we should find a way to avoid boilerplate. impl DBusArg for ScanFilterCondition { type DBusType = dbus::arg::PropMap; fn from_dbus( data: dbus::arg::PropMap, _conn: Option<std::sync::Arc<dbus::nonblock::SyncConnection>>, _remote: Option<dbus::strings::BusName<'static>>, _disconnect_watcher: Option< std::sync::Arc<std::sync::Mutex<dbus_projection::DisconnectWatcher>>, >, ) -> Result<ScanFilterCondition, Box<dyn std::error::Error>> { let variant = match data.get("patterns") { Some(variant) => variant, None => { return Err(Box::new(DBusArgError::new(String::from(format!( "ScanFilterCondition does not contain any enum variant", ))))); } }; match variant.arg_type() { dbus::arg::ArgType::Variant => {} _ => { return Err(Box::new(DBusArgError::new(String::from(format!( "ScanFilterCondition::Patterns must be a variant", ))))); } }; let patterns = <<Vec<ScanFilterPattern> as DBusArg>::DBusType as RefArgToRust>::ref_arg_to_rust( variant.as_static_inner(0).unwrap(), format!("ScanFilterCondition::Patterns"), )?; let patterns = Vec::<ScanFilterPattern>::from_dbus(patterns, None, None, None)?; return Ok(ScanFilterCondition::Patterns(patterns)); } fn to_dbus( condition: ScanFilterCondition, ) -> Result<dbus::arg::PropMap, Box<dyn std::error::Error>> { let mut map: dbus::arg::PropMap = std::collections::HashMap::new(); match condition { ScanFilterCondition::Patterns(patterns) => { map.insert( String::from("patterns"), dbus::arg::Variant(Box::new(DBusArg::to_dbus(patterns)?)), ); } _ => {} } return Ok(map); } } #[dbus_propmap(ScanFilter)] struct ScanFilterDBus {} struct ScanFilterDBus { rssi_high_threshold: i16, rssi_low_threshold: i16, rssi_low_timeout: u16, rssi_sampling_period: u16, condition: ScanFilterCondition, } #[dbus_propmap(ScanResult)] struct ScanResultDBus { Loading Loading @@ -781,7 +865,7 @@ impl IBluetoothGatt for BluetoothGattDBus { &mut self, _scanner_id: u8, _settings: ScanSettings, _filters: Vec<ScanFilter>, _filter: ScanFilter, ) -> BtStatus { dbus_generated!() } Loading system/gd/rust/linux/service/src/iface_bluetooth_gatt.rs +94 −10 Original line number Diff line number Diff line Loading @@ -7,7 +7,8 @@ use btstack::bluetooth_adv::{ use btstack::bluetooth_gatt::{ BluetoothGattCharacteristic, BluetoothGattDescriptor, BluetoothGattService, GattWriteRequestStatus, GattWriteType, IBluetoothGatt, IBluetoothGattCallback, IScannerCallback, RSSISettings, ScanFilter, ScanResult, ScanSettings, ScanType, IScannerCallback, ScanFilter, ScanFilterCondition, ScanFilterPattern, ScanResult, ScanSettings, ScanType, }; use btstack::{RPCProxy, SuspendMode}; Loading Loading @@ -200,18 +201,11 @@ pub struct BluetoothGattServiceDBus { included_services: Vec<BluetoothGattService>, } #[dbus_propmap(RSSISettings)] pub struct RSSISettingsDBus { low_threshold: i32, high_threshold: i32, } #[dbus_propmap(ScanSettings)] struct ScanSettingsDBus { interval: i32, window: i32, scan_type: ScanType, rssi_settings: RSSISettings, } #[dbus_propmap(ScanResult)] Loading @@ -235,8 +229,98 @@ impl_dbus_arg_enum!(LePhy); impl_dbus_arg_enum!(ScanType); impl_dbus_arg_enum!(SuspendMode); #[dbus_propmap(ScanFilterPattern)] struct ScanFilterPatternDBus { start_position: u8, ad_type: u8, content: Vec<u8>, } // Manually converts enum variant from/into D-Bus. // // The ScanFilterCondition enum variant is represented as a D-Bus dictionary with one and only one // member which key determines which variant it refers to and the value determines the data. // // For example, ScanFilterCondition::Patterns(data: Vec<u8>) is represented as: // array [ // dict entry( // string "patterns" // variant array [ ... ] // ) // ] // // And ScanFilterCondition::All is represented as: // array [ // dict entry( // string "all" // variant string "unit" // ) // ] // // If enum variant is used many times, we should find a way to avoid boilerplate. impl DBusArg for ScanFilterCondition { type DBusType = dbus::arg::PropMap; fn from_dbus( data: dbus::arg::PropMap, _conn: Option<std::sync::Arc<dbus::nonblock::SyncConnection>>, _remote: Option<dbus::strings::BusName<'static>>, _disconnect_watcher: Option< std::sync::Arc<std::sync::Mutex<dbus_projection::DisconnectWatcher>>, >, ) -> Result<ScanFilterCondition, Box<dyn std::error::Error>> { let variant = match data.get("patterns") { Some(variant) => variant, None => { return Err(Box::new(DBusArgError::new(String::from(format!( "ScanFilterCondition does not contain any enum variant", ))))); } }; match variant.arg_type() { dbus::arg::ArgType::Variant => {} _ => { return Err(Box::new(DBusArgError::new(String::from(format!( "ScanFilterCondition::Patterns must be a variant", ))))); } }; let patterns = <<Vec<ScanFilterPattern> as DBusArg>::DBusType as RefArgToRust>::ref_arg_to_rust( variant.as_static_inner(0).unwrap(), format!("ScanFilterCondition::Patterns"), )?; let patterns = Vec::<ScanFilterPattern>::from_dbus(patterns, None, None, None)?; return Ok(ScanFilterCondition::Patterns(patterns)); } fn to_dbus( condition: ScanFilterCondition, ) -> Result<dbus::arg::PropMap, Box<dyn std::error::Error>> { let mut map: dbus::arg::PropMap = std::collections::HashMap::new(); match condition { ScanFilterCondition::Patterns(patterns) => { map.insert( String::from("patterns"), dbus::arg::Variant(Box::new(DBusArg::to_dbus(patterns)?)), ); } _ => {} } return Ok(map); } } #[dbus_propmap(ScanFilter)] struct ScanFilterDBus {} struct ScanFilterDBus { rssi_high_threshold: i16, rssi_low_threshold: i16, rssi_low_timeout: u16, rssi_sampling_period: u16, condition: ScanFilterCondition, } #[allow(dead_code)] struct AdvertisingSetCallbackDBus {} Loading Loading @@ -373,7 +457,7 @@ impl IBluetoothGatt for IBluetoothGattDBus { &mut self, scanner_id: u8, settings: ScanSettings, filters: Vec<ScanFilter>, filter: ScanFilter, ) -> BtStatus { dbus_generated!() } Loading system/gd/rust/linux/stack/src/bluetooth_gatt.rs +62 −13 Original line number Diff line number Diff line Loading @@ -203,7 +203,7 @@ pub trait IBluetoothGatt { &mut self, scanner_id: u8, settings: ScanSettings, filters: Vec<ScanFilter>, filter: ScanFilter, ) -> BtStatus; /// Deactivate scan of the given scanner id. Loading Loading @@ -617,21 +617,15 @@ impl Default for ScanType { } } /// Represents RSSI configurations for hardware offloaded scanning. // TODO(b/200066804): This is still a placeholder struct, not yet complete. #[derive(Debug, Default)] pub struct RSSISettings { pub low_threshold: i32, pub high_threshold: i32, } /// Represents scanning configurations to be passed to `IBluetoothGatt::start_scan`. /// /// This configuration is general and supported on all Bluetooth hardware, irrelevant of the /// hardware filter offload (APCF or MSFT). #[derive(Debug, Default)] pub struct ScanSettings { pub interval: i32, pub window: i32, pub scan_type: ScanType, pub rssi_settings: RSSISettings, } /// Represents scan result Loading @@ -649,9 +643,64 @@ pub struct ScanResult { pub adv_data: Vec<u8>, } #[derive(Debug)] pub struct ScanFilterPattern { /// Specifies the starting byte position of the pattern immediately following AD Type. pub start_position: u8, /// Advertising Data type (https://www.bluetooth.com/specifications/assigned-numbers/). pub ad_type: u8, /// The pattern to be matched for the specified AD Type within the advertisement packet from /// the specified starting byte. pub content: Vec<u8>, } /// Represents the condition for matching advertisements. /// /// Only pattern-based matching is implemented. #[derive(Debug)] pub enum ScanFilterCondition { /// All advertisements are matched. All, /// Match by pattern anywhere in the advertisement data. Multiple patterns are "OR"-ed. Patterns(Vec<ScanFilterPattern>), /// Match by UUID (not implemented). Uuid, /// Match if the IRK resolves an advertisement (not implemented). Irk, /// Match by Bluetooth address (not implemented). BluetoothAddress, } /// Represents a scan filter to be passed to `IBluetoothGatt::start_scan`. #[derive(Debug, Default)] pub struct ScanFilter {} /// /// This filter is intentionally modelled close to the MSFT hardware offload filter. /// Reference: /// https://learn.microsoft.com/en-us/windows-hardware/drivers/bluetooth/microsoft-defined-bluetooth-hci-commands-and-events #[derive(Debug)] pub struct ScanFilter { /// Advertisements with RSSI above or equal this value is considered "found". pub rssi_high_threshold: i16, /// Advertisements with RSSI below or equal this value (for a period of rssi_low_timeout) is /// considered "lost". pub rssi_low_threshold: i16, /// The time in seconds over which the RSSI value should be below rssi_low_threshold before /// being considered "lost". pub rssi_low_timeout: u16, /// The sampling interval in milliseconds. pub rssi_sampling_period: u16, /// The condition to match advertisements with. pub condition: ScanFilterCondition, } /// Implementation of the GATT API (IBluetoothGatt). pub struct BluetoothGatt { Loading Loading @@ -901,7 +950,7 @@ impl IBluetoothGatt for BluetoothGatt { &mut self, scanner_id: u8, _settings: ScanSettings, _filters: Vec<ScanFilter>, _filter: ScanFilter, ) -> BtStatus { // Multiplexing scanners happens at this layer. The implementations of start_scan // and stop_scan maintains the state of all registered scanners and based on the states Loading Loading
system/gd/rust/linux/client/src/command_handler.rs +10 −7 Original line number Diff line number Diff line Loading @@ -9,7 +9,9 @@ use bt_topshim::btif::{BtConnectionState, BtStatus, BtTransport}; use bt_topshim::profiles::gatt::LePhy; use btstack::bluetooth::{BluetoothDevice, IBluetooth, IBluetoothQA}; use btstack::bluetooth_adv::{AdvertiseData, AdvertisingSetParameters}; use btstack::bluetooth_gatt::{IBluetoothGatt, RSSISettings, ScanSettings, ScanType}; use btstack::bluetooth_gatt::{ IBluetoothGatt, ScanFilter, ScanFilterCondition, ScanSettings, ScanType, }; use btstack::socket_manager::{IBluetoothSocketManager, SocketResult}; use btstack::uuid::{Profile, UuidHelper, UuidWrapper}; use manager_service::iface_bluetooth_manager::IBluetoothManager; Loading Loading @@ -866,13 +868,14 @@ impl CommandHandler { self.context.lock().unwrap().gatt_dbus.as_mut().unwrap().start_scan( id, // TODO(b/217274432): Construct real settings and filters. ScanSettings { interval: 0, window: 0, rssi_settings: RSSISettings { high_threshold: 0, low_threshold: 0 }, scan_type: ScanType::Active, ScanSettings { interval: 0, window: 0, scan_type: ScanType::Active }, ScanFilter { condition: ScanFilterCondition::Patterns(vec![]), rssi_low_threshold: 0, rssi_low_timeout: 0, rssi_high_threshold: 0, rssi_sampling_period: 0, }, vec![], ); self.context.lock().unwrap().active_scanner_ids.insert(id); } else { Loading
system/gd/rust/linux/client/src/dbus_iface.rs +94 −10 Original line number Diff line number Diff line Loading @@ -16,7 +16,8 @@ use btstack::bluetooth_adv::{ use btstack::bluetooth_gatt::{ BluetoothGattCharacteristic, BluetoothGattDescriptor, BluetoothGattService, GattWriteRequestStatus, GattWriteType, IBluetoothGatt, IBluetoothGattCallback, IScannerCallback, RSSISettings, ScanFilter, ScanResult, ScanSettings, ScanType, IScannerCallback, ScanFilter, ScanFilterCondition, ScanFilterPattern, ScanResult, ScanSettings, ScanType, }; use btstack::socket_manager::{ BluetoothServerSocket, BluetoothSocket, CallbackId, IBluetoothSocketManager, Loading Loading @@ -134,22 +135,105 @@ pub struct BluetoothDeviceDBus { name: String, } #[dbus_propmap(RSSISettings)] pub struct RSSISettingsDBus { low_threshold: i32, high_threshold: i32, } #[dbus_propmap(ScanSettings)] struct ScanSettingsDBus { interval: i32, window: i32, scan_type: ScanType, rssi_settings: RSSISettings, } #[dbus_propmap(ScanFilterPattern)] struct ScanFilterPatternDBus { start_position: u8, ad_type: u8, content: Vec<u8>, } // Manually converts enum variant from/into D-Bus. // // The ScanFilterCondition enum variant is represented as a D-Bus dictionary with one and only one // member which key determines which variant it refers to and the value determines the data. // // For example, ScanFilterCondition::Patterns(data: Vec<u8>) is represented as: // array [ // dict entry( // string "patterns" // variant array [ ... ] // ) // ] // // And ScanFilterCondition::All is represented as: // array [ // dict entry( // string "all" // variant string "unit" // ) // ] // // If enum variant is used many times, we should find a way to avoid boilerplate. impl DBusArg for ScanFilterCondition { type DBusType = dbus::arg::PropMap; fn from_dbus( data: dbus::arg::PropMap, _conn: Option<std::sync::Arc<dbus::nonblock::SyncConnection>>, _remote: Option<dbus::strings::BusName<'static>>, _disconnect_watcher: Option< std::sync::Arc<std::sync::Mutex<dbus_projection::DisconnectWatcher>>, >, ) -> Result<ScanFilterCondition, Box<dyn std::error::Error>> { let variant = match data.get("patterns") { Some(variant) => variant, None => { return Err(Box::new(DBusArgError::new(String::from(format!( "ScanFilterCondition does not contain any enum variant", ))))); } }; match variant.arg_type() { dbus::arg::ArgType::Variant => {} _ => { return Err(Box::new(DBusArgError::new(String::from(format!( "ScanFilterCondition::Patterns must be a variant", ))))); } }; let patterns = <<Vec<ScanFilterPattern> as DBusArg>::DBusType as RefArgToRust>::ref_arg_to_rust( variant.as_static_inner(0).unwrap(), format!("ScanFilterCondition::Patterns"), )?; let patterns = Vec::<ScanFilterPattern>::from_dbus(patterns, None, None, None)?; return Ok(ScanFilterCondition::Patterns(patterns)); } fn to_dbus( condition: ScanFilterCondition, ) -> Result<dbus::arg::PropMap, Box<dyn std::error::Error>> { let mut map: dbus::arg::PropMap = std::collections::HashMap::new(); match condition { ScanFilterCondition::Patterns(patterns) => { map.insert( String::from("patterns"), dbus::arg::Variant(Box::new(DBusArg::to_dbus(patterns)?)), ); } _ => {} } return Ok(map); } } #[dbus_propmap(ScanFilter)] struct ScanFilterDBus {} struct ScanFilterDBus { rssi_high_threshold: i16, rssi_low_threshold: i16, rssi_low_timeout: u16, rssi_sampling_period: u16, condition: ScanFilterCondition, } #[dbus_propmap(ScanResult)] struct ScanResultDBus { Loading Loading @@ -781,7 +865,7 @@ impl IBluetoothGatt for BluetoothGattDBus { &mut self, _scanner_id: u8, _settings: ScanSettings, _filters: Vec<ScanFilter>, _filter: ScanFilter, ) -> BtStatus { dbus_generated!() } Loading
system/gd/rust/linux/service/src/iface_bluetooth_gatt.rs +94 −10 Original line number Diff line number Diff line Loading @@ -7,7 +7,8 @@ use btstack::bluetooth_adv::{ use btstack::bluetooth_gatt::{ BluetoothGattCharacteristic, BluetoothGattDescriptor, BluetoothGattService, GattWriteRequestStatus, GattWriteType, IBluetoothGatt, IBluetoothGattCallback, IScannerCallback, RSSISettings, ScanFilter, ScanResult, ScanSettings, ScanType, IScannerCallback, ScanFilter, ScanFilterCondition, ScanFilterPattern, ScanResult, ScanSettings, ScanType, }; use btstack::{RPCProxy, SuspendMode}; Loading Loading @@ -200,18 +201,11 @@ pub struct BluetoothGattServiceDBus { included_services: Vec<BluetoothGattService>, } #[dbus_propmap(RSSISettings)] pub struct RSSISettingsDBus { low_threshold: i32, high_threshold: i32, } #[dbus_propmap(ScanSettings)] struct ScanSettingsDBus { interval: i32, window: i32, scan_type: ScanType, rssi_settings: RSSISettings, } #[dbus_propmap(ScanResult)] Loading @@ -235,8 +229,98 @@ impl_dbus_arg_enum!(LePhy); impl_dbus_arg_enum!(ScanType); impl_dbus_arg_enum!(SuspendMode); #[dbus_propmap(ScanFilterPattern)] struct ScanFilterPatternDBus { start_position: u8, ad_type: u8, content: Vec<u8>, } // Manually converts enum variant from/into D-Bus. // // The ScanFilterCondition enum variant is represented as a D-Bus dictionary with one and only one // member which key determines which variant it refers to and the value determines the data. // // For example, ScanFilterCondition::Patterns(data: Vec<u8>) is represented as: // array [ // dict entry( // string "patterns" // variant array [ ... ] // ) // ] // // And ScanFilterCondition::All is represented as: // array [ // dict entry( // string "all" // variant string "unit" // ) // ] // // If enum variant is used many times, we should find a way to avoid boilerplate. impl DBusArg for ScanFilterCondition { type DBusType = dbus::arg::PropMap; fn from_dbus( data: dbus::arg::PropMap, _conn: Option<std::sync::Arc<dbus::nonblock::SyncConnection>>, _remote: Option<dbus::strings::BusName<'static>>, _disconnect_watcher: Option< std::sync::Arc<std::sync::Mutex<dbus_projection::DisconnectWatcher>>, >, ) -> Result<ScanFilterCondition, Box<dyn std::error::Error>> { let variant = match data.get("patterns") { Some(variant) => variant, None => { return Err(Box::new(DBusArgError::new(String::from(format!( "ScanFilterCondition does not contain any enum variant", ))))); } }; match variant.arg_type() { dbus::arg::ArgType::Variant => {} _ => { return Err(Box::new(DBusArgError::new(String::from(format!( "ScanFilterCondition::Patterns must be a variant", ))))); } }; let patterns = <<Vec<ScanFilterPattern> as DBusArg>::DBusType as RefArgToRust>::ref_arg_to_rust( variant.as_static_inner(0).unwrap(), format!("ScanFilterCondition::Patterns"), )?; let patterns = Vec::<ScanFilterPattern>::from_dbus(patterns, None, None, None)?; return Ok(ScanFilterCondition::Patterns(patterns)); } fn to_dbus( condition: ScanFilterCondition, ) -> Result<dbus::arg::PropMap, Box<dyn std::error::Error>> { let mut map: dbus::arg::PropMap = std::collections::HashMap::new(); match condition { ScanFilterCondition::Patterns(patterns) => { map.insert( String::from("patterns"), dbus::arg::Variant(Box::new(DBusArg::to_dbus(patterns)?)), ); } _ => {} } return Ok(map); } } #[dbus_propmap(ScanFilter)] struct ScanFilterDBus {} struct ScanFilterDBus { rssi_high_threshold: i16, rssi_low_threshold: i16, rssi_low_timeout: u16, rssi_sampling_period: u16, condition: ScanFilterCondition, } #[allow(dead_code)] struct AdvertisingSetCallbackDBus {} Loading Loading @@ -373,7 +457,7 @@ impl IBluetoothGatt for IBluetoothGattDBus { &mut self, scanner_id: u8, settings: ScanSettings, filters: Vec<ScanFilter>, filter: ScanFilter, ) -> BtStatus { dbus_generated!() } Loading
system/gd/rust/linux/stack/src/bluetooth_gatt.rs +62 −13 Original line number Diff line number Diff line Loading @@ -203,7 +203,7 @@ pub trait IBluetoothGatt { &mut self, scanner_id: u8, settings: ScanSettings, filters: Vec<ScanFilter>, filter: ScanFilter, ) -> BtStatus; /// Deactivate scan of the given scanner id. Loading Loading @@ -617,21 +617,15 @@ impl Default for ScanType { } } /// Represents RSSI configurations for hardware offloaded scanning. // TODO(b/200066804): This is still a placeholder struct, not yet complete. #[derive(Debug, Default)] pub struct RSSISettings { pub low_threshold: i32, pub high_threshold: i32, } /// Represents scanning configurations to be passed to `IBluetoothGatt::start_scan`. /// /// This configuration is general and supported on all Bluetooth hardware, irrelevant of the /// hardware filter offload (APCF or MSFT). #[derive(Debug, Default)] pub struct ScanSettings { pub interval: i32, pub window: i32, pub scan_type: ScanType, pub rssi_settings: RSSISettings, } /// Represents scan result Loading @@ -649,9 +643,64 @@ pub struct ScanResult { pub adv_data: Vec<u8>, } #[derive(Debug)] pub struct ScanFilterPattern { /// Specifies the starting byte position of the pattern immediately following AD Type. pub start_position: u8, /// Advertising Data type (https://www.bluetooth.com/specifications/assigned-numbers/). pub ad_type: u8, /// The pattern to be matched for the specified AD Type within the advertisement packet from /// the specified starting byte. pub content: Vec<u8>, } /// Represents the condition for matching advertisements. /// /// Only pattern-based matching is implemented. #[derive(Debug)] pub enum ScanFilterCondition { /// All advertisements are matched. All, /// Match by pattern anywhere in the advertisement data. Multiple patterns are "OR"-ed. Patterns(Vec<ScanFilterPattern>), /// Match by UUID (not implemented). Uuid, /// Match if the IRK resolves an advertisement (not implemented). Irk, /// Match by Bluetooth address (not implemented). BluetoothAddress, } /// Represents a scan filter to be passed to `IBluetoothGatt::start_scan`. #[derive(Debug, Default)] pub struct ScanFilter {} /// /// This filter is intentionally modelled close to the MSFT hardware offload filter. /// Reference: /// https://learn.microsoft.com/en-us/windows-hardware/drivers/bluetooth/microsoft-defined-bluetooth-hci-commands-and-events #[derive(Debug)] pub struct ScanFilter { /// Advertisements with RSSI above or equal this value is considered "found". pub rssi_high_threshold: i16, /// Advertisements with RSSI below or equal this value (for a period of rssi_low_timeout) is /// considered "lost". pub rssi_low_threshold: i16, /// The time in seconds over which the RSSI value should be below rssi_low_threshold before /// being considered "lost". pub rssi_low_timeout: u16, /// The sampling interval in milliseconds. pub rssi_sampling_period: u16, /// The condition to match advertisements with. pub condition: ScanFilterCondition, } /// Implementation of the GATT API (IBluetoothGatt). pub struct BluetoothGatt { Loading Loading @@ -901,7 +950,7 @@ impl IBluetoothGatt for BluetoothGatt { &mut self, scanner_id: u8, _settings: ScanSettings, _filters: Vec<ScanFilter>, _filter: ScanFilter, ) -> BtStatus { // Multiplexing scanners happens at this layer. The implementations of start_scan // and stop_scan maintains the state of all registered scanners and based on the states Loading