| use crate::dbus_iface::{ |
| 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, |
| }; |
| use crate::ClientContext; |
| use crate::{console_red, console_yellow, print_error, print_info}; |
| use bt_topshim::btif::{BtBondState, BtPropertyType, BtSspVariant, BtStatus, Uuid128Bit}; |
| use bt_topshim::profiles::gatt::GattStatus; |
| use btstack::bluetooth::{ |
| BluetoothDevice, IBluetooth, IBluetoothCallback, IBluetoothConnectionCallback, |
| }; |
| use btstack::bluetooth_adv::IAdvertisingSetCallback; |
| use btstack::bluetooth_gatt::{ |
| BluetoothGattService, IBluetoothGattCallback, IScannerCallback, LePhy, ScanResult, |
| }; |
| use btstack::socket_manager::{ |
| BluetoothServerSocket, BluetoothSocket, IBluetoothSocketManager, |
| IBluetoothSocketManagerCallbacks, SocketId, |
| }; |
| use btstack::suspend::ISuspendCallback; |
| use btstack::uuid::UuidWrapper; |
| use btstack::{RPCProxy, SuspendMode}; |
| use dbus::nonblock::SyncConnection; |
| use dbus_crossroads::Crossroads; |
| use dbus_projection::DisconnectWatcher; |
| use manager_service::iface_bluetooth_manager::IBluetoothManagerCallback; |
| use std::sync::{Arc, Mutex}; |
| |
| /// Callback context for manager interface callbacks. |
| pub(crate) struct BtManagerCallback { |
| objpath: String, |
| context: Arc<Mutex<ClientContext>>, |
| |
| dbus_connection: Arc<SyncConnection>, |
| dbus_crossroads: Arc<Mutex<Crossroads>>, |
| } |
| |
| impl BtManagerCallback { |
| 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 IBluetoothManagerCallback for BtManagerCallback { |
| fn on_hci_device_changed(&self, hci_interface: i32, present: bool) { |
| print_info!("hci{} present = {}", hci_interface, present); |
| |
| if present { |
| self.context.lock().unwrap().adapters.entry(hci_interface).or_insert(false); |
| } else { |
| self.context.lock().unwrap().adapters.remove(&hci_interface); |
| } |
| } |
| |
| fn on_hci_enabled_changed(&self, hci_interface: i32, enabled: bool) { |
| self.context.lock().unwrap().set_adapter_enabled(hci_interface, enabled); |
| } |
| |
| fn on_default_adapter_changed(&self, hci_interface: i32) { |
| print_info!("hci{} is now the default", hci_interface); |
| } |
| } |
| |
| impl RPCProxy for BtManagerCallback { |
| 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_bluetooth_manager_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))); |
| } |
| } |
| |
| /// Callback container for adapter interface callbacks. |
| pub(crate) struct BtCallback { |
| objpath: String, |
| context: Arc<Mutex<ClientContext>>, |
| |
| dbus_connection: Arc<SyncConnection>, |
| dbus_crossroads: Arc<Mutex<Crossroads>>, |
| } |
| |
| impl BtCallback { |
| 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 IBluetoothCallback for BtCallback { |
| fn on_adapter_property_changed(&self, _prop: BtPropertyType) {} |
| |
| fn on_address_changed(&self, addr: String) { |
| print_info!("Address changed to {}", &addr); |
| self.context.lock().unwrap().adapter_address = Some(addr); |
| } |
| |
| fn on_name_changed(&self, name: String) { |
| print_info!("Name changed to {}", &name); |
| } |
| |
| fn on_discoverable_changed(&self, discoverable: bool) { |
| print_info!("Discoverable changed to {}", &discoverable); |
| } |
| |
| fn on_device_found(&self, remote_device: BluetoothDevice) { |
| self.context |
| .lock() |
| .unwrap() |
| .found_devices |
| .entry(remote_device.address.clone()) |
| .or_insert(remote_device.clone()); |
| |
| print_info!("Found device: {:?}", remote_device); |
| } |
| |
| fn on_device_cleared(&self, remote_device: BluetoothDevice) { |
| match self.context.lock().unwrap().found_devices.remove(&remote_device.address) { |
| Some(_) => print_info!("Removed device: {:?}", remote_device), |
| None => (), |
| }; |
| |
| self.context.lock().unwrap().bonded_devices.remove(&remote_device.address); |
| } |
| |
| fn on_discovering_changed(&self, discovering: bool) { |
| self.context.lock().unwrap().discovering_state = discovering; |
| |
| print_info!("Discovering: {}", discovering); |
| } |
| |
| fn on_ssp_request( |
| &self, |
| remote_device: BluetoothDevice, |
| _cod: u32, |
| variant: BtSspVariant, |
| passkey: u32, |
| ) { |
| match variant { |
| BtSspVariant::PasskeyNotification => { |
| print_info!( |
| "Device [{}: {}] would like to pair, enter passkey on remote device: {:06}", |
| &remote_device.address, |
| &remote_device.name, |
| passkey |
| ); |
| } |
| BtSspVariant::Consent => { |
| let rd = remote_device.clone(); |
| self.context.lock().unwrap().run_callback(Box::new(move |context| { |
| // Auto-confirm bonding attempts that were locally initiated. |
| // Ignore all other bonding attempts. |
| let bonding_device = context.lock().unwrap().bonding_attempt.as_ref().cloned(); |
| match bonding_device { |
| Some(bd) => { |
| if bd.address == rd.address { |
| context |
| .lock() |
| .unwrap() |
| .adapter_dbus |
| .as_ref() |
| .unwrap() |
| .set_pairing_confirmation(rd.clone(), true); |
| } |
| } |
| None => (), |
| } |
| })); |
| } |
| BtSspVariant::PasskeyEntry => { |
| println!("Got PasskeyEntry but it is not supported..."); |
| } |
| BtSspVariant::PasskeyConfirmation => { |
| println!("Got PasskeyConfirmation but there's nothing to do..."); |
| } |
| } |
| } |
| |
| fn on_bond_state_changed(&self, status: u32, address: String, state: u32) { |
| print_info!("Bonding state changed: [{}] state: {}, Status = {}", address, state, status); |
| |
| // Clear bonding attempt if bonding fails or succeeds |
| match BtBondState::from(state) { |
| BtBondState::NotBonded | BtBondState::Bonded => { |
| let bonding_attempt = |
| self.context.lock().unwrap().bonding_attempt.as_ref().cloned(); |
| match bonding_attempt { |
| Some(bd) => { |
| if &address == &bd.address { |
| self.context.lock().unwrap().bonding_attempt = None; |
| } |
| } |
| None => (), |
| } |
| } |
| BtBondState::Bonding => (), |
| } |
| |
| let device = |
| BluetoothDevice { address: address.clone(), name: String::from("Classic device") }; |
| |
| // If bonded, we should also automatically connect all enabled profiles |
| if BtBondState::Bonded == state.into() { |
| self.context.lock().unwrap().bonded_devices.insert(address.clone(), device.clone()); |
| self.context.lock().unwrap().connect_all_enabled_profiles(device.clone()); |
| } |
| |
| if BtBondState::NotBonded == state.into() { |
| self.context.lock().unwrap().bonded_devices.remove(&address); |
| } |
| } |
| } |
| |
| impl RPCProxy for BtCallback { |
| 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_bluetooth_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 BtConnectionCallback { |
| objpath: String, |
| _context: Arc<Mutex<ClientContext>>, |
| |
| dbus_connection: Arc<SyncConnection>, |
| dbus_crossroads: Arc<Mutex<Crossroads>>, |
| } |
| |
| impl BtConnectionCallback { |
| 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 IBluetoothConnectionCallback for BtConnectionCallback { |
| fn on_device_connected(&self, remote_device: BluetoothDevice) { |
| print_info!("Connected: [{}]: {}", remote_device.address, remote_device.name); |
| } |
| |
| fn on_device_disconnected(&self, remote_device: BluetoothDevice) { |
| print_info!("Disconnected: [{}]: {}", remote_device.address, remote_device.name); |
| } |
| } |
| |
| impl RPCProxy for BtConnectionCallback { |
| 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_bluetooth_connection_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 ScannerCallback { |
| objpath: String, |
| context: Arc<Mutex<ClientContext>>, |
| |
| dbus_connection: Arc<SyncConnection>, |
| dbus_crossroads: Arc<Mutex<Crossroads>>, |
| } |
| |
| impl ScannerCallback { |
| 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 IScannerCallback for ScannerCallback { |
| fn on_scanner_registered(&self, uuid: Uuid128Bit, scanner_id: u8, status: GattStatus) { |
| if status != GattStatus::Success { |
| print_error!("Failed registering scanner, status = {}", status); |
| return; |
| } |
| |
| print_info!( |
| "Scanner callback registered, uuid = {}, id = {}", |
| UuidWrapper(&uuid), |
| scanner_id |
| ); |
| } |
| |
| fn on_scan_result(&self, scan_result: ScanResult) { |
| if self.context.lock().unwrap().active_scanner_ids.len() > 0 { |
| print_info!("Scan result: {:#?}", scan_result); |
| } |
| } |
| |
| fn on_suspend_mode_change(&self, _suspend_mode: SuspendMode) { |
| // No-op, not interesting for btclient. |
| } |
| } |
| |
| impl RPCProxy for ScannerCallback { |
| 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_scanner_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 AdvertisingSetCallback { |
| objpath: String, |
| context: Arc<Mutex<ClientContext>>, |
| |
| dbus_connection: Arc<SyncConnection>, |
| dbus_crossroads: Arc<Mutex<Crossroads>>, |
| } |
| |
| impl AdvertisingSetCallback { |
| 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 IAdvertisingSetCallback for AdvertisingSetCallback { |
| fn on_advertising_set_started( |
| &self, |
| reg_id: i32, |
| advertiser_id: i32, |
| tx_power: i32, |
| status: GattStatus, |
| ) { |
| print_info!( |
| "on_advertising_set_started: reg_id = {}, advertiser_id = {}, tx_power = {}, status = {}", |
| reg_id, |
| advertiser_id, |
| tx_power, |
| status |
| ); |
| if status == GattStatus::Success { |
| if let Some(Some(ex_adv_id)) = |
| self.context.lock().unwrap().adv_sets.insert(reg_id, Some(advertiser_id)) |
| { |
| print_error!( |
| "on_advertising_set_started: previous advertising set ({}) registered ({}) is omitted", |
| ex_adv_id, |
| reg_id, |
| ); |
| } |
| } else { |
| print_error!( |
| "on_advertising_set_started: remove advertising set registered ({})", |
| reg_id |
| ); |
| self.context.lock().unwrap().adv_sets.remove(®_id); |
| } |
| } |
| |
| fn on_own_address_read(&self, advertiser_id: i32, address_type: i32, address: String) { |
| print_info!( |
| "on_own_address_read: advertiser_id = {}, address_type = {}, address = {}", |
| advertiser_id, |
| address_type, |
| address |
| ); |
| } |
| |
| fn on_advertising_set_stopped(&self, advertiser_id: i32) { |
| print_info!("on_advertising_set_stopped: advertiser_id = {}", advertiser_id); |
| self.context.lock().unwrap().adv_sets.retain(|_, val| *val != Some(advertiser_id)); |
| } |
| |
| fn on_advertising_enabled(&self, advertiser_id: i32, enable: bool, status: GattStatus) { |
| print_info!( |
| "on_advertising_enabled: advertiser_id = {}, enable = {}, status = {}", |
| advertiser_id, |
| enable, |
| status |
| ); |
| } |
| |
| fn on_advertising_data_set(&self, advertiser_id: i32, status: GattStatus) { |
| print_info!( |
| "on_advertising_data_set: advertiser_id = {}, status = {}", |
| advertiser_id, |
| status |
| ); |
| } |
| |
| fn on_scan_response_data_set(&self, advertiser_id: i32, status: GattStatus) { |
| print_info!( |
| "on_scan_response_data_set: advertiser_id = {}, status = {}", |
| advertiser_id, |
| status |
| ); |
| } |
| |
| fn on_advertising_parameters_updated( |
| &self, |
| advertiser_id: i32, |
| tx_power: i32, |
| status: GattStatus, |
| ) { |
| print_info!( |
| "on_advertising_parameters_updated: advertiser_id = {}, tx_power: {}, status = {}", |
| advertiser_id, |
| tx_power, |
| status |
| ); |
| } |
| |
| fn on_periodic_advertising_parameters_updated(&self, advertiser_id: i32, status: GattStatus) { |
| print_info!( |
| "on_periodic_advertising_parameters_updated: advertiser_id = {}, status = {}", |
| advertiser_id, |
| status |
| ); |
| } |
| |
| fn on_periodic_advertising_data_set(&self, advertiser_id: i32, status: GattStatus) { |
| print_info!( |
| "on_periodic_advertising_data_set: advertiser_id = {}, status = {}", |
| advertiser_id, |
| status |
| ); |
| } |
| |
| fn on_periodic_advertising_enabled( |
| &self, |
| advertiser_id: i32, |
| enable: bool, |
| status: GattStatus, |
| ) { |
| print_info!( |
| "on_periodic_advertising_enabled: advertiser_id = {}, enable = {}, status = {}", |
| advertiser_id, |
| enable, |
| status |
| ); |
| } |
| } |
| |
| impl RPCProxy for AdvertisingSetCallback { |
| 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_advertising_set_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 BtGattCallback { |
| objpath: String, |
| context: Arc<Mutex<ClientContext>>, |
| |
| dbus_connection: Arc<SyncConnection>, |
| dbus_crossroads: Arc<Mutex<Crossroads>>, |
| } |
| |
| impl BtGattCallback { |
| 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 IBluetoothGattCallback for BtGattCallback { |
| fn on_client_registered(&self, status: GattStatus, client_id: i32) { |
| print_info!("GATT Client registered status = {}, client_id = {}", status, client_id); |
| self.context.lock().unwrap().gatt_client_id = Some(client_id); |
| } |
| |
| fn on_client_connection_state( |
| &self, |
| status: GattStatus, |
| client_id: i32, |
| connected: bool, |
| addr: String, |
| ) { |
| print_info!( |
| "GATT Client connection state = {}, client_id = {}, connected = {}, addr = {}", |
| status, |
| client_id, |
| connected, |
| addr |
| ); |
| } |
| |
| fn on_phy_update(&self, addr: String, tx_phy: LePhy, rx_phy: LePhy, status: GattStatus) { |
| print_info!( |
| "Phy updated: addr = {}, tx_phy = {:?}, rx_phy = {:?}, status = {:?}", |
| addr, |
| tx_phy, |
| rx_phy, |
| status |
| ); |
| } |
| |
| fn on_phy_read(&self, addr: String, tx_phy: LePhy, rx_phy: LePhy, status: GattStatus) { |
| print_info!( |
| "Phy read: addr = {}, tx_phy = {:?}, rx_phy = {:?}, status = {:?}", |
| addr, |
| tx_phy, |
| rx_phy, |
| status |
| ); |
| } |
| |
| fn on_search_complete( |
| &self, |
| addr: String, |
| services: Vec<BluetoothGattService>, |
| status: GattStatus, |
| ) { |
| print_info!( |
| "GATT DB Search complete: addr = {}, services = {:?}, status = {}", |
| addr, |
| services, |
| status |
| ); |
| } |
| |
| fn on_characteristic_read( |
| &self, |
| addr: String, |
| status: GattStatus, |
| handle: i32, |
| value: Vec<u8>, |
| ) { |
| print_info!( |
| "GATT Characteristic read: addr = {}, status = {}, handle = {}, value = {:?}", |
| addr, |
| status, |
| handle, |
| value |
| ); |
| } |
| |
| fn on_characteristic_write(&self, addr: String, status: GattStatus, handle: i32) { |
| print_info!( |
| "GATT Characteristic write: addr = {}, status = {}, handle = {}", |
| addr, |
| status, |
| handle |
| ); |
| } |
| |
| fn on_execute_write(&self, addr: String, status: GattStatus) { |
| print_info!("GATT execute write addr = {}, status = {}", addr, status); |
| } |
| |
| fn on_descriptor_read(&self, addr: String, status: GattStatus, handle: i32, value: Vec<u8>) { |
| print_info!( |
| "GATT Descriptor read: addr = {}, status = {}, handle = {}, value = {:?}", |
| addr, |
| status, |
| handle, |
| value |
| ); |
| } |
| |
| fn on_descriptor_write(&self, addr: String, status: GattStatus, handle: i32) { |
| print_info!( |
| "GATT Descriptor write: addr = {}, status = {}, handle = {}", |
| addr, |
| status, |
| handle |
| ); |
| } |
| |
| fn on_notify(&self, addr: String, handle: i32, value: Vec<u8>) { |
| print_info!("GATT Notification: addr = {}, handle = {}, value = {:?}", addr, handle, value); |
| } |
| |
| fn on_read_remote_rssi(&self, addr: String, rssi: i32, status: GattStatus) { |
| print_info!("Remote RSSI read: addr = {}, rssi = {}, status = {}", addr, rssi, status); |
| } |
| |
| fn on_configure_mtu(&self, addr: String, mtu: i32, status: GattStatus) { |
| print_info!("MTU configured: addr = {}, mtu = {}, status = {}", addr, mtu, status); |
| } |
| |
| fn on_connection_updated( |
| &self, |
| addr: String, |
| interval: i32, |
| latency: i32, |
| timeout: i32, |
| status: GattStatus, |
| ) { |
| print_info!( |
| "Connection updated: addr = {}, interval = {}, latency = {}, timeout = {}, status = {}", |
| addr, |
| interval, |
| latency, |
| timeout, |
| status |
| ); |
| } |
| |
| fn on_service_changed(&self, addr: String) { |
| print_info!("Service changed for {}", addr,); |
| } |
| } |
| |
| impl RPCProxy for BtGattCallback { |
| 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_bluetooth_gatt_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>>, |
| |
| dbus_connection: Arc<SyncConnection>, |
| dbus_crossroads: Arc<Mutex<Crossroads>>, |
| } |
| |
| impl BtSocketManagerCallback { |
| 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 IBluetoothSocketManagerCallbacks for BtSocketManagerCallback { |
| fn on_incoming_socket_ready(&mut self, socket: BluetoothServerSocket, status: BtStatus) { |
| if status != BtStatus::Success { |
| print_error!( |
| "Incoming socket {} failed to be ready, type = {:?}, flags = {}, status = {:?}", |
| socket.id, |
| socket.sock_type, |
| socket.flags, |
| status, |
| ); |
| return; |
| } |
| |
| print_info!( |
| "Socket {} ready, details: {:?}, flags = {}, psm = {:?}, channel = {:?}, name = {:?}, uuid = {:?}", |
| socket.id, |
| socket.sock_type, |
| socket.flags, |
| socket.psm, |
| socket.channel, |
| socket.name, |
| socket.uuid, |
| ); |
| |
| let callback_id = self.context.lock().unwrap().socket_manager_callback_id.clone().unwrap(); |
| |
| self.context.lock().unwrap().run_callback(Box::new(move |context| { |
| let status = context |
| .lock() |
| .unwrap() |
| .socket_manager_dbus |
| .as_mut() |
| .unwrap() |
| .close(callback_id, socket.id); |
| if status != BtStatus::Success { |
| print_error!("Failed to close socket {}, status = {:?}", socket.id, status); |
| return; |
| } |
| print_info!("Requested for closing socket {}", socket.id); |
| })); |
| } |
| |
| fn on_incoming_socket_closed(&mut self, listener_id: SocketId, reason: BtStatus) { |
| print_info!("Socket {} closed, reason = {:?}", listener_id, reason); |
| } |
| |
| fn on_handle_incoming_connection( |
| &mut self, |
| _listener_id: SocketId, |
| _connection: BluetoothSocket, |
| ) { |
| todo!(); |
| } |
| |
| fn on_outgoing_connection_result( |
| &mut self, |
| _connecting_id: SocketId, |
| _result: BtStatus, |
| _socket: Option<BluetoothSocket>, |
| ) { |
| todo!(); |
| } |
| } |
| |
| impl RPCProxy for BtSocketManagerCallback { |
| 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_socket_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))); |
| } |
| } |
| |
| /// Callback container for suspend interface callbacks. |
| pub(crate) struct SuspendCallback { |
| objpath: String, |
| |
| dbus_connection: Arc<SyncConnection>, |
| dbus_crossroads: Arc<Mutex<Crossroads>>, |
| } |
| |
| impl SuspendCallback { |
| pub(crate) fn new( |
| objpath: String, |
| dbus_connection: Arc<SyncConnection>, |
| dbus_crossroads: Arc<Mutex<Crossroads>>, |
| ) -> Self { |
| Self { objpath, dbus_connection, dbus_crossroads } |
| } |
| } |
| |
| impl ISuspendCallback for SuspendCallback { |
| // TODO(b/224606285): Implement suspend utils in btclient. |
| fn on_callback_registered(&self, _callback_id: u32) {} |
| fn on_suspend_ready(&self, _suspend_id: u32) {} |
| fn on_resumed(&self, _suspend_id: i32) {} |
| } |
| |
| impl RPCProxy for SuspendCallback { |
| 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_suspend_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))); |
| } |
| } |