• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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