diff options
Diffstat (limited to 'gd/rust/linux/service/src/main.rs')
-rw-r--r-- | gd/rust/linux/service/src/main.rs | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/gd/rust/linux/service/src/main.rs b/gd/rust/linux/service/src/main.rs new file mode 100644 index 000000000..755c61107 --- /dev/null +++ b/gd/rust/linux/service/src/main.rs @@ -0,0 +1,100 @@ +use bt_topshim::btif::BluetoothInterface; +use bt_topshim::topstack; + +use dbus::channel::MatchingReceiver; +use dbus::message::MatchRule; + +use dbus_crossroads::Crossroads; + +use dbus_projection::DisconnectWatcher; + +use dbus_tokio::connection; + +use futures::future; + +use btstack::bluetooth::btif_bluetooth_callbacks; +use btstack::bluetooth::Bluetooth; +use btstack::bluetooth_gatt::BluetoothGatt; +use btstack::Stack; + +use std::error::Error; +use std::sync::{Arc, Mutex}; + +mod dbus_arg; +mod iface_bluetooth; +mod iface_bluetooth_gatt; + +const DBUS_SERVICE_NAME: &str = "org.chromium.bluetooth"; +const OBJECT_BLUETOOTH: &str = "/org/chromium/bluetooth/adapter"; +const OBJECT_BLUETOOTH_GATT: &str = "/org/chromium/bluetooth/gatt"; + +/// Runs the Bluetooth daemon serving D-Bus IPC. +fn main() -> Result<(), Box<dyn Error>> { + let (tx, rx) = Stack::create_channel(); + + let intf = Arc::new(Mutex::new(BluetoothInterface::new())); + let bluetooth = Arc::new(Mutex::new(Bluetooth::new(tx.clone(), intf.clone()))); + let bluetooth_gatt = Arc::new(Mutex::new(BluetoothGatt::new(intf.clone()))); + + topstack::get_runtime().block_on(async { + // Connect to D-Bus system bus. + let (resource, conn) = connection::new_system_sync()?; + + // The `resource` is a task that should be spawned onto a tokio compatible + // reactor ASAP. If the resource ever finishes, we lost connection to D-Bus. + topstack::get_runtime().spawn(async { + let err = resource.await; + panic!("Lost connection to D-Bus: {}", err); + }); + + // Request a service name and quit if not able to. + conn.request_name(DBUS_SERVICE_NAME, false, true, false).await?; + + // Prepare D-Bus interfaces. + let mut cr = Crossroads::new(); + cr.set_async_support(Some(( + conn.clone(), + Box::new(|x| { + topstack::get_runtime().spawn(x); + }), + ))); + + intf.lock().unwrap().initialize(Arc::new(btif_bluetooth_callbacks(tx)), vec![]); + + // Run the stack main dispatch loop. + topstack::get_runtime().spawn(Stack::dispatch(rx, bluetooth.clone())); + + // Set up the disconnect watcher to monitor client disconnects. + let disconnect_watcher = Arc::new(Mutex::new(DisconnectWatcher::new())); + disconnect_watcher.lock().unwrap().setup_watch(conn.clone()).await; + + // Register D-Bus method handlers of IBluetooth. + iface_bluetooth::export_bluetooth_dbus_obj( + OBJECT_BLUETOOTH, + conn.clone(), + &mut cr, + bluetooth, + disconnect_watcher.clone(), + ); + // Register D-Bus method handlers of IBluetoothGatt. + iface_bluetooth_gatt::export_bluetooth_gatt_dbus_obj( + OBJECT_BLUETOOTH_GATT, + conn.clone(), + &mut cr, + bluetooth_gatt, + disconnect_watcher.clone(), + ); + + conn.start_receive( + MatchRule::new_method_call(), + Box::new(move |msg, conn| { + cr.handle_message(msg, conn).unwrap(); + true + }), + ); + + // Serve clients forever. + future::pending::<()>().await; + unreachable!() + }) +} |