1 use dbus::channel::MatchingReceiver; 2 use dbus::message::MatchRule; 3 use dbus::nonblock::SyncConnection; 4 use dbus_crossroads::Crossroads; 5 use dbus_projection::DisconnectWatcher; 6 7 use std::sync::{Arc, Mutex}; 8 use tokio::sync::mpsc::{channel, Receiver, Sender}; 9 10 use btstack::battery_manager::BatteryManager; 11 use btstack::battery_provider_manager::BatteryProviderManager; 12 use btstack::bluetooth::{Bluetooth, SigData}; 13 use btstack::bluetooth_admin::BluetoothAdmin; 14 use btstack::bluetooth_gatt::BluetoothGatt; 15 use btstack::bluetooth_logging::BluetoothLogging; 16 use btstack::bluetooth_media::BluetoothMedia; 17 use btstack::bluetooth_qa::BluetoothQA; 18 use btstack::socket_manager::BluetoothSocketManager; 19 use btstack::suspend::Suspend; 20 use btstack::{APIMessage, BluetoothAPI}; 21 22 use crate::{ 23 iface_battery_manager, iface_battery_provider_manager, iface_bluetooth, iface_bluetooth_admin, 24 iface_bluetooth_gatt, iface_bluetooth_media, iface_bluetooth_qa, iface_bluetooth_telephony, 25 iface_logging, 26 }; 27 28 pub(crate) struct InterfaceManager {} 29 30 impl InterfaceManager { make_object_name(idx: i32, name: &str) -> String31 fn make_object_name(idx: i32, name: &str) -> String { 32 format!("/org/chromium/bluetooth/hci{}/{}", idx, name) 33 } 34 35 /// Creates an mpsc channel for passing messages to the main dispatch loop. create_channel() -> (Sender<APIMessage>, Receiver<APIMessage>)36 pub fn create_channel() -> (Sender<APIMessage>, Receiver<APIMessage>) { 37 channel::<APIMessage>(1) 38 } 39 40 /// Runs the dispatch loop for APIMessage 41 /// 42 /// # Arguments 43 /// 44 /// * `rx` - The receiver channel for APIMessage 45 /// * `tx` - The sender channel for Message 46 /// * `virt_index` - The virtual index of the adapter 47 /// * `conn` - The DBus connection 48 /// * `conn_join_handle` - The thread handle that's maintaining the DBus resource 49 /// * `disconnect_watcher` - DisconnectWatcher to monitor client disconnects 50 /// * `bluetooth` - Implementation of the Bluetooth API 51 /// other implementations follow. 52 #[allow(clippy::too_many_arguments)] dispatch( mut rx: Receiver<APIMessage>, virt_index: i32, conn: Arc<SyncConnection>, conn_join_handle: tokio::task::JoinHandle<()>, disconnect_watcher: Arc<Mutex<DisconnectWatcher>>, sig_notifier: Arc<SigData>, 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>>>, )53 pub async fn dispatch( 54 mut rx: Receiver<APIMessage>, 55 virt_index: i32, 56 conn: Arc<SyncConnection>, 57 conn_join_handle: tokio::task::JoinHandle<()>, 58 disconnect_watcher: Arc<Mutex<DisconnectWatcher>>, 59 sig_notifier: Arc<SigData>, 60 bluetooth: Arc<Mutex<Box<Bluetooth>>>, 61 bluetooth_admin: Arc<Mutex<Box<BluetoothAdmin>>>, 62 bluetooth_gatt: Arc<Mutex<Box<BluetoothGatt>>>, 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 *sig_notifier.api_enabled.lock().unwrap() = true; 99 sig_notifier.api_notify.notify_all(); 100 101 // Register D-Bus method handlers of IBluetooth. 102 let adapter_iface = iface_bluetooth::export_bluetooth_dbus_intf( 103 conn.clone(), 104 &mut cr.lock().unwrap(), 105 disconnect_watcher.clone(), 106 ); 107 let qa_iface = iface_bluetooth_qa::export_bluetooth_qa_dbus_intf( 108 conn.clone(), 109 &mut cr.lock().unwrap(), 110 disconnect_watcher.clone(), 111 ); 112 let qa_legacy_iface = iface_bluetooth::export_bluetooth_qa_legacy_dbus_intf( 113 conn.clone(), 114 &mut cr.lock().unwrap(), 115 disconnect_watcher.clone(), 116 ); 117 let socket_mgr_iface = iface_bluetooth::export_socket_mgr_intf( 118 conn.clone(), 119 &mut cr.lock().unwrap(), 120 disconnect_watcher.clone(), 121 ); 122 let suspend_iface = iface_bluetooth::export_suspend_dbus_intf( 123 conn.clone(), 124 &mut cr.lock().unwrap(), 125 disconnect_watcher.clone(), 126 ); 127 let logging_iface = iface_logging::export_bluetooth_logging_dbus_intf( 128 conn.clone(), 129 &mut cr.lock().unwrap(), 130 disconnect_watcher.clone(), 131 ); 132 133 // Register D-Bus method handlers of IBluetoothGatt. 134 let gatt_iface = iface_bluetooth_gatt::export_bluetooth_gatt_dbus_intf( 135 conn.clone(), 136 &mut cr.lock().unwrap(), 137 disconnect_watcher.clone(), 138 ); 139 140 let media_iface = iface_bluetooth_media::export_bluetooth_media_dbus_intf( 141 conn.clone(), 142 &mut cr.lock().unwrap(), 143 disconnect_watcher.clone(), 144 ); 145 146 let telephony_iface = iface_bluetooth_telephony::export_bluetooth_telephony_dbus_intf( 147 conn.clone(), 148 &mut cr.lock().unwrap(), 149 disconnect_watcher.clone(), 150 ); 151 152 let battery_provider_manager_iface = 153 iface_battery_provider_manager::export_battery_provider_manager_dbus_intf( 154 conn.clone(), 155 &mut cr.lock().unwrap(), 156 disconnect_watcher.clone(), 157 ); 158 159 let battery_manager_iface = iface_battery_manager::export_battery_manager_dbus_intf( 160 conn.clone(), 161 &mut cr.lock().unwrap(), 162 disconnect_watcher.clone(), 163 ); 164 165 let admin_iface = iface_bluetooth_admin::export_bluetooth_admin_dbus_intf( 166 conn.clone(), 167 &mut cr.lock().unwrap(), 168 disconnect_watcher.clone(), 169 ); 170 171 // Create mixin object for Bluetooth + Suspend interfaces. 172 let mixin = Box::new(iface_bluetooth::BluetoothMixin { 173 adapter: bluetooth.clone(), 174 qa: bluetooth.clone(), 175 suspend: suspend.clone(), 176 socket_mgr: bt_sock_mgr.clone(), 177 }); 178 179 loop { 180 let m = rx.recv().await; 181 182 if m.is_none() { 183 eprintln!("APIMessage dispatch loop quit"); 184 break; 185 } 186 187 match m.unwrap() { 188 APIMessage::IsReady(api) => match api { 189 BluetoothAPI::Adapter => { 190 cr.lock().unwrap().insert( 191 Self::make_object_name(virt_index, "adapter"), 192 &[adapter_iface, qa_legacy_iface, socket_mgr_iface, suspend_iface], 193 mixin.clone(), 194 ); 195 196 cr.lock().unwrap().insert( 197 Self::make_object_name(virt_index, "logging"), 198 &[logging_iface], 199 logging.clone(), 200 ); 201 202 cr.lock().unwrap().insert( 203 Self::make_object_name(virt_index, "qa"), 204 &[qa_iface], 205 bluetooth_qa.clone(), 206 ); 207 } 208 BluetoothAPI::Admin => { 209 cr.lock().unwrap().insert( 210 Self::make_object_name(virt_index, "admin"), 211 &[admin_iface], 212 bluetooth_admin.clone(), 213 ); 214 } 215 BluetoothAPI::Gatt => { 216 cr.lock().unwrap().insert( 217 Self::make_object_name(virt_index, "gatt"), 218 &[gatt_iface], 219 bluetooth_gatt.clone(), 220 ); 221 } 222 BluetoothAPI::Media => { 223 cr.lock().unwrap().insert( 224 Self::make_object_name(virt_index, "media"), 225 &[media_iface], 226 bluetooth_media.clone(), 227 ); 228 229 cr.lock().unwrap().insert( 230 Self::make_object_name(virt_index, "telephony"), 231 &[telephony_iface], 232 bluetooth_media.clone(), 233 ); 234 } 235 BluetoothAPI::Battery => { 236 cr.lock().unwrap().insert( 237 Self::make_object_name(virt_index, "battery_provider_manager"), 238 &[battery_provider_manager_iface], 239 battery_provider_manager.clone(), 240 ); 241 242 cr.lock().unwrap().insert( 243 Self::make_object_name(virt_index, "battery_manager"), 244 &[battery_manager_iface], 245 battery_manager.clone(), 246 ); 247 } 248 }, 249 250 APIMessage::ShutDown => { 251 // To shut down the connection, call _handle.abort() and drop the connection. 252 conn_join_handle.abort(); 253 drop(conn); 254 *sig_notifier.api_enabled.lock().unwrap() = false; 255 sig_notifier.api_notify.notify_all(); 256 break; 257 } 258 } 259 } 260 } 261 } 262