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