Loading system/gd/rust/linux/client/src/callbacks.rs +46 −3 Original line number Diff line number Diff line Loading @@ -2,8 +2,8 @@ use crate::dbus_iface::{ export_admin_policy_callback_dbus_intf, export_advertising_set_callback_dbus_intf, export_bluetooth_callback_dbus_intf, export_bluetooth_connection_callback_dbus_intf, export_bluetooth_gatt_callback_dbus_intf, export_bluetooth_manager_callback_dbus_intf, export_scanner_callback_dbus_intf, export_socket_callback_dbus_intf, export_suspend_callback_dbus_intf, export_gatt_server_callback_dbus_intf, export_scanner_callback_dbus_intf, export_socket_callback_dbus_intf, export_suspend_callback_dbus_intf, }; use crate::ClientContext; use crate::{console_red, console_yellow, print_error, print_info}; Loading @@ -15,7 +15,8 @@ use btstack::bluetooth::{ use btstack::bluetooth_admin::{IBluetoothAdminPolicyCallback, PolicyEffect}; use btstack::bluetooth_adv::IAdvertisingSetCallback; use btstack::bluetooth_gatt::{ BluetoothGattService, IBluetoothGattCallback, IScannerCallback, ScanResult, BluetoothGattService, IBluetoothGattCallback, IBluetoothGattServerCallback, IScannerCallback, ScanResult, }; use btstack::socket_manager::{ BluetoothServerSocket, BluetoothSocket, IBluetoothSocketManager, Loading Loading @@ -738,6 +739,48 @@ impl RPCProxy for BtGattCallback { } } pub(crate) struct BtGattServerCallback { objpath: String, _context: Arc<Mutex<ClientContext>>, dbus_connection: Arc<SyncConnection>, dbus_crossroads: Arc<Mutex<Crossroads>>, } impl BtGattServerCallback { pub(crate) fn new( objpath: String, _context: Arc<Mutex<ClientContext>>, dbus_connection: Arc<SyncConnection>, dbus_crossroads: Arc<Mutex<Crossroads>>, ) -> Self { Self { objpath, _context, dbus_connection, dbus_crossroads } } } impl IBluetoothGattServerCallback for BtGattServerCallback { fn on_server_registered(&self, status: GattStatus, server_id: i32) { print_info!("GATT Server registered status = {}, server_id = {}", status, server_id); } } impl RPCProxy for BtGattServerCallback { fn get_object_id(&self) -> String { self.objpath.clone() } fn export_for_rpc(self: Box<Self>) { let cr = self.dbus_crossroads.clone(); let iface = export_gatt_server_callback_dbus_intf( self.dbus_connection.clone(), &mut cr.lock().unwrap(), Arc::new(Mutex::new(DisconnectWatcher::new())), ); cr.lock().unwrap().insert(self.get_object_id(), &[iface], Arc::new(Mutex::new(self))); } } pub(crate) struct BtSocketManagerCallback { objpath: String, context: Arc<Mutex<ClientContext>>, Loading system/gd/rust/linux/client/src/command_handler.rs +20 −1 Original line number Diff line number Diff line Loading @@ -5,7 +5,7 @@ use std::sync::{Arc, Mutex}; use crate::bt_adv::AdvSet; use crate::bt_gatt::AuthReq; use crate::callbacks::BtGattCallback; use crate::callbacks::{BtGattCallback, BtGattServerCallback}; use crate::ClientContext; use crate::{console_red, console_yellow, print_error, print_info}; use bt_topshim::btif::{BtConnectionState, BtStatus, BtTransport}; Loading @@ -21,6 +21,7 @@ const BAR1_CHAR: &str = "="; const BAR2_CHAR: &str = "-"; const MAX_MENU_CHAR_WIDTH: usize = 72; const GATT_CLIENT_APP_UUID: &str = "12345678123456781234567812345678"; const GATT_SERVER_APP_UUID: &str = "12345678123456781234567812345679"; enum CommandError { // Command not handled due to invalid arguments. Loading Loading @@ -169,6 +170,7 @@ fn build_commands() -> HashMap<String, CommandOption> { "gatt write-characteristic <address> <handle> <NoRsp|Write|Prepare> <value>", ), String::from("gatt read-characteristic <address> <handle>"), String::from("gatt register-server"), ], description: String::from("GATT tools"), function_pointer: CommandHandler::cmd_gatt, Loading Loading @@ -1076,6 +1078,23 @@ impl CommandHandler { .unwrap() .read_characteristic(client_id, addr, handle, auth_req); } "register-server" => { let dbus_connection = self.context.lock().unwrap().dbus_connection.clone(); let dbus_crossroads = self.context.lock().unwrap().dbus_crossroads.clone(); self.context.lock().unwrap().gatt_dbus.as_mut().unwrap().register_server( String::from(GATT_SERVER_APP_UUID), Box::new(BtGattServerCallback::new( String::from( "/org/chromium/bluetooth/client/bluetooth_gatt_server_callback", ), self.context.clone(), dbus_connection, dbus_crossroads, )), false, ); } _ => return Err(CommandError::InvalidArgs), } Ok(()) Loading system/gd/rust/linux/client/src/dbus_iface.rs +28 −2 Original line number Diff line number Diff line Loading @@ -18,8 +18,8 @@ use btstack::bluetooth_adv::{ use btstack::bluetooth_gatt::{ BluetoothGattCharacteristic, BluetoothGattDescriptor, BluetoothGattService, GattWriteRequestStatus, GattWriteType, IBluetoothGatt, IBluetoothGattCallback, IScannerCallback, ScanFilter, ScanFilterCondition, ScanFilterPattern, ScanResult, ScanSettings, ScanType, IBluetoothGattServerCallback, IScannerCallback, ScanFilter, ScanFilterCondition, ScanFilterPattern, ScanResult, ScanSettings, ScanType, }; use btstack::socket_manager::{ BluetoothServerSocket, BluetoothSocket, CallbackId, IBluetoothSocketManager, Loading Loading @@ -1264,6 +1264,23 @@ impl IBluetoothGatt for BluetoothGattDBus { ) { dbus_generated!() } // GATT Server #[dbus_method("RegisterServer")] fn register_server( &mut self, app_uuid: String, callback: Box<dyn IBluetoothGattServerCallback + Send>, eatt_support: bool, ) { dbus_generated!() } #[dbus_method("UnregisterServer")] fn unregister_server(&mut self, server_id: i32) { dbus_generated!() } } struct IBluetoothGattCallbackDBus {} Loading Loading @@ -1349,6 +1366,15 @@ impl IBluetoothGattCallback for IBluetoothGattCallbackDBus { fn on_service_changed(&self, addr: String) {} } #[generate_dbus_exporter( export_gatt_server_callback_dbus_intf, "org.chromium.bluetooth.BluetoothGattServerCallback" )] impl IBluetoothGattServerCallback for IBluetoothGattCallbackDBus { #[dbus_method("OnServerRegistered")] fn on_server_registered(&self, status: GattStatus, client_id: i32) {} } #[dbus_propmap(BluetoothServerSocket)] pub struct BluetoothServerSocketDBus { id: SocketId, Loading system/gd/rust/linux/service/src/iface_bluetooth_gatt.rs +30 −2 Original line number Diff line number Diff line Loading @@ -8,8 +8,8 @@ use btstack::bluetooth_adv::{ use btstack::bluetooth_gatt::{ BluetoothGattCharacteristic, BluetoothGattDescriptor, BluetoothGattService, GattWriteRequestStatus, GattWriteType, IBluetoothGatt, IBluetoothGattCallback, IScannerCallback, ScanFilter, ScanFilterCondition, ScanFilterPattern, ScanResult, ScanSettings, ScanType, IBluetoothGattServerCallback, IScannerCallback, ScanFilter, ScanFilterCondition, ScanFilterPattern, ScanResult, ScanSettings, ScanType, }; use btstack::{RPCProxy, SuspendMode}; Loading Loading @@ -136,6 +136,17 @@ impl IBluetoothGattCallback for BluetoothGattCallbackDBus { } } #[allow(dead_code)] struct BluetoothGattServerCallbackDBus {} #[dbus_proxy_obj(BluetoothGattServerCallback, "org.chromium.bluetooth.BluetoothGattServerCallback")] impl IBluetoothGattServerCallback for BluetoothGattServerCallbackDBus { #[dbus_method("OnServerRegistered")] fn on_server_registered(&self, status: GattStatus, server_id: i32) { dbus_generated!() } } // Represents Uuid128Bit as an array in D-Bus. impl DBusArg for Uuid128Bit { type DBusType = Vec<u8>; Loading Loading @@ -747,4 +758,21 @@ impl IBluetoothGatt for IBluetoothGattDBus { fn client_read_phy(&mut self, client_id: i32, addr: String) { dbus_generated!() } // GATT Server #[dbus_method("RegisterServer")] fn register_server( &mut self, app_uuid: String, callback: Box<dyn IBluetoothGattServerCallback + Send>, eatt_support: bool, ) { dbus_generated!() } #[dbus_method("UnregisterServer")] fn unregister_server(&mut self, server_id: i32) { dbus_generated!() } } system/gd/rust/linux/stack/src/bluetooth_gatt.rs +169 −4 Original line number Diff line number Diff line Loading @@ -9,8 +9,8 @@ use bt_topshim::profiles::gatt::{ BtGattReadParams, Gatt, GattAdvCallbacks, GattAdvCallbacksDispatcher, GattAdvInbandCallbacksDispatcher, GattClientCallbacks, GattClientCallbacksDispatcher, GattScannerCallbacks, GattScannerCallbacksDispatcher, GattScannerInbandCallbacks, GattScannerInbandCallbacksDispatcher, GattServerCallbacksDispatcher, GattStatus, LePhy, MsftAdvMonitor, MsftAdvMonitorPattern, GattScannerInbandCallbacksDispatcher, GattServerCallbacks, GattServerCallbacksDispatcher, GattStatus, LePhy, MsftAdvMonitor, MsftAdvMonitorPattern, }; use bt_topshim::topstack; use bt_utils::adv_parser; Loading Loading @@ -180,6 +180,79 @@ impl ContextMap { } } struct Server { id: Option<i32>, cbid: u32, uuid: Uuid128Bit, } struct ServerContextMap { // TODO(b/196635530): Consider using `multimap` for a more efficient implementation of get by // multiple keys. callbacks: Callbacks<dyn IBluetoothGattServerCallback + Send>, servers: Vec<Server>, } type GattServerCallback = Box<dyn IBluetoothGattServerCallback + Send>; impl ServerContextMap { fn new(tx: Sender<Message>) -> ServerContextMap { ServerContextMap { callbacks: Callbacks::new(tx, Message::GattServerCallbackDisconnected), servers: vec![], } } fn get_by_uuid(&self, uuid: &Uuid128Bit) -> Option<&Server> { self.servers.iter().find(|server| server.uuid == *uuid) } fn get_by_server_id(&self, server_id: i32) -> Option<&Server> { self.servers.iter().find(|server| server.id.map_or(false, |id| id == server_id)) } fn get_by_callback_id(&self, callback_id: u32) -> Option<&Server> { self.servers.iter().find(|server| server.cbid == callback_id) } fn add(&mut self, uuid: &Uuid128Bit, callback: GattServerCallback) { if self.get_by_uuid(uuid).is_some() { return; } let cbid = self.callbacks.add_callback(callback); self.servers.push(Server { id: None, cbid, uuid: uuid.clone() }); } fn remove(&mut self, id: i32) { // Remove any callbacks if let Some(cbid) = self.get_by_server_id(id).map(|server| server.cbid) { self.remove_callback(cbid); } self.servers.retain(|server| !(server.id.is_some() && server.id.unwrap() == id)); } fn remove_callback(&mut self, callback_id: u32) { self.callbacks.remove_callback(callback_id); } fn set_server_id(&mut self, uuid: &Uuid128Bit, id: i32) { let server = self.servers.iter_mut().find(|server| server.uuid == *uuid); if let Some(s) = server { s.id = Some(id); } } fn get_callback_from_callback_id( &mut self, callback_id: u32, ) -> Option<&mut GattServerCallback> { self.callbacks.get_by_id(callback_id) } } /// Defines the GATT API. // TODO(242083290): Split out interfaces. pub trait IBluetoothGatt { Loading Loading @@ -425,6 +498,19 @@ pub trait IBluetoothGatt { /// Reads the PHY used by a peer. fn client_read_phy(&mut self, client_id: i32, addr: String); // GATT Server /// Registers a GATT Server. fn register_server( &mut self, app_uuid: String, callback: Box<dyn IBluetoothGattServerCallback + Send>, eatt_support: bool, ); /// Unregisters a GATT Server. fn unregister_server(&mut self, server_id: i32); } #[derive(Debug, Default)] Loading Loading @@ -580,6 +666,12 @@ pub trait IBluetoothGattCallback: RPCProxy { fn on_service_changed(&self, _addr: String); } /// Callback for GATT Server API. pub trait IBluetoothGattServerCallback: RPCProxy { /// When the `register_server` request is done. fn on_server_registered(&self, _status: GattStatus, _server_id: i32); } /// Interface for scanner callbacks to clients, passed to /// `IBluetoothGatt::register_scanner_callback`. pub trait IScannerCallback: RPCProxy { Loading Loading @@ -813,6 +905,7 @@ pub struct BluetoothGatt { adapter: Option<Arc<Mutex<Box<Bluetooth>>>>, context_map: ContextMap, server_context_map: ServerContextMap, reliable_queue: HashSet<String>, scanner_callbacks: Callbacks<dyn IScannerCallback + Send>, scanners: Arc<Mutex<ScannersMap>>, Loading Loading @@ -842,6 +935,7 @@ impl BluetoothGatt { gatt: None, adapter: None, context_map: ContextMap::new(tx.clone()), server_context_map: ServerContextMap::new(tx.clone()), reliable_queue: HashSet::new(), scanner_callbacks: Callbacks::new(tx.clone(), Message::ScannerCallbackDisconnected), scanners: scanners.clone(), Loading Loading @@ -874,10 +968,13 @@ impl BluetoothGatt { }), }; let tx_clone = tx.clone(); let gatt_server_callbacks_dispatcher = GattServerCallbacksDispatcher { dispatch: Box::new(move |cb| { // TODO(b/193685149): Implement the callbacks debug!("received Gatt server callback: {:?}", cb); let tx_clone = tx_clone.clone(); topstack::get_runtime().spawn(async move { let _ = tx_clone.send(Message::GattServer(cb)).await; }); }), }; Loading Loading @@ -1015,6 +1112,18 @@ impl BluetoothGatt { self.context_map.remove_callback(callback_id); } pub fn remove_server_callback(&mut self, callback_id: u32) { // Unregister server if server id exists. if let Some(server) = self.server_context_map.get_by_callback_id(callback_id) { if let Some(id) = server.id { self.unregister_server(id); } } // Always remove callback. self.context_map.remove_callback(callback_id); } /// Enters suspend mode for LE advertising. pub fn advertising_enter_suspend(&mut self) { self.advertisers.set_suspend_mode(SuspendMode::Suspending); Loading Loading @@ -1501,6 +1610,8 @@ impl IBluetoothGatt for BluetoothGatt { } } // GATT Client fn register_client( &mut self, app_uuid: String, Loading Loading @@ -1829,6 +1940,36 @@ impl IBluetoothGatt for BluetoothGatt { self.gatt.as_ref().unwrap().lock().unwrap().client.read_phy(client_id, &address); } // GATT Server fn register_server( &mut self, app_uuid: String, callback: Box<dyn IBluetoothGattServerCallback + Send>, eatt_support: bool, ) { let uuid = match UuidHelper::parse_string(&app_uuid) { Some(id) => id, None => { log::info!("Uuid is malformed: {}", app_uuid); return; } }; self.server_context_map.add(&uuid.uu, callback); self.gatt .as_ref() .expect("GATT has not been initialized") .lock() .unwrap() .server .register_server(&uuid, eatt_support); } fn unregister_server(&mut self, server_id: i32) { self.server_context_map.remove(server_id); self.gatt.as_ref().unwrap().lock().unwrap().server.unregister_server(server_id); } } #[btif_callbacks_dispatcher(dispatch_gatt_client_callbacks, GattClientCallbacks)] Loading Loading @@ -2430,6 +2571,30 @@ impl BtifGattClientCallbacks for BluetoothGatt { } } #[btif_callbacks_dispatcher(dispatch_gatt_server_callbacks, GattServerCallbacks)] pub(crate) trait BtifGattServerCallbacks { #[btif_callback(RegisterServer)] fn register_server_cb(&mut self, status: GattStatus, server_id: i32, app_uuid: Uuid); } impl BtifGattServerCallbacks for BluetoothGatt { fn register_server_cb(&mut self, status: GattStatus, server_id: i32, app_uuid: Uuid) { self.server_context_map.set_server_id(&app_uuid.uu, server_id); let cbid = self.server_context_map.get_by_uuid(&app_uuid.uu).map(|server| server.cbid); match cbid { Some(cbid) => { if let Some(cb) = self.server_context_map.get_callback_from_callback_id(cbid) { cb.on_server_registered(status, server_id) } } None => { warn!("Warning: No callback found for UUID {}", app_uuid); } } } } #[btif_callbacks_dispatcher(dispatch_le_scanner_callbacks, GattScannerCallbacks)] pub(crate) trait BtifGattScannerCallbacks { #[btif_callback(OnScannerRegistered)] Loading Loading
system/gd/rust/linux/client/src/callbacks.rs +46 −3 Original line number Diff line number Diff line Loading @@ -2,8 +2,8 @@ use crate::dbus_iface::{ export_admin_policy_callback_dbus_intf, export_advertising_set_callback_dbus_intf, export_bluetooth_callback_dbus_intf, export_bluetooth_connection_callback_dbus_intf, export_bluetooth_gatt_callback_dbus_intf, export_bluetooth_manager_callback_dbus_intf, export_scanner_callback_dbus_intf, export_socket_callback_dbus_intf, export_suspend_callback_dbus_intf, export_gatt_server_callback_dbus_intf, export_scanner_callback_dbus_intf, export_socket_callback_dbus_intf, export_suspend_callback_dbus_intf, }; use crate::ClientContext; use crate::{console_red, console_yellow, print_error, print_info}; Loading @@ -15,7 +15,8 @@ use btstack::bluetooth::{ use btstack::bluetooth_admin::{IBluetoothAdminPolicyCallback, PolicyEffect}; use btstack::bluetooth_adv::IAdvertisingSetCallback; use btstack::bluetooth_gatt::{ BluetoothGattService, IBluetoothGattCallback, IScannerCallback, ScanResult, BluetoothGattService, IBluetoothGattCallback, IBluetoothGattServerCallback, IScannerCallback, ScanResult, }; use btstack::socket_manager::{ BluetoothServerSocket, BluetoothSocket, IBluetoothSocketManager, Loading Loading @@ -738,6 +739,48 @@ impl RPCProxy for BtGattCallback { } } pub(crate) struct BtGattServerCallback { objpath: String, _context: Arc<Mutex<ClientContext>>, dbus_connection: Arc<SyncConnection>, dbus_crossroads: Arc<Mutex<Crossroads>>, } impl BtGattServerCallback { pub(crate) fn new( objpath: String, _context: Arc<Mutex<ClientContext>>, dbus_connection: Arc<SyncConnection>, dbus_crossroads: Arc<Mutex<Crossroads>>, ) -> Self { Self { objpath, _context, dbus_connection, dbus_crossroads } } } impl IBluetoothGattServerCallback for BtGattServerCallback { fn on_server_registered(&self, status: GattStatus, server_id: i32) { print_info!("GATT Server registered status = {}, server_id = {}", status, server_id); } } impl RPCProxy for BtGattServerCallback { fn get_object_id(&self) -> String { self.objpath.clone() } fn export_for_rpc(self: Box<Self>) { let cr = self.dbus_crossroads.clone(); let iface = export_gatt_server_callback_dbus_intf( self.dbus_connection.clone(), &mut cr.lock().unwrap(), Arc::new(Mutex::new(DisconnectWatcher::new())), ); cr.lock().unwrap().insert(self.get_object_id(), &[iface], Arc::new(Mutex::new(self))); } } pub(crate) struct BtSocketManagerCallback { objpath: String, context: Arc<Mutex<ClientContext>>, Loading
system/gd/rust/linux/client/src/command_handler.rs +20 −1 Original line number Diff line number Diff line Loading @@ -5,7 +5,7 @@ use std::sync::{Arc, Mutex}; use crate::bt_adv::AdvSet; use crate::bt_gatt::AuthReq; use crate::callbacks::BtGattCallback; use crate::callbacks::{BtGattCallback, BtGattServerCallback}; use crate::ClientContext; use crate::{console_red, console_yellow, print_error, print_info}; use bt_topshim::btif::{BtConnectionState, BtStatus, BtTransport}; Loading @@ -21,6 +21,7 @@ const BAR1_CHAR: &str = "="; const BAR2_CHAR: &str = "-"; const MAX_MENU_CHAR_WIDTH: usize = 72; const GATT_CLIENT_APP_UUID: &str = "12345678123456781234567812345678"; const GATT_SERVER_APP_UUID: &str = "12345678123456781234567812345679"; enum CommandError { // Command not handled due to invalid arguments. Loading Loading @@ -169,6 +170,7 @@ fn build_commands() -> HashMap<String, CommandOption> { "gatt write-characteristic <address> <handle> <NoRsp|Write|Prepare> <value>", ), String::from("gatt read-characteristic <address> <handle>"), String::from("gatt register-server"), ], description: String::from("GATT tools"), function_pointer: CommandHandler::cmd_gatt, Loading Loading @@ -1076,6 +1078,23 @@ impl CommandHandler { .unwrap() .read_characteristic(client_id, addr, handle, auth_req); } "register-server" => { let dbus_connection = self.context.lock().unwrap().dbus_connection.clone(); let dbus_crossroads = self.context.lock().unwrap().dbus_crossroads.clone(); self.context.lock().unwrap().gatt_dbus.as_mut().unwrap().register_server( String::from(GATT_SERVER_APP_UUID), Box::new(BtGattServerCallback::new( String::from( "/org/chromium/bluetooth/client/bluetooth_gatt_server_callback", ), self.context.clone(), dbus_connection, dbus_crossroads, )), false, ); } _ => return Err(CommandError::InvalidArgs), } Ok(()) Loading
system/gd/rust/linux/client/src/dbus_iface.rs +28 −2 Original line number Diff line number Diff line Loading @@ -18,8 +18,8 @@ use btstack::bluetooth_adv::{ use btstack::bluetooth_gatt::{ BluetoothGattCharacteristic, BluetoothGattDescriptor, BluetoothGattService, GattWriteRequestStatus, GattWriteType, IBluetoothGatt, IBluetoothGattCallback, IScannerCallback, ScanFilter, ScanFilterCondition, ScanFilterPattern, ScanResult, ScanSettings, ScanType, IBluetoothGattServerCallback, IScannerCallback, ScanFilter, ScanFilterCondition, ScanFilterPattern, ScanResult, ScanSettings, ScanType, }; use btstack::socket_manager::{ BluetoothServerSocket, BluetoothSocket, CallbackId, IBluetoothSocketManager, Loading Loading @@ -1264,6 +1264,23 @@ impl IBluetoothGatt for BluetoothGattDBus { ) { dbus_generated!() } // GATT Server #[dbus_method("RegisterServer")] fn register_server( &mut self, app_uuid: String, callback: Box<dyn IBluetoothGattServerCallback + Send>, eatt_support: bool, ) { dbus_generated!() } #[dbus_method("UnregisterServer")] fn unregister_server(&mut self, server_id: i32) { dbus_generated!() } } struct IBluetoothGattCallbackDBus {} Loading Loading @@ -1349,6 +1366,15 @@ impl IBluetoothGattCallback for IBluetoothGattCallbackDBus { fn on_service_changed(&self, addr: String) {} } #[generate_dbus_exporter( export_gatt_server_callback_dbus_intf, "org.chromium.bluetooth.BluetoothGattServerCallback" )] impl IBluetoothGattServerCallback for IBluetoothGattCallbackDBus { #[dbus_method("OnServerRegistered")] fn on_server_registered(&self, status: GattStatus, client_id: i32) {} } #[dbus_propmap(BluetoothServerSocket)] pub struct BluetoothServerSocketDBus { id: SocketId, Loading
system/gd/rust/linux/service/src/iface_bluetooth_gatt.rs +30 −2 Original line number Diff line number Diff line Loading @@ -8,8 +8,8 @@ use btstack::bluetooth_adv::{ use btstack::bluetooth_gatt::{ BluetoothGattCharacteristic, BluetoothGattDescriptor, BluetoothGattService, GattWriteRequestStatus, GattWriteType, IBluetoothGatt, IBluetoothGattCallback, IScannerCallback, ScanFilter, ScanFilterCondition, ScanFilterPattern, ScanResult, ScanSettings, ScanType, IBluetoothGattServerCallback, IScannerCallback, ScanFilter, ScanFilterCondition, ScanFilterPattern, ScanResult, ScanSettings, ScanType, }; use btstack::{RPCProxy, SuspendMode}; Loading Loading @@ -136,6 +136,17 @@ impl IBluetoothGattCallback for BluetoothGattCallbackDBus { } } #[allow(dead_code)] struct BluetoothGattServerCallbackDBus {} #[dbus_proxy_obj(BluetoothGattServerCallback, "org.chromium.bluetooth.BluetoothGattServerCallback")] impl IBluetoothGattServerCallback for BluetoothGattServerCallbackDBus { #[dbus_method("OnServerRegistered")] fn on_server_registered(&self, status: GattStatus, server_id: i32) { dbus_generated!() } } // Represents Uuid128Bit as an array in D-Bus. impl DBusArg for Uuid128Bit { type DBusType = Vec<u8>; Loading Loading @@ -747,4 +758,21 @@ impl IBluetoothGatt for IBluetoothGattDBus { fn client_read_phy(&mut self, client_id: i32, addr: String) { dbus_generated!() } // GATT Server #[dbus_method("RegisterServer")] fn register_server( &mut self, app_uuid: String, callback: Box<dyn IBluetoothGattServerCallback + Send>, eatt_support: bool, ) { dbus_generated!() } #[dbus_method("UnregisterServer")] fn unregister_server(&mut self, server_id: i32) { dbus_generated!() } }
system/gd/rust/linux/stack/src/bluetooth_gatt.rs +169 −4 Original line number Diff line number Diff line Loading @@ -9,8 +9,8 @@ use bt_topshim::profiles::gatt::{ BtGattReadParams, Gatt, GattAdvCallbacks, GattAdvCallbacksDispatcher, GattAdvInbandCallbacksDispatcher, GattClientCallbacks, GattClientCallbacksDispatcher, GattScannerCallbacks, GattScannerCallbacksDispatcher, GattScannerInbandCallbacks, GattScannerInbandCallbacksDispatcher, GattServerCallbacksDispatcher, GattStatus, LePhy, MsftAdvMonitor, MsftAdvMonitorPattern, GattScannerInbandCallbacksDispatcher, GattServerCallbacks, GattServerCallbacksDispatcher, GattStatus, LePhy, MsftAdvMonitor, MsftAdvMonitorPattern, }; use bt_topshim::topstack; use bt_utils::adv_parser; Loading Loading @@ -180,6 +180,79 @@ impl ContextMap { } } struct Server { id: Option<i32>, cbid: u32, uuid: Uuid128Bit, } struct ServerContextMap { // TODO(b/196635530): Consider using `multimap` for a more efficient implementation of get by // multiple keys. callbacks: Callbacks<dyn IBluetoothGattServerCallback + Send>, servers: Vec<Server>, } type GattServerCallback = Box<dyn IBluetoothGattServerCallback + Send>; impl ServerContextMap { fn new(tx: Sender<Message>) -> ServerContextMap { ServerContextMap { callbacks: Callbacks::new(tx, Message::GattServerCallbackDisconnected), servers: vec![], } } fn get_by_uuid(&self, uuid: &Uuid128Bit) -> Option<&Server> { self.servers.iter().find(|server| server.uuid == *uuid) } fn get_by_server_id(&self, server_id: i32) -> Option<&Server> { self.servers.iter().find(|server| server.id.map_or(false, |id| id == server_id)) } fn get_by_callback_id(&self, callback_id: u32) -> Option<&Server> { self.servers.iter().find(|server| server.cbid == callback_id) } fn add(&mut self, uuid: &Uuid128Bit, callback: GattServerCallback) { if self.get_by_uuid(uuid).is_some() { return; } let cbid = self.callbacks.add_callback(callback); self.servers.push(Server { id: None, cbid, uuid: uuid.clone() }); } fn remove(&mut self, id: i32) { // Remove any callbacks if let Some(cbid) = self.get_by_server_id(id).map(|server| server.cbid) { self.remove_callback(cbid); } self.servers.retain(|server| !(server.id.is_some() && server.id.unwrap() == id)); } fn remove_callback(&mut self, callback_id: u32) { self.callbacks.remove_callback(callback_id); } fn set_server_id(&mut self, uuid: &Uuid128Bit, id: i32) { let server = self.servers.iter_mut().find(|server| server.uuid == *uuid); if let Some(s) = server { s.id = Some(id); } } fn get_callback_from_callback_id( &mut self, callback_id: u32, ) -> Option<&mut GattServerCallback> { self.callbacks.get_by_id(callback_id) } } /// Defines the GATT API. // TODO(242083290): Split out interfaces. pub trait IBluetoothGatt { Loading Loading @@ -425,6 +498,19 @@ pub trait IBluetoothGatt { /// Reads the PHY used by a peer. fn client_read_phy(&mut self, client_id: i32, addr: String); // GATT Server /// Registers a GATT Server. fn register_server( &mut self, app_uuid: String, callback: Box<dyn IBluetoothGattServerCallback + Send>, eatt_support: bool, ); /// Unregisters a GATT Server. fn unregister_server(&mut self, server_id: i32); } #[derive(Debug, Default)] Loading Loading @@ -580,6 +666,12 @@ pub trait IBluetoothGattCallback: RPCProxy { fn on_service_changed(&self, _addr: String); } /// Callback for GATT Server API. pub trait IBluetoothGattServerCallback: RPCProxy { /// When the `register_server` request is done. fn on_server_registered(&self, _status: GattStatus, _server_id: i32); } /// Interface for scanner callbacks to clients, passed to /// `IBluetoothGatt::register_scanner_callback`. pub trait IScannerCallback: RPCProxy { Loading Loading @@ -813,6 +905,7 @@ pub struct BluetoothGatt { adapter: Option<Arc<Mutex<Box<Bluetooth>>>>, context_map: ContextMap, server_context_map: ServerContextMap, reliable_queue: HashSet<String>, scanner_callbacks: Callbacks<dyn IScannerCallback + Send>, scanners: Arc<Mutex<ScannersMap>>, Loading Loading @@ -842,6 +935,7 @@ impl BluetoothGatt { gatt: None, adapter: None, context_map: ContextMap::new(tx.clone()), server_context_map: ServerContextMap::new(tx.clone()), reliable_queue: HashSet::new(), scanner_callbacks: Callbacks::new(tx.clone(), Message::ScannerCallbackDisconnected), scanners: scanners.clone(), Loading Loading @@ -874,10 +968,13 @@ impl BluetoothGatt { }), }; let tx_clone = tx.clone(); let gatt_server_callbacks_dispatcher = GattServerCallbacksDispatcher { dispatch: Box::new(move |cb| { // TODO(b/193685149): Implement the callbacks debug!("received Gatt server callback: {:?}", cb); let tx_clone = tx_clone.clone(); topstack::get_runtime().spawn(async move { let _ = tx_clone.send(Message::GattServer(cb)).await; }); }), }; Loading Loading @@ -1015,6 +1112,18 @@ impl BluetoothGatt { self.context_map.remove_callback(callback_id); } pub fn remove_server_callback(&mut self, callback_id: u32) { // Unregister server if server id exists. if let Some(server) = self.server_context_map.get_by_callback_id(callback_id) { if let Some(id) = server.id { self.unregister_server(id); } } // Always remove callback. self.context_map.remove_callback(callback_id); } /// Enters suspend mode for LE advertising. pub fn advertising_enter_suspend(&mut self) { self.advertisers.set_suspend_mode(SuspendMode::Suspending); Loading Loading @@ -1501,6 +1610,8 @@ impl IBluetoothGatt for BluetoothGatt { } } // GATT Client fn register_client( &mut self, app_uuid: String, Loading Loading @@ -1829,6 +1940,36 @@ impl IBluetoothGatt for BluetoothGatt { self.gatt.as_ref().unwrap().lock().unwrap().client.read_phy(client_id, &address); } // GATT Server fn register_server( &mut self, app_uuid: String, callback: Box<dyn IBluetoothGattServerCallback + Send>, eatt_support: bool, ) { let uuid = match UuidHelper::parse_string(&app_uuid) { Some(id) => id, None => { log::info!("Uuid is malformed: {}", app_uuid); return; } }; self.server_context_map.add(&uuid.uu, callback); self.gatt .as_ref() .expect("GATT has not been initialized") .lock() .unwrap() .server .register_server(&uuid, eatt_support); } fn unregister_server(&mut self, server_id: i32) { self.server_context_map.remove(server_id); self.gatt.as_ref().unwrap().lock().unwrap().server.unregister_server(server_id); } } #[btif_callbacks_dispatcher(dispatch_gatt_client_callbacks, GattClientCallbacks)] Loading Loading @@ -2430,6 +2571,30 @@ impl BtifGattClientCallbacks for BluetoothGatt { } } #[btif_callbacks_dispatcher(dispatch_gatt_server_callbacks, GattServerCallbacks)] pub(crate) trait BtifGattServerCallbacks { #[btif_callback(RegisterServer)] fn register_server_cb(&mut self, status: GattStatus, server_id: i32, app_uuid: Uuid); } impl BtifGattServerCallbacks for BluetoothGatt { fn register_server_cb(&mut self, status: GattStatus, server_id: i32, app_uuid: Uuid) { self.server_context_map.set_server_id(&app_uuid.uu, server_id); let cbid = self.server_context_map.get_by_uuid(&app_uuid.uu).map(|server| server.cbid); match cbid { Some(cbid) => { if let Some(cb) = self.server_context_map.get_callback_from_callback_id(cbid) { cb.on_server_registered(status, server_id) } } None => { warn!("Warning: No callback found for UUID {}", app_uuid); } } } } #[btif_callbacks_dispatcher(dispatch_le_scanner_callbacks, GattScannerCallbacks)] pub(crate) trait BtifGattScannerCallbacks { #[btif_callback(OnScannerRegistered)] Loading