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 #[macro_use] 7 extern crate num_derive; 8 9 pub mod bluetooth; 10 pub mod bluetooth_gatt; 11 pub mod bluetooth_media; 12 pub mod suspend; 13 pub mod uuid; 14 15 use log::debug; 16 use std::sync::{Arc, Mutex}; 17 use tokio::sync::mpsc::channel; 18 use tokio::sync::mpsc::{Receiver, Sender}; 19 20 use crate::bluetooth::Bluetooth; 21 use crate::bluetooth_gatt::BluetoothGatt; 22 use crate::bluetooth_media::{BluetoothMedia, MediaActions}; 23 use crate::suspend::Suspend; 24 use bt_topshim::{ 25 btif::BaseCallbacks, 26 profiles::{ 27 a2dp::A2dpCallbacks, avrcp::AvrcpCallbacks, gatt::GattClientCallbacks, 28 gatt::GattServerCallbacks, hfp::HfpCallbacks, hid_host::HHCallbacks, sdp::SdpCallbacks, 29 }, 30 }; 31 32 #[derive(Clone, Debug)] 33 pub enum BluetoothCallbackType { 34 Adapter, 35 Connection, 36 } 37 38 /// Message types that are sent to the stack main dispatch loop. 39 pub enum Message { 40 // Callbacks from libbluetooth 41 A2dp(A2dpCallbacks), 42 Avrcp(AvrcpCallbacks), 43 Base(BaseCallbacks), 44 GattClient(GattClientCallbacks), 45 GattServer(GattServerCallbacks), 46 HidHost(HHCallbacks), 47 Hfp(HfpCallbacks), 48 Sdp(SdpCallbacks), 49 50 // Actions within the stack 51 Media(MediaActions), 52 53 // Client callback disconnections 54 BluetoothCallbackDisconnected(u32, BluetoothCallbackType), 55 56 // Update list of found devices and remove old instances. 57 DeviceFreshnessCheck, 58 59 // Suspend related 60 SuspendCallbackRegistered(u32), 61 SuspendCallbackDisconnected(u32), 62 } 63 64 /// Umbrella class for the Bluetooth stack. 65 pub struct Stack {} 66 67 impl Stack { 68 /// Creates an mpsc channel for passing messages to the main dispatch loop. create_channel() -> (Sender<Message>, Receiver<Message>)69 pub fn create_channel() -> (Sender<Message>, Receiver<Message>) { 70 channel::<Message>(1) 71 } 72 73 /// Runs the main dispatch loop. dispatch( mut rx: Receiver<Message>, bluetooth: Arc<Mutex<Box<Bluetooth>>>, bluetooth_gatt: Arc<Mutex<Box<BluetoothGatt>>>, bluetooth_media: Arc<Mutex<Box<BluetoothMedia>>>, suspend: Arc<Mutex<Box<Suspend>>>, )74 pub async fn dispatch( 75 mut rx: Receiver<Message>, 76 bluetooth: Arc<Mutex<Box<Bluetooth>>>, 77 bluetooth_gatt: Arc<Mutex<Box<BluetoothGatt>>>, 78 bluetooth_media: Arc<Mutex<Box<BluetoothMedia>>>, 79 suspend: Arc<Mutex<Box<Suspend>>>, 80 ) { 81 loop { 82 let m = rx.recv().await; 83 84 if m.is_none() { 85 eprintln!("Message dispatch loop quit"); 86 break; 87 } 88 89 match m.unwrap() { 90 Message::A2dp(a) => { 91 bluetooth_media.lock().unwrap().dispatch_a2dp_callbacks(a); 92 } 93 94 Message::Avrcp(av) => { 95 bluetooth_media.lock().unwrap().dispatch_avrcp_callbacks(av); 96 } 97 98 Message::Base(b) => { 99 bluetooth.lock().unwrap().dispatch_base_callbacks(b); 100 } 101 102 Message::GattClient(m) => { 103 bluetooth_gatt.lock().unwrap().dispatch_gatt_client_callbacks(m); 104 } 105 106 Message::GattServer(m) => { 107 // TODO(b/193685149): dispatch GATT server callbacks. 108 debug!("Unhandled Message::GattServer: {:?}", m); 109 } 110 111 Message::Hfp(hf) => { 112 bluetooth_media.lock().unwrap().dispatch_hfp_callbacks(hf); 113 } 114 115 Message::HidHost(_h) => { 116 // TODO(abps) - Handle hid host callbacks 117 debug!("Received HH callback"); 118 } 119 120 Message::Sdp(s) => { 121 bluetooth.lock().unwrap().dispatch_sdp_callbacks(s); 122 } 123 124 Message::Media(action) => { 125 bluetooth_media.lock().unwrap().dispatch_media_actions(action); 126 } 127 128 Message::BluetoothCallbackDisconnected(id, cb_type) => { 129 bluetooth.lock().unwrap().callback_disconnected(id, cb_type); 130 } 131 132 Message::DeviceFreshnessCheck => { 133 bluetooth.lock().unwrap().trigger_freshness_check(); 134 } 135 136 Message::SuspendCallbackRegistered(id) => { 137 suspend.lock().unwrap().callback_registered(id); 138 } 139 140 Message::SuspendCallbackDisconnected(id) => { 141 suspend.lock().unwrap().remove_callback(id); 142 } 143 } 144 } 145 } 146 } 147 148 /// Signifies that the object may be a proxy to a remote RPC object. 149 /// 150 /// An object that implements RPCProxy trait signifies that the object may be a proxy to a remote 151 /// RPC object. Therefore the object may be disconnected and thus should implement 152 /// `register_disconnect` to let others observe the disconnection event. 153 pub trait RPCProxy { 154 /// Registers disconnect observer that will be notified when the remote object is disconnected. register_disconnect(&mut self, f: Box<dyn Fn(u32) + Send>) -> u32155 fn register_disconnect(&mut self, f: Box<dyn Fn(u32) + Send>) -> u32; 156 157 /// Returns the ID of the object. For example this would be an object path in D-Bus RPC. get_object_id(&self) -> String158 fn get_object_id(&self) -> String; 159 160 /// Unregisters callback with this id. unregister(&mut self, id: u32) -> bool161 fn unregister(&mut self, id: u32) -> bool; 162 163 /// Makes this object available for remote call. export_for_rpc(self: Box<Self>)164 fn export_for_rpc(self: Box<Self>); 165 } 166