1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
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!()
})
}
|