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, IBluetoothQA}; 24 use log::debug; 25 use num_derive::{FromPrimitive, ToPrimitive}; 26 use std::sync::{Arc, Mutex}; 27 use tokio::sync::mpsc::channel; 28 use tokio::sync::mpsc::{Receiver, Sender}; 29 use tokio::time::{sleep, Duration}; 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_adv::{dispatch_le_adv_callbacks, AdvertiserActions}; 40 use crate::bluetooth_gatt::{ 41 dispatch_gatt_client_callbacks, dispatch_gatt_server_callbacks, dispatch_le_scanner_callbacks, 42 dispatch_le_scanner_inband_callbacks, BluetoothGatt, GattActions, 43 }; 44 use crate::bluetooth_media::{BluetoothMedia, MediaActions}; 45 use crate::dis::{DeviceInformation, ServiceCallbacks}; 46 use crate::socket_manager::{BluetoothSocketManager, SocketActions}; 47 use crate::suspend::Suspend; 48 use bt_topshim::{ 49 btif::{BaseCallbacks, BtTransport, RawAddress}, 50 profiles::{ 51 a2dp::A2dpCallbacks, 52 avrcp::AvrcpCallbacks, 53 csis::CsisClientCallbacks, 54 gatt::GattAdvCallbacks, 55 gatt::GattAdvInbandCallbacks, 56 gatt::GattClientCallbacks, 57 gatt::GattScannerCallbacks, 58 gatt::GattScannerInbandCallbacks, 59 gatt::GattServerCallbacks, 60 hfp::HfpCallbacks, 61 hid_host::{BthhReportType, HHCallbacks}, 62 le_audio::LeAudioClientCallbacks, 63 sdp::SdpCallbacks, 64 vc::VolumeControlCallbacks, 65 }, 66 }; 67 68 /// Message types that are sent to the stack main dispatch loop. 69 pub enum Message { 70 /// Remove the DBus API. Call it before other AdapterShutdown. 71 InterfaceShutdown, 72 /// Disable the adapter by calling btif disable. 73 AdapterShutdown, 74 /// Clean up the adapter by calling btif cleanup. 75 Cleanup, 76 77 // Adapter is enabled and ready. 78 AdapterReady, 79 80 // Callbacks from libbluetooth 81 A2dp(A2dpCallbacks), 82 Avrcp(AvrcpCallbacks), 83 Base(BaseCallbacks), 84 GattClient(GattClientCallbacks), 85 GattServer(GattServerCallbacks), 86 LeAudioClient(LeAudioClientCallbacks), 87 LeScanner(GattScannerCallbacks), 88 LeScannerInband(GattScannerInbandCallbacks), 89 LeAdvInband(GattAdvInbandCallbacks), 90 LeAdv(GattAdvCallbacks), 91 HidHost(HHCallbacks), 92 Hfp(HfpCallbacks), 93 Sdp(SdpCallbacks), 94 VolumeControl(VolumeControlCallbacks), 95 CsisClient(CsisClientCallbacks), 96 CreateBondWithRetry(BluetoothDevice, BtTransport, u32, Duration), 97 98 // Actions within the stack 99 Media(MediaActions), 100 MediaCallbackDisconnected(u32), 101 TelephonyCallbackDisconnected(u32), 102 103 // Client callback disconnections 104 AdapterCallbackDisconnected(u32), 105 ConnectionCallbackDisconnected(u32), 106 107 // Some delayed actions for the adapter. 108 TriggerUpdateConnectableMode, 109 DelayedAdapterActions(DelayedActions), 110 111 // Follows IBluetooth's on_device_(dis)connected callback but doesn't require depending on 112 // Bluetooth. 113 OnAclConnected(BluetoothDevice, BtTransport), 114 OnAclDisconnected(BluetoothDevice), 115 116 // Suspend related 117 SuspendCallbackRegistered(u32), 118 SuspendCallbackDisconnected(u32), 119 SuspendReady(i32), 120 ResumeReady(i32), 121 AudioReconnectOnResumeComplete, 122 123 // Scanner related 124 ScannerCallbackDisconnected(u32), 125 126 // Advertising related 127 AdvertiserCallbackDisconnected(u32), 128 AdvertiserActions(AdvertiserActions), 129 130 SocketManagerActions(SocketActions), 131 SocketManagerCallbackDisconnected(u32), 132 133 // Battery related 134 BatteryProviderManagerCallbackDisconnected(u32), 135 BatteryProviderManagerBatteryUpdated(RawAddress, BatterySet), 136 BatteryServiceCallbackDisconnected(u32), 137 BatteryService(BatteryServiceActions), 138 BatteryServiceRefresh, 139 BatteryManagerCallbackDisconnected(u32), 140 141 GattActions(GattActions), 142 GattClientCallbackDisconnected(u32), 143 GattServerCallbackDisconnected(u32), 144 145 // Admin policy related 146 AdminCallbackDisconnected(u32), 147 HidHostEnable, 148 AdminPolicyChanged, 149 150 // Dis callbacks 151 Dis(ServiceCallbacks), 152 153 // Device removal 154 DisconnectDevice(BluetoothDevice), 155 156 // Qualification Only 157 QaCallbackDisconnected(u32), 158 QaAddMediaPlayer(String, bool), 159 QaRfcommSendMsc(u8, RawAddress), 160 QaFetchDiscoverableMode, 161 QaFetchConnectable, 162 QaSetConnectable(bool), 163 QaFetchAlias, 164 QaGetHidReport(RawAddress, BthhReportType, u8), 165 QaSetHidReport(RawAddress, BthhReportType, String), 166 QaSendHidData(RawAddress, String), 167 168 // UHid callbacks 169 UHidHfpOutputCallback(RawAddress, u8, u8), 170 UHidTelephonyUseCallback(RawAddress, bool), 171 } 172 173 pub enum BluetoothAPI { 174 Adapter, 175 Battery, 176 Media, 177 Gatt, 178 } 179 180 /// Message types that are sent to the InterfaceManager's dispatch loop. 181 pub enum APIMessage { 182 /// Indicates a subcomponent is ready to receive DBus messages. 183 IsReady(BluetoothAPI), 184 /// Indicates bluetooth is shutting down, so we remove all DBus endpoints. 185 ShutDown, 186 } 187 188 /// Represents suspend mode of a module. 189 /// 190 /// Being in suspend mode means that the module pauses some activities if required for suspend and 191 /// some subsequent API calls will be blocked with a retryable error. 192 #[derive(FromPrimitive, ToPrimitive, Debug, PartialEq, Clone)] 193 pub enum SuspendMode { 194 Normal = 0, 195 Suspending = 1, 196 Suspended = 2, 197 Resuming = 3, 198 } 199 200 /// Umbrella class for the Bluetooth stack. 201 pub struct Stack {} 202 203 impl Stack { 204 /// Creates an mpsc channel for passing messages to the main dispatch loop. create_channel() -> (Sender<Message>, Receiver<Message>)205 pub fn create_channel() -> (Sender<Message>, Receiver<Message>) { 206 channel::<Message>(1) 207 } 208 209 /// Runs the main dispatch loop. dispatch( mut rx: Receiver<Message>, tx: Sender<Message>, api_tx: Sender<APIMessage>, 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>>>, )210 pub async fn dispatch( 211 mut rx: Receiver<Message>, 212 tx: Sender<Message>, 213 api_tx: Sender<APIMessage>, 214 bluetooth: Arc<Mutex<Box<Bluetooth>>>, 215 bluetooth_gatt: Arc<Mutex<Box<BluetoothGatt>>>, 216 battery_service: Arc<Mutex<Box<BatteryService>>>, 217 battery_manager: Arc<Mutex<Box<BatteryManager>>>, 218 battery_provider_manager: Arc<Mutex<Box<BatteryProviderManager>>>, 219 bluetooth_media: Arc<Mutex<Box<BluetoothMedia>>>, 220 suspend: Arc<Mutex<Box<Suspend>>>, 221 bluetooth_socketmgr: Arc<Mutex<Box<BluetoothSocketManager>>>, 222 bluetooth_admin: Arc<Mutex<Box<BluetoothAdmin>>>, 223 bluetooth_dis: Arc<Mutex<Box<DeviceInformation>>>, 224 bluetooth_qa: Arc<Mutex<Box<BluetoothQA>>>, 225 ) { 226 loop { 227 let m = rx.recv().await; 228 229 if m.is_none() { 230 eprintln!("Message dispatch loop quit"); 231 break; 232 } 233 234 match m.unwrap() { 235 Message::InterfaceShutdown => { 236 let txl = api_tx.clone(); 237 tokio::spawn(async move { 238 let _ = txl.send(APIMessage::ShutDown).await; 239 }); 240 } 241 242 Message::AdapterShutdown => { 243 bluetooth.lock().unwrap().disable(); 244 } 245 246 Message::Cleanup => { 247 bluetooth.lock().unwrap().cleanup(); 248 } 249 250 Message::AdapterReady => { 251 // Initialize objects that need the adapter to be fully 252 // enabled before running. 253 254 // Register device information service. 255 bluetooth_dis.lock().unwrap().initialize(); 256 } 257 258 Message::A2dp(a) => { 259 bluetooth_media.lock().unwrap().dispatch_a2dp_callbacks(a); 260 } 261 262 Message::Avrcp(av) => { 263 bluetooth_media.lock().unwrap().dispatch_avrcp_callbacks(av); 264 } 265 266 Message::Base(b) => { 267 dispatch_base_callbacks(bluetooth.lock().unwrap().as_mut(), b.clone()); 268 dispatch_base_callbacks(suspend.lock().unwrap().as_mut(), b); 269 } 270 271 // When pairing is busy for any reason, the bond cannot be created. 272 // Allow retries until it is ready for bonding. 273 Message::CreateBondWithRetry(device, bt_transport, num_attempts, retry_delay) => { 274 if num_attempts == 0 { 275 continue; 276 } 277 278 let mut bt = bluetooth.lock().unwrap(); 279 if !bt.is_pairing_busy() { 280 bt.create_bond(device, bt_transport); 281 continue; 282 } 283 284 let txl = tx.clone(); 285 tokio::spawn(async move { 286 sleep(retry_delay).await; 287 let _ = txl 288 .send(Message::CreateBondWithRetry( 289 device, 290 bt_transport, 291 num_attempts - 1, 292 retry_delay, 293 )) 294 .await; 295 }); 296 } 297 298 Message::GattClient(m) => { 299 dispatch_gatt_client_callbacks(bluetooth_gatt.lock().unwrap().as_mut(), m); 300 } 301 302 Message::GattServer(m) => { 303 dispatch_gatt_server_callbacks(bluetooth_gatt.lock().unwrap().as_mut(), m); 304 } 305 306 Message::LeAudioClient(a) => { 307 bluetooth_media.lock().unwrap().dispatch_le_audio_callbacks(a); 308 } 309 310 Message::VolumeControl(a) => { 311 bluetooth_media.lock().unwrap().dispatch_vc_callbacks(a); 312 } 313 314 Message::CsisClient(a) => { 315 bluetooth_media.lock().unwrap().dispatch_csis_callbacks(a); 316 } 317 318 Message::LeScanner(m) => { 319 dispatch_le_scanner_callbacks(bluetooth_gatt.lock().unwrap().as_mut(), m); 320 } 321 322 Message::LeScannerInband(m) => { 323 dispatch_le_scanner_inband_callbacks( 324 bluetooth_gatt.lock().unwrap().as_mut(), 325 m, 326 ); 327 } 328 329 Message::LeAdvInband(m) => { 330 debug!("Received LeAdvInband message: {:?}. This is unexpected!", m); 331 } 332 333 Message::LeAdv(m) => { 334 dispatch_le_adv_callbacks(bluetooth_gatt.lock().unwrap().as_mut(), m); 335 } 336 337 Message::Hfp(hf) => { 338 bluetooth_media.lock().unwrap().dispatch_hfp_callbacks(hf); 339 } 340 341 Message::HidHost(h) => { 342 dispatch_hid_host_callbacks(bluetooth.lock().unwrap().as_mut(), h); 343 } 344 345 Message::Sdp(s) => { 346 dispatch_sdp_callbacks(bluetooth.lock().unwrap().as_mut(), s); 347 } 348 349 Message::Media(action) => { 350 bluetooth_media.lock().unwrap().dispatch_media_actions(action); 351 } 352 353 Message::MediaCallbackDisconnected(cb_id) => { 354 bluetooth_media.lock().unwrap().remove_callback(cb_id); 355 } 356 357 Message::TelephonyCallbackDisconnected(cb_id) => { 358 bluetooth_media.lock().unwrap().remove_telephony_callback(cb_id); 359 } 360 361 Message::AdapterCallbackDisconnected(id) => { 362 bluetooth.lock().unwrap().adapter_callback_disconnected(id); 363 } 364 365 Message::ConnectionCallbackDisconnected(id) => { 366 bluetooth.lock().unwrap().connection_callback_disconnected(id); 367 } 368 369 Message::TriggerUpdateConnectableMode => { 370 let is_listening = bluetooth_socketmgr.lock().unwrap().is_listening(); 371 bluetooth.lock().unwrap().handle_delayed_actions( 372 DelayedActions::UpdateConnectableMode(is_listening), 373 ); 374 } 375 376 Message::DelayedAdapterActions(action) => { 377 bluetooth.lock().unwrap().handle_delayed_actions(action); 378 } 379 380 // Any service needing an updated list of devices can have an 381 // update method triggered from here rather than needing a 382 // reference to Bluetooth. 383 Message::OnAclConnected(device, transport) => { 384 battery_service 385 .lock() 386 .unwrap() 387 .handle_action(BatteryServiceActions::Connect(device, transport)); 388 } 389 390 // For battery service, use this to clean up internal handles. GATT connection is 391 // already dropped if ACL disconnect has occurred. 392 Message::OnAclDisconnected(device) => { 393 battery_service 394 .lock() 395 .unwrap() 396 .handle_action(BatteryServiceActions::Disconnect(device)); 397 } 398 399 Message::SuspendCallbackRegistered(id) => { 400 suspend.lock().unwrap().callback_registered(id); 401 } 402 403 Message::SuspendCallbackDisconnected(id) => { 404 suspend.lock().unwrap().remove_callback(id); 405 } 406 407 Message::SuspendReady(suspend_id) => { 408 suspend.lock().unwrap().suspend_ready(suspend_id); 409 } 410 411 Message::ResumeReady(suspend_id) => { 412 suspend.lock().unwrap().resume_ready(suspend_id); 413 } 414 415 Message::AudioReconnectOnResumeComplete => { 416 suspend.lock().unwrap().audio_reconnect_complete(); 417 } 418 419 Message::ScannerCallbackDisconnected(id) => { 420 bluetooth_gatt.lock().unwrap().remove_scanner_callback(id); 421 } 422 423 Message::AdvertiserCallbackDisconnected(id) => { 424 bluetooth_gatt.lock().unwrap().remove_adv_callback(id); 425 } 426 427 Message::AdvertiserActions(action) => { 428 bluetooth_gatt.lock().unwrap().handle_adv_action(action); 429 } 430 431 Message::SocketManagerActions(action) => { 432 bluetooth_socketmgr.lock().unwrap().handle_actions(action); 433 } 434 Message::SocketManagerCallbackDisconnected(id) => { 435 bluetooth_socketmgr.lock().unwrap().remove_callback(id); 436 } 437 Message::BatteryProviderManagerBatteryUpdated(remote_address, battery_set) => { 438 battery_manager 439 .lock() 440 .unwrap() 441 .handle_battery_updated(remote_address, battery_set); 442 } 443 Message::BatteryProviderManagerCallbackDisconnected(id) => { 444 battery_provider_manager.lock().unwrap().remove_battery_provider_callback(id); 445 } 446 Message::BatteryServiceCallbackDisconnected(id) => { 447 battery_service.lock().unwrap().remove_callback(id); 448 } 449 Message::BatteryService(action) => { 450 battery_service.lock().unwrap().handle_action(action); 451 } 452 Message::BatteryServiceRefresh => { 453 battery_service.lock().unwrap().refresh_all_devices(); 454 } 455 Message::BatteryManagerCallbackDisconnected(id) => { 456 battery_manager.lock().unwrap().remove_callback(id); 457 } 458 Message::GattActions(action) => { 459 bluetooth_gatt.lock().unwrap().handle_action(action); 460 } 461 Message::GattClientCallbackDisconnected(id) => { 462 bluetooth_gatt.lock().unwrap().remove_client_callback(id); 463 } 464 Message::GattServerCallbackDisconnected(id) => { 465 bluetooth_gatt.lock().unwrap().remove_server_callback(id); 466 } 467 Message::AdminCallbackDisconnected(id) => { 468 bluetooth_admin.lock().unwrap().unregister_admin_policy_callback(id); 469 } 470 Message::HidHostEnable => { 471 bluetooth.lock().unwrap().enable_hidhost(); 472 } 473 Message::AdminPolicyChanged => { 474 bluetooth_socketmgr.lock().unwrap().handle_admin_policy_changed(); 475 } 476 Message::Dis(callback) => { 477 bluetooth_dis.lock().unwrap().handle_callbacks(&callback); 478 } 479 Message::DisconnectDevice(addr) => { 480 bluetooth.lock().unwrap().disconnect_all_enabled_profiles(addr); 481 } 482 // Qualification Only 483 Message::QaAddMediaPlayer(name, browsing_supported) => { 484 bluetooth_media.lock().unwrap().add_player(name, browsing_supported); 485 } 486 Message::QaRfcommSendMsc(dlci, addr) => { 487 bluetooth_socketmgr.lock().unwrap().rfcomm_send_msc(dlci, addr); 488 } 489 Message::QaCallbackDisconnected(id) => { 490 bluetooth_qa.lock().unwrap().unregister_qa_callback(id); 491 } 492 Message::QaFetchDiscoverableMode => { 493 let mode = bluetooth.lock().unwrap().get_discoverable_mode_internal(); 494 bluetooth_qa.lock().unwrap().on_fetch_discoverable_mode_completed(mode); 495 } 496 Message::QaFetchConnectable => { 497 let connectable = bluetooth.lock().unwrap().get_connectable_internal(); 498 bluetooth_qa.lock().unwrap().on_fetch_connectable_completed(connectable); 499 } 500 Message::QaSetConnectable(mode) => { 501 let succeed = bluetooth.lock().unwrap().set_connectable_internal(mode); 502 bluetooth_qa.lock().unwrap().on_set_connectable_completed(succeed); 503 } 504 Message::QaFetchAlias => { 505 let alias = bluetooth.lock().unwrap().get_alias_internal(); 506 bluetooth_qa.lock().unwrap().on_fetch_alias_completed(alias); 507 } 508 Message::QaGetHidReport(addr, report_type, report_id) => { 509 let status = bluetooth.lock().unwrap().get_hid_report_internal( 510 addr, 511 report_type, 512 report_id, 513 ); 514 bluetooth_qa.lock().unwrap().on_get_hid_report_completed(status); 515 } 516 Message::QaSetHidReport(addr, report_type, report) => { 517 let status = bluetooth.lock().unwrap().set_hid_report_internal( 518 addr, 519 report_type, 520 report, 521 ); 522 bluetooth_qa.lock().unwrap().on_set_hid_report_completed(status); 523 } 524 Message::QaSendHidData(addr, data) => { 525 let status = bluetooth.lock().unwrap().send_hid_data_internal(addr, data); 526 bluetooth_qa.lock().unwrap().on_send_hid_data_completed(status); 527 } 528 529 // UHid callbacks 530 Message::UHidHfpOutputCallback(addr, id, data) => { 531 bluetooth_media 532 .lock() 533 .unwrap() 534 .dispatch_uhid_hfp_output_callback(addr, id, data); 535 } 536 537 Message::UHidTelephonyUseCallback(addr, state) => { 538 bluetooth_media 539 .lock() 540 .unwrap() 541 .dispatch_uhid_telephony_use_callback(addr, state); 542 } 543 } 544 } 545 } 546 } 547 548 /// Signifies that the object may be a proxy to a remote RPC object. 549 /// 550 /// An object that implements RPCProxy trait signifies that the object may be a proxy to a remote 551 /// RPC object. Therefore the object may be disconnected and thus should implement 552 /// `register_disconnect` to let others observe the disconnection event. 553 pub trait RPCProxy { 554 /// Registers disconnect observer that will be notified when the remote object is disconnected. register_disconnect(&mut self, _f: Box<dyn Fn(u32) + Send>) -> u32555 fn register_disconnect(&mut self, _f: Box<dyn Fn(u32) + Send>) -> u32 { 556 0 557 } 558 559 /// Returns the ID of the object. For example this would be an object path in D-Bus RPC. get_object_id(&self) -> String560 fn get_object_id(&self) -> String { 561 String::from("") 562 } 563 564 /// Unregisters callback with this id. unregister(&mut self, _id: u32) -> bool565 fn unregister(&mut self, _id: u32) -> bool { 566 false 567 } 568 569 /// Makes this object available for remote call. export_for_rpc(self: Box<Self>)570 fn export_for_rpc(self: Box<Self>) {} 571 } 572