1 //! Floss Bluetooth stack. 2 //! 3 //! This crate provides the API implementation of the Fluoride/GD Bluetooth 4 //! stack, independent of any RPC projection. 5 6 pub mod async_helper; 7 pub mod battery_manager; 8 pub mod battery_provider_manager; 9 pub mod battery_service; 10 pub mod bluetooth; 11 pub mod bluetooth_admin; 12 pub mod bluetooth_adv; 13 pub mod bluetooth_gatt; 14 pub mod bluetooth_logging; 15 pub mod bluetooth_media; 16 pub mod bluetooth_qa; 17 pub mod callbacks; 18 pub mod dis; 19 pub mod socket_manager; 20 pub mod suspend; 21 pub mod uuid; 22 23 use bluetooth_qa::BluetoothQA; 24 use bt_topshim::btif::BtDiscMode; 25 use log::debug; 26 use num_derive::{FromPrimitive, ToPrimitive}; 27 use std::sync::{Arc, Mutex}; 28 use tokio::sync::mpsc::channel; 29 use tokio::sync::mpsc::{Receiver, Sender}; 30 31 use crate::battery_manager::{BatteryManager, BatterySet}; 32 use crate::battery_provider_manager::BatteryProviderManager; 33 use crate::battery_service::{BatteryService, BatteryServiceActions}; 34 use crate::bluetooth::{ 35 dispatch_base_callbacks, dispatch_hid_host_callbacks, dispatch_sdp_callbacks, Bluetooth, 36 BluetoothDevice, DelayedActions, IBluetooth, 37 }; 38 use crate::bluetooth_admin::{BluetoothAdmin, IBluetoothAdmin}; 39 use crate::bluetooth_gatt::{ 40 dispatch_gatt_client_callbacks, dispatch_gatt_server_callbacks, dispatch_le_adv_callbacks, 41 dispatch_le_scanner_callbacks, dispatch_le_scanner_inband_callbacks, BluetoothGatt, 42 }; 43 use crate::bluetooth_media::{BluetoothMedia, MediaActions}; 44 use crate::dis::{DeviceInformation, ServiceCallbacks}; 45 use crate::socket_manager::{BluetoothSocketManager, SocketActions}; 46 use crate::suspend::Suspend; 47 use bt_topshim::{ 48 btif::{BaseCallbacks, BtTransport}, 49 profiles::{ 50 a2dp::A2dpCallbacks, avrcp::AvrcpCallbacks, gatt::GattAdvCallbacks, 51 gatt::GattAdvInbandCallbacks, gatt::GattClientCallbacks, gatt::GattScannerCallbacks, 52 gatt::GattScannerInbandCallbacks, gatt::GattServerCallbacks, hfp::HfpCallbacks, 53 hid_host::HHCallbacks, sdp::SdpCallbacks, 54 }, 55 }; 56 57 /// Message types that are sent to the stack main dispatch loop. 58 pub enum Message { 59 // Shuts down the stack. 60 Shutdown, 61 62 // Adapter is enabled and ready. 63 AdapterReady, 64 65 // Callbacks from libbluetooth 66 A2dp(A2dpCallbacks), 67 Avrcp(AvrcpCallbacks), 68 Base(BaseCallbacks), 69 GattClient(GattClientCallbacks), 70 GattServer(GattServerCallbacks), 71 LeScanner(GattScannerCallbacks), 72 LeScannerInband(GattScannerInbandCallbacks), 73 LeAdvInband(GattAdvInbandCallbacks), 74 LeAdv(GattAdvCallbacks), 75 HidHost(HHCallbacks), 76 Hfp(HfpCallbacks), 77 Sdp(SdpCallbacks), 78 79 // Actions within the stack 80 Media(MediaActions), 81 MediaCallbackDisconnected(u32), 82 83 // Client callback disconnections 84 AdapterCallbackDisconnected(u32), 85 ConnectionCallbackDisconnected(u32), 86 87 // Some delayed actions for the adapter. 88 DelayedAdapterActions(DelayedActions), 89 90 // Follows IBluetooth's on_device_(dis)connected callback but doesn't require depending on 91 // Bluetooth. 92 OnAclConnected(BluetoothDevice, BtTransport), 93 OnAclDisconnected(BluetoothDevice), 94 95 // Suspend related 96 SuspendCallbackRegistered(u32), 97 SuspendCallbackDisconnected(u32), 98 SuspendReady(i32), 99 ResumeReady(i32), 100 AudioReconnectOnResumeComplete, 101 102 // Scanner related 103 ScannerCallbackDisconnected(u32), 104 105 // Advertising related 106 AdvertiserCallbackDisconnected(u32), 107 108 SocketManagerActions(SocketActions), 109 SocketManagerCallbackDisconnected(u32), 110 111 // Battery related 112 BatteryProviderManagerCallbackDisconnected(u32), 113 BatteryProviderManagerBatteryUpdated(String, BatterySet), 114 BatteryServiceCallbackDisconnected(u32), 115 BatteryService(BatteryServiceActions), 116 BatteryServiceRefresh, 117 BatteryManagerCallbackDisconnected(u32), 118 119 GattClientCallbackDisconnected(u32), 120 GattServerCallbackDisconnected(u32), 121 122 // Admin policy related 123 AdminCallbackDisconnected(u32), 124 HidHostEnable, 125 AdminPolicyChanged, 126 127 // Dis callbacks 128 Dis(ServiceCallbacks), 129 130 // Qualification Only 131 QaAddMediaPlayer(String, bool), 132 QaRfcommSendMsc(u8, String), 133 QaOnDiscoverableModeChanged(BtDiscMode), 134 } 135 136 /// Represents suspend mode of a module. 137 /// 138 /// Being in suspend mode means that the module pauses some activities if required for suspend and 139 /// some subsequent API calls will be blocked with a retryable error. 140 #[derive(FromPrimitive, ToPrimitive, Debug, PartialEq, Clone)] 141 pub enum SuspendMode { 142 Normal = 0, 143 Suspending = 1, 144 Suspended = 2, 145 Resuming = 3, 146 } 147 148 /// Umbrella class for the Bluetooth stack. 149 pub struct Stack {} 150 151 impl Stack { 152 /// Creates an mpsc channel for passing messages to the main dispatch loop. create_channel() -> (Sender<Message>, Receiver<Message>)153 pub fn create_channel() -> (Sender<Message>, Receiver<Message>) { 154 channel::<Message>(1) 155 } 156 157 /// Runs the main dispatch loop. dispatch( mut rx: Receiver<Message>, bluetooth: Arc<Mutex<Box<Bluetooth>>>, bluetooth_gatt: Arc<Mutex<Box<BluetoothGatt>>>, battery_service: Arc<Mutex<Box<BatteryService>>>, battery_manager: Arc<Mutex<Box<BatteryManager>>>, battery_provider_manager: Arc<Mutex<Box<BatteryProviderManager>>>, bluetooth_media: Arc<Mutex<Box<BluetoothMedia>>>, suspend: Arc<Mutex<Box<Suspend>>>, bluetooth_socketmgr: Arc<Mutex<Box<BluetoothSocketManager>>>, bluetooth_admin: Arc<Mutex<Box<BluetoothAdmin>>>, bluetooth_dis: Arc<Mutex<Box<DeviceInformation>>>, bluetooth_qa: Arc<Mutex<Box<BluetoothQA>>>, )158 pub async fn dispatch( 159 mut rx: Receiver<Message>, 160 bluetooth: Arc<Mutex<Box<Bluetooth>>>, 161 bluetooth_gatt: Arc<Mutex<Box<BluetoothGatt>>>, 162 battery_service: Arc<Mutex<Box<BatteryService>>>, 163 battery_manager: Arc<Mutex<Box<BatteryManager>>>, 164 battery_provider_manager: Arc<Mutex<Box<BatteryProviderManager>>>, 165 bluetooth_media: Arc<Mutex<Box<BluetoothMedia>>>, 166 suspend: Arc<Mutex<Box<Suspend>>>, 167 bluetooth_socketmgr: Arc<Mutex<Box<BluetoothSocketManager>>>, 168 bluetooth_admin: Arc<Mutex<Box<BluetoothAdmin>>>, 169 bluetooth_dis: Arc<Mutex<Box<DeviceInformation>>>, 170 bluetooth_qa: Arc<Mutex<Box<BluetoothQA>>>, 171 ) { 172 loop { 173 let m = rx.recv().await; 174 175 if m.is_none() { 176 eprintln!("Message dispatch loop quit"); 177 break; 178 } 179 180 match m.unwrap() { 181 Message::Shutdown => { 182 bluetooth.lock().unwrap().disable(); 183 } 184 185 Message::AdapterReady => { 186 // Initialize objects that need the adapter to be fully 187 // enabled before running. 188 189 // Register device information service. 190 bluetooth_dis.lock().unwrap().initialize(); 191 } 192 193 Message::A2dp(a) => { 194 bluetooth_media.lock().unwrap().dispatch_a2dp_callbacks(a); 195 } 196 197 Message::Avrcp(av) => { 198 bluetooth_media.lock().unwrap().dispatch_avrcp_callbacks(av); 199 } 200 201 Message::Base(b) => { 202 dispatch_base_callbacks(bluetooth.lock().unwrap().as_mut(), b.clone()); 203 dispatch_base_callbacks(suspend.lock().unwrap().as_mut(), b); 204 } 205 206 Message::GattClient(m) => { 207 dispatch_gatt_client_callbacks(bluetooth_gatt.lock().unwrap().as_mut(), m); 208 } 209 210 Message::GattServer(m) => { 211 dispatch_gatt_server_callbacks(bluetooth_gatt.lock().unwrap().as_mut(), m); 212 } 213 214 Message::LeScanner(m) => { 215 dispatch_le_scanner_callbacks(bluetooth_gatt.lock().unwrap().as_mut(), m); 216 } 217 218 Message::LeScannerInband(m) => { 219 dispatch_le_scanner_inband_callbacks( 220 bluetooth_gatt.lock().unwrap().as_mut(), 221 m, 222 ); 223 } 224 225 Message::LeAdvInband(m) => { 226 debug!("Received LeAdvInband message: {:?}. This is unexpected!", m); 227 } 228 229 Message::LeAdv(m) => { 230 dispatch_le_adv_callbacks(bluetooth_gatt.lock().unwrap().as_mut(), m); 231 } 232 233 Message::Hfp(hf) => { 234 bluetooth_media.lock().unwrap().dispatch_hfp_callbacks(hf); 235 } 236 237 Message::HidHost(h) => { 238 dispatch_hid_host_callbacks(bluetooth.lock().unwrap().as_mut(), h); 239 } 240 241 Message::Sdp(s) => { 242 dispatch_sdp_callbacks(bluetooth.lock().unwrap().as_mut(), s); 243 } 244 245 Message::Media(action) => { 246 bluetooth_media.lock().unwrap().dispatch_media_actions(action); 247 } 248 249 Message::MediaCallbackDisconnected(cb_id) => { 250 bluetooth_media.lock().unwrap().remove_callback(cb_id); 251 } 252 253 Message::AdapterCallbackDisconnected(id) => { 254 bluetooth.lock().unwrap().adapter_callback_disconnected(id); 255 } 256 257 Message::ConnectionCallbackDisconnected(id) => { 258 bluetooth.lock().unwrap().connection_callback_disconnected(id); 259 } 260 261 Message::DelayedAdapterActions(action) => { 262 bluetooth.lock().unwrap().handle_delayed_actions(action); 263 } 264 265 // Any service needing an updated list of devices can have an 266 // update method triggered from here rather than needing a 267 // reference to Bluetooth. 268 Message::OnAclConnected(device, transport) => { 269 battery_service 270 .lock() 271 .unwrap() 272 .handle_action(BatteryServiceActions::Connect(device, transport)); 273 } 274 275 // For battery service, use this to clean up internal handles. GATT connection is 276 // already dropped if ACL disconnect has occurred. 277 Message::OnAclDisconnected(device) => { 278 battery_service 279 .lock() 280 .unwrap() 281 .handle_action(BatteryServiceActions::Disconnect(device)); 282 } 283 284 Message::SuspendCallbackRegistered(id) => { 285 suspend.lock().unwrap().callback_registered(id); 286 } 287 288 Message::SuspendCallbackDisconnected(id) => { 289 suspend.lock().unwrap().remove_callback(id); 290 } 291 292 Message::SuspendReady(suspend_id) => { 293 suspend.lock().unwrap().suspend_ready(suspend_id); 294 } 295 296 Message::ResumeReady(suspend_id) => { 297 suspend.lock().unwrap().resume_ready(suspend_id); 298 } 299 300 Message::AudioReconnectOnResumeComplete => { 301 suspend.lock().unwrap().audio_reconnect_complete(); 302 } 303 304 Message::ScannerCallbackDisconnected(id) => { 305 bluetooth_gatt.lock().unwrap().remove_scanner_callback(id); 306 } 307 308 Message::AdvertiserCallbackDisconnected(id) => { 309 bluetooth_gatt.lock().unwrap().remove_adv_callback(id); 310 } 311 312 Message::SocketManagerActions(action) => { 313 bluetooth_socketmgr.lock().unwrap().handle_actions(action); 314 } 315 Message::SocketManagerCallbackDisconnected(id) => { 316 bluetooth_socketmgr.lock().unwrap().remove_callback(id); 317 } 318 Message::BatteryProviderManagerBatteryUpdated(remote_address, battery_set) => { 319 battery_manager 320 .lock() 321 .unwrap() 322 .handle_battery_updated(remote_address, battery_set); 323 } 324 Message::BatteryProviderManagerCallbackDisconnected(id) => { 325 battery_provider_manager.lock().unwrap().remove_battery_provider_callback(id); 326 } 327 Message::BatteryServiceCallbackDisconnected(id) => { 328 battery_service.lock().unwrap().remove_callback(id); 329 } 330 Message::BatteryService(action) => { 331 battery_service.lock().unwrap().handle_action(action); 332 } 333 Message::BatteryServiceRefresh => { 334 battery_service.lock().unwrap().refresh_all_devices(); 335 } 336 Message::BatteryManagerCallbackDisconnected(id) => { 337 battery_manager.lock().unwrap().remove_callback(id); 338 } 339 Message::GattClientCallbackDisconnected(id) => { 340 bluetooth_gatt.lock().unwrap().remove_client_callback(id); 341 } 342 Message::GattServerCallbackDisconnected(id) => { 343 bluetooth_gatt.lock().unwrap().remove_server_callback(id); 344 } 345 Message::AdminCallbackDisconnected(id) => { 346 bluetooth_admin.lock().unwrap().unregister_admin_policy_callback(id); 347 } 348 Message::HidHostEnable => { 349 bluetooth.lock().unwrap().enable_hidhost(); 350 } 351 Message::AdminPolicyChanged => { 352 bluetooth_socketmgr.lock().unwrap().handle_admin_policy_changed(); 353 } 354 Message::Dis(callback) => { 355 bluetooth_dis.lock().unwrap().handle_callbacks(&callback); 356 } 357 // Qualification Only 358 Message::QaAddMediaPlayer(name, browsing_supported) => { 359 bluetooth_media.lock().unwrap().add_player(name, browsing_supported); 360 } 361 Message::QaRfcommSendMsc(dlci, addr) => { 362 bluetooth_socketmgr.lock().unwrap().rfcomm_send_msc(dlci, addr); 363 } 364 Message::QaOnDiscoverableModeChanged(mode) => { 365 bluetooth_qa.lock().unwrap().handle_discoverable_mode_changed(mode); 366 } 367 } 368 } 369 } 370 } 371 372 /// Signifies that the object may be a proxy to a remote RPC object. 373 /// 374 /// An object that implements RPCProxy trait signifies that the object may be a proxy to a remote 375 /// RPC object. Therefore the object may be disconnected and thus should implement 376 /// `register_disconnect` to let others observe the disconnection event. 377 pub trait RPCProxy { 378 /// Registers disconnect observer that will be notified when the remote object is disconnected. register_disconnect(&mut self, _f: Box<dyn Fn(u32) + Send>) -> u32379 fn register_disconnect(&mut self, _f: Box<dyn Fn(u32) + Send>) -> u32 { 380 0 381 } 382 383 /// Returns the ID of the object. For example this would be an object path in D-Bus RPC. get_object_id(&self) -> String384 fn get_object_id(&self) -> String { 385 String::from("") 386 } 387 388 /// Unregisters callback with this id. unregister(&mut self, _id: u32) -> bool389 fn unregister(&mut self, _id: u32) -> bool { 390 false 391 } 392 393 /// Makes this object available for remote call. export_for_rpc(self: Box<Self>)394 fn export_for_rpc(self: Box<Self>) {} 395 } 396