1 use dbus::{channel::MatchingReceiver, message::MatchRule, nonblock::SyncConnection}; 2 use dbus_crossroads::Crossroads; 3 use dbus_projection::DisconnectWatcher; 4 5 use std::sync::{Arc, Mutex}; 6 use tokio::sync::mpsc::{channel, Receiver, Sender}; 7 8 use btstack::{ 9 battery_manager::BatteryManager, battery_provider_manager::BatteryProviderManager, 10 battery_service::BatteryService, bluetooth::Bluetooth, bluetooth::IBluetooth, 11 bluetooth_admin::BluetoothAdmin, bluetooth_gatt::BluetoothGatt, 12 bluetooth_logging::BluetoothLogging, bluetooth_media::BluetoothMedia, 13 bluetooth_qa::BluetoothQA, socket_manager::BluetoothSocketManager, suspend::Suspend, 14 APIMessage, BluetoothAPI, Message, 15 }; 16 17 use crate::iface_battery_manager; 18 use crate::iface_battery_provider_manager; 19 use crate::iface_bluetooth; 20 use crate::iface_bluetooth_admin; 21 use crate::iface_bluetooth_gatt; 22 use crate::iface_bluetooth_media; 23 use crate::iface_bluetooth_qa; 24 use crate::iface_bluetooth_telephony; 25 use crate::iface_logging; 26 27 pub(crate) struct InterfaceManager {} 28 29 impl InterfaceManager { make_object_name(idx: i32, name: &str) -> String30 fn make_object_name(idx: i32, name: &str) -> String { 31 format!("/org/chromium/bluetooth/hci{}/{}", idx, name) 32 } 33 34 /// Creates an mpsc channel for passing messages to the main dispatch loop. create_channel() -> (Sender<APIMessage>, Receiver<APIMessage>)35 pub fn create_channel() -> (Sender<APIMessage>, Receiver<APIMessage>) { 36 channel::<APIMessage>(1) 37 } 38 39 /// Runs the dispatch loop for APIMessage 40 /// 41 /// # Arguments 42 /// 43 /// * `rx` - The receiver channel for APIMessage 44 /// * `tx` - The sender channel for Message 45 /// * `virt_index` - The virtual index of the adapter 46 /// * `conn` - The DBus connection 47 /// * `conn_join_handle` - The thread handle that's maintaining the DBus resource 48 /// * `disconnect_watcher` - DisconnectWatcher to monitor client disconnects 49 /// * `bluetooth` - Implementation of the Bluetooth API 50 /// other implementations follow. 51 /// dispatch( mut rx: Receiver<APIMessage>, tx: Sender<Message>, virt_index: i32, conn: Arc<SyncConnection>, conn_join_handle: tokio::task::JoinHandle<()>, disconnect_watcher: Arc<Mutex<DisconnectWatcher>>, bluetooth: Arc<Mutex<Box<Bluetooth>>>, bluetooth_admin: Arc<Mutex<Box<BluetoothAdmin>>>, 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>>>, bluetooth_qa: Arc<Mutex<Box<BluetoothQA>>>, bt_sock_mgr: Arc<Mutex<Box<BluetoothSocketManager>>>, suspend: Arc<Mutex<Box<Suspend>>>, logging: Arc<Mutex<Box<BluetoothLogging>>>, )52 pub async fn dispatch( 53 mut rx: Receiver<APIMessage>, 54 tx: Sender<Message>, 55 virt_index: i32, 56 conn: Arc<SyncConnection>, 57 conn_join_handle: tokio::task::JoinHandle<()>, 58 disconnect_watcher: Arc<Mutex<DisconnectWatcher>>, 59 bluetooth: Arc<Mutex<Box<Bluetooth>>>, 60 bluetooth_admin: Arc<Mutex<Box<BluetoothAdmin>>>, 61 bluetooth_gatt: Arc<Mutex<Box<BluetoothGatt>>>, 62 battery_service: Arc<Mutex<Box<BatteryService>>>, 63 battery_manager: Arc<Mutex<Box<BatteryManager>>>, 64 battery_provider_manager: Arc<Mutex<Box<BatteryProviderManager>>>, 65 bluetooth_media: Arc<Mutex<Box<BluetoothMedia>>>, 66 bluetooth_qa: Arc<Mutex<Box<BluetoothQA>>>, 67 bt_sock_mgr: Arc<Mutex<Box<BluetoothSocketManager>>>, 68 suspend: Arc<Mutex<Box<Suspend>>>, 69 logging: Arc<Mutex<Box<BluetoothLogging>>>, 70 ) { 71 // Prepare D-Bus interfaces. 72 let cr = Arc::new(Mutex::new(Crossroads::new())); 73 cr.lock().unwrap().set_async_support(Some(( 74 conn.clone(), 75 Box::new(|x| { 76 tokio::spawn(x); 77 }), 78 ))); 79 80 // Announce the exported adapter objects so that clients can properly detect the readiness 81 // of the adapter APIs. 82 cr.lock().unwrap().set_object_manager_support(Some(conn.clone())); 83 let object_manager = cr.lock().unwrap().object_manager(); 84 cr.lock().unwrap().insert("/", &[object_manager], {}); 85 86 // Set up handling of D-Bus methods. This must be done before exporting interfaces so that 87 // clients that rely on InterfacesAdded signal can rely on us being ready to handle methods 88 // on those exported interfaces. 89 let cr_clone = cr.clone(); 90 conn.start_receive( 91 MatchRule::new_method_call(), 92 Box::new(move |msg, conn| { 93 cr_clone.lock().unwrap().handle_message(msg, conn).unwrap(); 94 true 95 }), 96 ); 97 98 // Register D-Bus method handlers of IBluetooth. 99 let adapter_iface = iface_bluetooth::export_bluetooth_dbus_intf( 100 conn.clone(), 101 &mut cr.lock().unwrap(), 102 disconnect_watcher.clone(), 103 ); 104 let qa_iface = iface_bluetooth_qa::export_bluetooth_qa_dbus_intf( 105 conn.clone(), 106 &mut cr.lock().unwrap(), 107 disconnect_watcher.clone(), 108 ); 109 let qa_legacy_iface = iface_bluetooth::export_bluetooth_qa_legacy_dbus_intf( 110 conn.clone(), 111 &mut cr.lock().unwrap(), 112 disconnect_watcher.clone(), 113 ); 114 let socket_mgr_iface = iface_bluetooth::export_socket_mgr_intf( 115 conn.clone(), 116 &mut cr.lock().unwrap(), 117 disconnect_watcher.clone(), 118 ); 119 let suspend_iface = iface_bluetooth::export_suspend_dbus_intf( 120 conn.clone(), 121 &mut cr.lock().unwrap(), 122 disconnect_watcher.clone(), 123 ); 124 let logging_iface = iface_logging::export_bluetooth_logging_dbus_intf( 125 conn.clone(), 126 &mut cr.lock().unwrap(), 127 disconnect_watcher.clone(), 128 ); 129 130 // Register D-Bus method handlers of IBluetoothGatt. 131 let gatt_iface = iface_bluetooth_gatt::export_bluetooth_gatt_dbus_intf( 132 conn.clone(), 133 &mut cr.lock().unwrap(), 134 disconnect_watcher.clone(), 135 ); 136 137 let media_iface = iface_bluetooth_media::export_bluetooth_media_dbus_intf( 138 conn.clone(), 139 &mut cr.lock().unwrap(), 140 disconnect_watcher.clone(), 141 ); 142 143 let telephony_iface = iface_bluetooth_telephony::export_bluetooth_telephony_dbus_intf( 144 conn.clone(), 145 &mut cr.lock().unwrap(), 146 disconnect_watcher.clone(), 147 ); 148 149 let battery_provider_manager_iface = 150 iface_battery_provider_manager::export_battery_provider_manager_dbus_intf( 151 conn.clone(), 152 &mut cr.lock().unwrap(), 153 disconnect_watcher.clone(), 154 ); 155 156 let battery_manager_iface = iface_battery_manager::export_battery_manager_dbus_intf( 157 conn.clone(), 158 &mut cr.lock().unwrap(), 159 disconnect_watcher.clone(), 160 ); 161 162 let admin_iface = iface_bluetooth_admin::export_bluetooth_admin_dbus_intf( 163 conn.clone(), 164 &mut cr.lock().unwrap(), 165 disconnect_watcher.clone(), 166 ); 167 168 // Create mixin object for Bluetooth + Suspend interfaces. 169 let mixin = Box::new(iface_bluetooth::BluetoothMixin { 170 adapter: bluetooth.clone(), 171 qa: bluetooth.clone(), 172 suspend: suspend.clone(), 173 socket_mgr: bt_sock_mgr.clone(), 174 }); 175 176 loop { 177 let m = rx.recv().await; 178 179 if m.is_none() { 180 eprintln!("APIMessage dispatch loop quit"); 181 break; 182 } 183 184 match m.unwrap() { 185 APIMessage::IsReady(api) => match api { 186 BluetoothAPI::Adapter => { 187 cr.lock().unwrap().insert( 188 Self::make_object_name(virt_index, "adapter"), 189 &[adapter_iface, qa_legacy_iface, socket_mgr_iface, suspend_iface], 190 mixin.clone(), 191 ); 192 193 cr.lock().unwrap().insert( 194 Self::make_object_name(virt_index, "admin"), 195 &[admin_iface], 196 bluetooth_admin.clone(), 197 ); 198 199 cr.lock().unwrap().insert( 200 Self::make_object_name(virt_index, "logging"), 201 &[logging_iface], 202 logging.clone(), 203 ); 204 205 cr.lock().unwrap().insert( 206 Self::make_object_name(virt_index, "qa"), 207 &[qa_iface], 208 bluetooth_qa.clone(), 209 ); 210 211 // AdvertiseManager selects the stack per is_le_ext_adv_supported. 212 // Initialize it after Adapter is ready. 213 let bt_clone = bluetooth.clone(); 214 let gatt_clone = bluetooth_gatt.clone(); 215 tokio::spawn(async move { 216 let is_le_ext_adv_supported = 217 bt_clone.lock().unwrap().is_le_extended_advertising_supported(); 218 gatt_clone 219 .lock() 220 .unwrap() 221 .init_adv_manager(bt_clone, is_le_ext_adv_supported); 222 }); 223 } 224 BluetoothAPI::Gatt => { 225 cr.lock().unwrap().insert( 226 Self::make_object_name(virt_index, "gatt"), 227 &[gatt_iface], 228 bluetooth_gatt.clone(), 229 ); 230 231 // Battery service is on top of Gatt. Only initialize it after 232 // GATT is ready. 233 let bs = battery_service.clone(); 234 tokio::spawn(async move { 235 bs.lock().unwrap().init(); 236 }); 237 } 238 BluetoothAPI::Media => { 239 cr.lock().unwrap().insert( 240 Self::make_object_name(virt_index, "media"), 241 &[media_iface], 242 bluetooth_media.clone(), 243 ); 244 245 cr.lock().unwrap().insert( 246 Self::make_object_name(virt_index, "telephony"), 247 &[telephony_iface], 248 bluetooth_media.clone(), 249 ); 250 } 251 BluetoothAPI::Battery => { 252 cr.lock().unwrap().insert( 253 Self::make_object_name(virt_index, "battery_provider_manager"), 254 &[battery_provider_manager_iface], 255 battery_provider_manager.clone(), 256 ); 257 258 cr.lock().unwrap().insert( 259 Self::make_object_name(virt_index, "battery_manager"), 260 &[battery_manager_iface], 261 battery_manager.clone(), 262 ); 263 } 264 }, 265 266 APIMessage::ShutDown => { 267 // To shut down the connection, call _handle.abort() and drop the connection. 268 conn_join_handle.abort(); 269 drop(conn); 270 271 let tx = tx.clone(); 272 tokio::spawn(async move { 273 let _ = tx.send(Message::AdapterShutdown).await; 274 }); 275 break; 276 } 277 } 278 } 279 } 280 } 281