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