1 //! Bluetooth interface shim
2 //!
3 //! This is a shim interface for calling the C++ bluetooth interface via Rust.
4 //!
5
6 // TODO(abps): Remove this once callbacks are implemented
7 #![allow(unused_variables)]
8
9 use num_traits::FromPrimitive;
10 use std::sync::Arc;
11 use std::vec::Vec;
12
13 #[derive(FromPrimitive, ToPrimitive, PartialEq, PartialOrd)]
14 #[repr(i32)]
15 pub enum BtState {
16 Off = 0,
17 On,
18 }
19
20 #[derive(FromPrimitive, ToPrimitive, PartialEq, PartialOrd, Debug)]
21 #[repr(i32)]
22 pub enum BtPropertyType {
23 BdName = 0x1,
24 BdAddr,
25 Uuids,
26 ClassOfDevice,
27 TypeOfDevice,
28 ServiceRecord,
29 AdapterScanMode,
30 AdapterBondedDevices,
31 AdapterDiscoveryTimeout,
32 RemoteFriendlyName,
33 RemoteRssi,
34 RemoteVersionInfo,
35 LocalLeFeatures,
36 LocalIoCaps,
37 LocalIoCapsBle,
38 DynamicAudioBuffer,
39
40 Unknown = 0xFE,
41 RemoteDeviceTimestamp = 0xFF,
42 }
43
44 #[derive(FromPrimitive, ToPrimitive, PartialEq, PartialOrd)]
45 #[repr(i32)]
46 pub enum BtDiscoveryState {
47 Stopped = 0x0,
48 Started,
49 }
50
51 #[derive(FromPrimitive, ToPrimitive, PartialEq, PartialOrd)]
52 #[repr(i32)]
53 pub enum BtStatus {
54 Success = 0,
55 Fail,
56 NotReady,
57 NoMemory,
58 Busy,
59 Done,
60 Unsupported,
61 InvalidParam,
62 Unhandled,
63 AuthFailure,
64 RemoteDeviceDown,
65 AuthRejected,
66 JniEnvironmentError,
67 JniThreadAttachError,
68 WakeLockError,
69
70 // Any statuses that couldn't be cleanly converted
71 Unknown = 0xff,
72 }
73
74 // FFI is a public module because we want Rust and C++ to share enums listed
75 // here. We redefine most of the Bluetooth structures we want to use because
76 // of memory management issues (for example, some api calls will free the
77 // memory passed into it). Bindgen was attempted but ultimately was not useful.
78 #[cxx::bridge(namespace = bluetooth::topshim::rust)]
79 pub mod ffi {
80
81 pub struct BtPinCode {
82 pin: [u8; 16],
83 }
84
85 pub struct BtProperty {
86 prop_type: i32,
87 len: i32,
88 val: Vec<u8>,
89 }
90
91 pub struct BtUuid {
92 uuid: [u8; 16],
93 }
94
95 pub struct RustRawAddress {
96 address: [u8; 6],
97 }
98
99 unsafe extern "C++" {
100 include!("btif/btif_shim.h");
101
102 // Opaque type meant to represent C object for the Bluetooth interface.
103 type BluetoothIntf;
104
105 // Loads a unique pointer to the underlying interface
Load() -> UniquePtr<BluetoothIntf>106 fn Load() -> UniquePtr<BluetoothIntf>;
107
Initialize( self: Pin<&mut Self>, callbacks: Box<RustCallbacks>, init_flags: Vec<String>, ) -> bool108 fn Initialize(
109 self: Pin<&mut Self>,
110 callbacks: Box<RustCallbacks>,
111 init_flags: Vec<String>,
112 ) -> bool;
113
CleanUp(&self)114 fn CleanUp(&self);
Enable(&self) -> i32115 fn Enable(&self) -> i32;
Disable(&self) -> i32116 fn Disable(&self) -> i32;
117
GetAdapterProperties(&self) -> i32118 fn GetAdapterProperties(&self) -> i32;
GetAdapterProperty(&self, prop_type: i32) -> i32119 fn GetAdapterProperty(&self, prop_type: i32) -> i32;
SetAdapterProperty(&self, prop: &BtProperty) -> i32120 fn SetAdapterProperty(&self, prop: &BtProperty) -> i32;
121
GetRemoteDeviceProperties(&self, address: &RustRawAddress) -> i32122 fn GetRemoteDeviceProperties(&self, address: &RustRawAddress) -> i32;
GetRemoteDeviceProperty(&self, address: &RustRawAddress, prop_type: i32) -> i32123 fn GetRemoteDeviceProperty(&self, address: &RustRawAddress, prop_type: i32) -> i32;
SetRemoteDeviceProperty(&self, address: &RustRawAddress, prop: &BtProperty) -> i32124 fn SetRemoteDeviceProperty(&self, address: &RustRawAddress, prop: &BtProperty) -> i32;
125
GetRemoteServices(&self, address: &RustRawAddress) -> i32126 fn GetRemoteServices(&self, address: &RustRawAddress) -> i32;
127
StartDiscovery(&self) -> i32128 fn StartDiscovery(&self) -> i32;
CancelDiscovery(&self) -> i32129 fn CancelDiscovery(&self) -> i32;
130
CreateBond(&self, address: &RustRawAddress, transport: i32) -> i32131 fn CreateBond(&self, address: &RustRawAddress, transport: i32) -> i32;
132 // TODO(abps): Implement at P3
133 // fn CreateBondOutOfBand(address: &RustRawAddress, transport: i32,
134 // oob_data: &BtOutOfBandData) -> i32;
RemoveBond(&self, address: &RustRawAddress) -> i32135 fn RemoveBond(&self, address: &RustRawAddress) -> i32;
CancelBond(&self, address: &RustRawAddress) -> i32136 fn CancelBond(&self, address: &RustRawAddress) -> i32;
137
GetConnectionState(&self, address: &RustRawAddress) -> i32138 fn GetConnectionState(&self, address: &RustRawAddress) -> i32;
139
PinReply( &self, address: &RustRawAddress, accept: u8, pin_len: u8, code: &BtPinCode, ) -> i32140 fn PinReply(
141 &self,
142 address: &RustRawAddress,
143 accept: u8,
144 pin_len: u8,
145 code: &BtPinCode,
146 ) -> i32;
SspReply( &self, address: &RustRawAddress, ssp_variant: i32, accept: u8, passkey: u32, ) -> i32147 fn SspReply(
148 &self,
149 address: &RustRawAddress,
150 ssp_variant: i32,
151 accept: u8,
152 passkey: u32,
153 ) -> i32;
154
155 // TODO(abps): Implement at P1
156 // fn GetProfileInterface(profile_id: &str) -> Option<BtProfileInterface>;
157
158 // TODO(abps): Implement at P2
159 // fn dut_mode_configure(enable: u8) -> i32;
160 // fn dut_mode_send(opcode: u16, buf: [u8], len: u8) -> i32;
161 // fn le_test_mode(opcode: u16, buf: [u8], len: u8) -> i32;
162
163 // TODO(abps): Implement at P1
164 // fn SetOsCallouts(callouts: Box<RustOsCallouts>) -> i32;
165
166 // TODO(abps): Implement at P3
167 // fn ReadEnergyInfo(&self) -> i32;
168 // fn Dump(fd: i32, args: &[str]);
169 // fn DumpMetrics() -> String;
170 // fn ConfigClear(&self) -> i32;
171 // fn InteropDatabaseClear(&self);
172 // fn InteropDatabaseAdd(&self, feature: u16, address: &RustRawAddress, match_len: u8);
173
174 // TODO(abps): Implement at P1
175 // fn GetAvrcpService() -> *mut AvrcpServiceInterface;
176
177 // TODO(abps): Implement at P3
178 // fn ObfuscateAddress(&self, address: &RustRawAddress) -> String;
179 // fn GetMetricId(&self, address: &RustRawAddress) -> i32;
180 // fn SetDynamicAudioBufferSize(&self, codec: i32, size: i32) -> i32;
181 }
182
183 extern "Rust" {
184 type RustCallbacks;
185
186 // Callbacks from C++ to Rust. The rust callbacks are stored when the
187 // `BluetoothIntf` is initialized and consist of closures that take the
188 // same parameters (without the first callbacks param).
189
adapter_state_changed_callback(cb: &RustCallbacks, state: i32)190 fn adapter_state_changed_callback(cb: &RustCallbacks, state: i32);
adapter_properties_callback( cb: &RustCallbacks, status: i32, num_properties: i32, properties: Vec<BtProperty>, )191 fn adapter_properties_callback(
192 cb: &RustCallbacks,
193 status: i32,
194 num_properties: i32,
195 properties: Vec<BtProperty>,
196 );
remote_device_properties_callback( cb: &RustCallbacks, status: i32, address: RustRawAddress, num_properties: i32, properties: Vec<BtProperty>, )197 fn remote_device_properties_callback(
198 cb: &RustCallbacks,
199 status: i32,
200 address: RustRawAddress,
201 num_properties: i32,
202 properties: Vec<BtProperty>,
203 );
device_found_callback( cb: &RustCallbacks, num_properties: i32, properties: Vec<BtProperty>, )204 fn device_found_callback(
205 cb: &RustCallbacks,
206 num_properties: i32,
207 properties: Vec<BtProperty>,
208 );
discovery_state_changed_callback(cb: &RustCallbacks, state: i32)209 fn discovery_state_changed_callback(cb: &RustCallbacks, state: i32);
pin_request_callback( cb: &RustCallbacks, remote_addr: RustRawAddress, bd_name: String, cod: u32, min_16_digit: bool, )210 fn pin_request_callback(
211 cb: &RustCallbacks,
212 remote_addr: RustRawAddress,
213 bd_name: String,
214 cod: u32,
215 min_16_digit: bool,
216 );
ssp_request_callback( cb: &RustCallbacks, remote_addr: RustRawAddress, bd_name: String, cod: u32, variant: i32, pass_key: u32, )217 fn ssp_request_callback(
218 cb: &RustCallbacks,
219 remote_addr: RustRawAddress,
220 bd_name: String,
221 cod: u32,
222 variant: i32,
223 pass_key: u32,
224 );
bond_state_changed_callback( cb: &RustCallbacks, status: i32, remote_addr: RustRawAddress, state: i32, )225 fn bond_state_changed_callback(
226 cb: &RustCallbacks,
227 status: i32,
228 remote_addr: RustRawAddress,
229 state: i32,
230 );
acl_state_changed_callback( cb: &RustCallbacks, status: i32, remote_addr: RustRawAddress, state: i32, hci_reason: i32, )231 fn acl_state_changed_callback(
232 cb: &RustCallbacks,
233 status: i32,
234 remote_addr: RustRawAddress,
235 state: i32,
236 hci_reason: i32,
237 );
238
239 }
240
241 unsafe impl Box<RustCallbacks> {}
242 }
243
244 /// Rust struct of closures for all callbacks from C++.
245 ///
246 /// Note: Due to the need to interop with the C interface, we cannot pass
247 /// additional state from C++ when calling these callbacks. Capture any
248 /// state you need in the closure provided to this struct.
249 pub struct BluetoothCallbacks {
250 pub adapter_state_changed: Box<dyn Fn(BtState) + Send>,
251 pub adapter_properties_changed: Box<dyn Fn(i32, i32, Vec<ffi::BtProperty>) + Send>,
252 pub remote_device_properties_changed:
253 Box<dyn Fn(i32, ffi::RustRawAddress, i32, Vec<ffi::BtProperty>) + Send>,
254 pub device_found: Box<dyn Fn(i32, Vec<ffi::BtProperty>) + Send>,
255 pub discovery_state_changed: Box<dyn Fn(BtDiscoveryState) + Send>,
256 pub pin_request: Box<dyn Fn(ffi::RustRawAddress, String, u32, bool) + Send>,
257 pub ssp_request: Box<dyn Fn(ffi::RustRawAddress, String, u32, i32, u32) + Send>,
258 pub bond_state_changed: Box<dyn Fn(i32, ffi::RustRawAddress, i32) + Send>,
259 pub acl_state_changed: Box<dyn Fn(i32, ffi::RustRawAddress, i32, i32) + Send>,
260 }
261
262 pub struct RustCallbacks {
263 inner: Arc<BluetoothCallbacks>,
264 }
265
266 /// Rust interface to native Bluetooth.
267 pub struct BluetoothInterface {
268 internal: cxx::UniquePtr<ffi::BluetoothIntf>,
269 }
270
271 impl BluetoothInterface {
new() -> BluetoothInterface272 pub fn new() -> BluetoothInterface {
273 BluetoothInterface { internal: ffi::Load() }
274 }
275
276 /// Initialize the BluetoothInterface shim (not strictly necessary as
277 /// Load also initializes the interface).
initialize( &mut self, callbacks: Arc<BluetoothCallbacks>, init_flags: Vec<String>, ) -> bool278 pub fn initialize(
279 &mut self,
280 callbacks: Arc<BluetoothCallbacks>,
281 init_flags: Vec<String>,
282 ) -> bool {
283 //ffi::Initialize(*self.internal)
284 self.internal
285 .pin_mut()
286 .Initialize(Box::new(RustCallbacks { inner: callbacks.clone() }), init_flags)
287 }
288
289 /// Enable the Bluetooth adapter. This triggers an adapter_state_changed callback.
enable(&mut self) -> i32290 pub fn enable(&mut self) -> i32 {
291 self.internal.Enable()
292 }
293
294 /// Disable the Bluetooth adapter. This triggers an adapter state changed callback.
disable(&mut self) -> i32295 pub fn disable(&mut self) -> i32 {
296 self.internal.Disable()
297 }
298
cleanup(&mut self)299 pub fn cleanup(&mut self) {
300 self.internal.CleanUp()
301 }
302
get_adapter_properties(&mut self) -> i32303 pub fn get_adapter_properties(&mut self) -> i32 {
304 self.internal.GetAdapterProperties()
305 }
306
get_adapter_property(&mut self, prop_type: i32) -> i32307 pub fn get_adapter_property(&mut self, prop_type: i32) -> i32 {
308 self.internal.GetAdapterProperty(prop_type)
309 }
310
set_adapter_property(&mut self, prop: &ffi::BtProperty) -> i32311 pub fn set_adapter_property(&mut self, prop: &ffi::BtProperty) -> i32 {
312 self.internal.SetAdapterProperty(prop)
313 }
314
315 //fn GetRemoteDeviceProperties(&self, address: &RustRawAddress) -> i32;
316 //fn GetRemoteDeviceProperty(&self, address: &RustRawAddress, prop_type: i32) -> i32;
317 //fn SetRemoteDeviceProperty(&self, address: &RustRawAddress, prop: &BtProperty) -> i32;
318 //fn GetRemoteServices(&self, address: &RustRawAddress) -> i32;
319
start_discovery(&mut self) -> i32320 pub fn start_discovery(&mut self) -> i32 {
321 self.internal.StartDiscovery()
322 }
cancel_discovery(&mut self) -> i32323 pub fn cancel_discovery(&mut self) -> i32 {
324 self.internal.CancelDiscovery()
325 }
326
create_bond(&mut self, address: &ffi::RustRawAddress, transport: i32) -> i32327 pub fn create_bond(&mut self, address: &ffi::RustRawAddress, transport: i32) -> i32 {
328 self.internal.CreateBond(address, transport)
329 }
remove_bond(&mut self, address: &ffi::RustRawAddress) -> i32330 pub fn remove_bond(&mut self, address: &ffi::RustRawAddress) -> i32 {
331 self.internal.RemoveBond(address)
332 }
cancel_bond(&mut self, address: &ffi::RustRawAddress) -> i32333 pub fn cancel_bond(&mut self, address: &ffi::RustRawAddress) -> i32 {
334 self.internal.CancelBond(address)
335 }
336
get_connection_state(&mut self, address: &ffi::RustRawAddress) -> i32337 pub fn get_connection_state(&mut self, address: &ffi::RustRawAddress) -> i32 {
338 self.internal.GetConnectionState(address)
339 }
340 }
341
342 unsafe impl Send for BluetoothInterface {}
343
adapter_state_changed_callback(cb: &RustCallbacks, state: i32)344 fn adapter_state_changed_callback(cb: &RustCallbacks, state: i32) {
345 let new_state = match BtState::from_i32(state) {
346 Some(x) => x,
347 None => BtState::Off,
348 };
349 (cb.inner.adapter_state_changed)(new_state);
350 }
351
adapter_properties_callback( cb: &RustCallbacks, status: i32, num_properties: i32, properties: Vec<ffi::BtProperty>, )352 fn adapter_properties_callback(
353 cb: &RustCallbacks,
354 status: i32,
355 num_properties: i32,
356 properties: Vec<ffi::BtProperty>,
357 ) {
358 (cb.inner.adapter_properties_changed)(status, num_properties, properties);
359 }
360
remote_device_properties_callback( cb: &RustCallbacks, status: i32, address: ffi::RustRawAddress, num_properties: i32, properties: Vec<ffi::BtProperty>, )361 fn remote_device_properties_callback(
362 cb: &RustCallbacks,
363 status: i32,
364 address: ffi::RustRawAddress,
365 num_properties: i32,
366 properties: Vec<ffi::BtProperty>,
367 ) {
368 (cb.inner.remote_device_properties_changed)(status, address, num_properties, properties);
369 }
370
device_found_callback( cb: &RustCallbacks, num_properties: i32, properties: Vec<ffi::BtProperty>, )371 fn device_found_callback(
372 cb: &RustCallbacks,
373 num_properties: i32,
374 properties: Vec<ffi::BtProperty>,
375 ) {
376 (cb.inner.device_found)(num_properties, properties);
377 }
discovery_state_changed_callback(cb: &RustCallbacks, state: i32)378 fn discovery_state_changed_callback(cb: &RustCallbacks, state: i32) {
379 let new_state = match BtDiscoveryState::from_i32(state) {
380 Some(x) => x,
381 None => BtDiscoveryState::Stopped,
382 };
383 (cb.inner.discovery_state_changed)(new_state);
384 }
pin_request_callback( cb: &RustCallbacks, remote_addr: ffi::RustRawAddress, bd_name: String, cod: u32, min_16_digit: bool, )385 fn pin_request_callback(
386 cb: &RustCallbacks,
387 remote_addr: ffi::RustRawAddress,
388 bd_name: String,
389 cod: u32,
390 min_16_digit: bool,
391 ) {
392 (cb.inner.pin_request)(remote_addr, bd_name, cod, min_16_digit);
393 }
ssp_request_callback( cb: &RustCallbacks, remote_addr: ffi::RustRawAddress, bd_name: String, cod: u32, variant: i32, pass_key: u32, )394 fn ssp_request_callback(
395 cb: &RustCallbacks,
396 remote_addr: ffi::RustRawAddress,
397 bd_name: String,
398 cod: u32,
399 variant: i32,
400 pass_key: u32,
401 ) {
402 (cb.inner.ssp_request)(remote_addr, bd_name, cod, variant, pass_key);
403 }
bond_state_changed_callback( cb: &RustCallbacks, status: i32, remote_addr: ffi::RustRawAddress, state: i32, )404 fn bond_state_changed_callback(
405 cb: &RustCallbacks,
406 status: i32,
407 remote_addr: ffi::RustRawAddress,
408 state: i32,
409 ) {
410 (cb.inner.bond_state_changed)(status, remote_addr, state);
411 }
acl_state_changed_callback( cb: &RustCallbacks, status: i32, remote_addr: ffi::RustRawAddress, state: i32, hci_reason: i32, )412 fn acl_state_changed_callback(
413 cb: &RustCallbacks,
414 status: i32,
415 remote_addr: ffi::RustRawAddress,
416 state: i32,
417 hci_reason: i32,
418 ) {
419 (cb.inner.acl_state_changed)(status, remote_addr, state, hci_reason);
420 }
421