1 //! Shim for `bt_interface_t`, providing access to libbluetooth.
2 //!
3 //! This is a shim interface for calling the C++ bluetooth interface via Rust.
4
5 use crate::bindings::root as bindings;
6 use crate::topstack::get_dispatchers;
7 use crate::utils::{LTCheckedPtr, LTCheckedPtrMut};
8 use num_derive::{FromPrimitive, ToPrimitive};
9 use num_traits::cast::{FromPrimitive, ToPrimitive};
10 use std::cmp;
11 use std::convert::TryFrom;
12 use std::fmt::{Debug, Display, Formatter, Result};
13 use std::hash::{Hash, Hasher};
14 use std::mem;
15 use std::os::raw::c_char;
16 use std::sync::{Arc, Mutex};
17 use std::vec::Vec;
18 use topshim_macros::cb_variant;
19
20 use cxx::{type_id, ExternType};
21
22 #[derive(Clone, Debug, FromPrimitive, ToPrimitive, PartialEq, PartialOrd)]
23 #[repr(u32)]
24 pub enum BtState {
25 Off = 0,
26 On,
27 }
28
29 impl From<bindings::bt_state_t> for BtState {
from(item: bindings::bt_state_t) -> Self30 fn from(item: bindings::bt_state_t) -> Self {
31 BtState::from_u32(item).unwrap_or(BtState::Off)
32 }
33 }
34
35 #[derive(Clone, Debug, FromPrimitive, ToPrimitive, PartialEq, PartialOrd, Copy)]
36 #[repr(u32)]
37 pub enum BtTransport {
38 Auto = 0,
39 Bredr,
40 Le,
41 }
42
43 impl From<i32> for BtTransport {
from(item: i32) -> Self44 fn from(item: i32) -> Self {
45 BtTransport::from_i32(item).unwrap_or(BtTransport::Auto)
46 }
47 }
48
49 impl From<BtTransport> for i32 {
from(item: BtTransport) -> Self50 fn from(item: BtTransport) -> Self {
51 item.to_i32().unwrap_or(0)
52 }
53 }
54
55 #[derive(Clone, Debug, FromPrimitive, ToPrimitive, PartialEq, PartialOrd)]
56 #[repr(u32)]
57 pub enum BtSspVariant {
58 PasskeyConfirmation = 0,
59 PasskeyEntry,
60 Consent,
61 PasskeyNotification,
62 }
63
64 impl From<bindings::bt_ssp_variant_t> for BtSspVariant {
from(item: bindings::bt_ssp_variant_t) -> Self65 fn from(item: bindings::bt_ssp_variant_t) -> Self {
66 BtSspVariant::from_u32(item).unwrap_or(BtSspVariant::PasskeyConfirmation)
67 }
68 }
69
70 impl From<BtSspVariant> for bindings::bt_ssp_variant_t {
from(item: BtSspVariant) -> Self71 fn from(item: BtSspVariant) -> Self {
72 item.to_u32().unwrap_or(0)
73 }
74 }
75
76 #[derive(Clone, Debug, FromPrimitive, ToPrimitive, PartialEq, PartialOrd)]
77 #[repr(u32)]
78 pub enum BtBondState {
79 NotBonded = 0,
80 Bonding,
81 Bonded,
82 }
83
84 impl From<bindings::bt_bond_state_t> for BtBondState {
from(item: bindings::bt_bond_state_t) -> Self85 fn from(item: bindings::bt_bond_state_t) -> Self {
86 BtBondState::from_u32(item).unwrap_or(BtBondState::NotBonded)
87 }
88 }
89
90 #[derive(Clone, Debug, FromPrimitive, ToPrimitive, PartialEq, PartialOrd)]
91 #[repr(u32)]
92 pub enum BtConnectionState {
93 NotConnected = 0,
94 ConnectedOnly = 1,
95 EncryptedBredr = 3,
96 EncryptedLe = 5,
97 EncryptedBoth = 7,
98 }
99
100 impl From<i32> for BtConnectionState {
from(item: i32) -> Self101 fn from(item: i32) -> Self {
102 let fallback = if item > 0 {
103 BtConnectionState::ConnectedOnly
104 } else {
105 BtConnectionState::NotConnected
106 };
107
108 BtConnectionState::from_i32(item).unwrap_or(fallback)
109 }
110 }
111
112 #[derive(Clone, Debug, FromPrimitive, ToPrimitive, PartialEq, PartialOrd)]
113 #[repr(u32)]
114 pub enum BtAclState {
115 Connected = 0,
116 Disconnected,
117 }
118
119 impl From<bindings::bt_acl_state_t> for BtAclState {
from(item: bindings::bt_acl_state_t) -> Self120 fn from(item: bindings::bt_acl_state_t) -> Self {
121 BtAclState::from_u32(item).unwrap_or(BtAclState::Disconnected)
122 }
123 }
124
125 #[derive(Clone, Debug, FromPrimitive, ToPrimitive, PartialEq, PartialOrd)]
126 #[repr(u32)]
127 pub enum BtDeviceType {
128 Unknown = 0,
129 Bredr,
130 Ble,
131 Dual,
132 }
133
134 #[derive(Clone, Debug, Eq, Hash, FromPrimitive, ToPrimitive, PartialEq, PartialOrd)]
135 #[repr(u32)]
136 pub enum BtPropertyType {
137 BdName = 0x1,
138 BdAddr,
139 Uuids,
140 ClassOfDevice,
141 TypeOfDevice,
142 ServiceRecord,
143 AdapterScanMode,
144 AdapterBondedDevices,
145 AdapterDiscoverableTimeout,
146 RemoteFriendlyName,
147 RemoteRssi,
148 RemoteVersionInfo,
149 LocalLeFeatures,
150 LocalIoCaps,
151 LocalIoCapsBle,
152 DynamicAudioBuffer,
153 RemoteIsCoordinatedSetMember,
154 Appearance,
155 VendorProductInfo,
156
157 Unknown = 0xFE,
158 RemoteDeviceTimestamp = 0xFF,
159 }
160
161 impl From<u32> for BtPropertyType {
from(item: u32) -> Self162 fn from(item: u32) -> Self {
163 BtPropertyType::from_u32(item).unwrap_or(BtPropertyType::Unknown)
164 }
165 }
166
167 impl From<BtPropertyType> for u32 {
from(item: BtPropertyType) -> Self168 fn from(item: BtPropertyType) -> Self {
169 item.to_u32().unwrap_or(0)
170 }
171 }
172
173 #[derive(Clone, Debug, FromPrimitive, ToPrimitive, PartialEq, PartialOrd)]
174 #[repr(u32)]
175 pub enum BtDiscoveryState {
176 Stopped = 0x0,
177 Started,
178 }
179
180 impl From<u32> for BtDiscoveryState {
from(item: u32) -> Self181 fn from(item: u32) -> Self {
182 BtDiscoveryState::from_u32(item).unwrap_or(BtDiscoveryState::Stopped)
183 }
184 }
185
186 #[derive(Clone, Copy, Debug, FromPrimitive, ToPrimitive, PartialEq, PartialOrd)]
187 #[repr(u32)]
188 pub enum BtStatus {
189 Success = 0,
190 Fail,
191 NotReady,
192 NoMemory,
193 Busy,
194 Done,
195 Unsupported,
196 InvalidParam,
197 Unhandled,
198 AuthFailure,
199 RemoteDeviceDown,
200 AuthRejected,
201 JniEnvironmentError,
202 JniThreadAttachError,
203 WakeLockError,
204
205 // Any statuses that couldn't be cleanly converted
206 Unknown = 0xff,
207 }
208
209 #[derive(Clone, Debug, FromPrimitive, ToPrimitive, PartialEq, PartialOrd)]
210 #[repr(u32)]
211 pub enum BtConnectionDirection {
212 Unknown = 0,
213 Outgoing,
214 Incoming,
215 }
216
217 impl From<u32> for BtConnectionDirection {
from(item: u32) -> Self218 fn from(item: u32) -> Self {
219 BtConnectionDirection::from_u32(item).unwrap_or(BtConnectionDirection::Unknown)
220 }
221 }
222
ascii_to_string(data: &[u8], length: usize) -> String223 pub fn ascii_to_string(data: &[u8], length: usize) -> String {
224 // We need to reslice data because from_utf8 tries to interpret the
225 // whole slice and not just what is before the null terminated portion
226 let ascii = data
227 .iter()
228 .enumerate()
229 .take_while(|&(pos, &c)| c != 0 && pos < length)
230 .map(|(_pos, &x)| x.clone())
231 .collect::<Vec<u8>>();
232
233 return String::from_utf8(ascii).unwrap_or_default();
234 }
235
u32_from_bytes(item: &[u8]) -> u32236 fn u32_from_bytes(item: &[u8]) -> u32 {
237 let mut u: [u8; 4] = [0; 4];
238 let len = std::cmp::min(item.len(), 4);
239 u[0..len].copy_from_slice(&item);
240 u32::from_ne_bytes(u)
241 }
242
u16_from_bytes(item: &[u8]) -> u16243 fn u16_from_bytes(item: &[u8]) -> u16 {
244 let mut u: [u8; 2] = [0; 2];
245 let len = std::cmp::min(item.len(), 2);
246 u[0..len].copy_from_slice(&item);
247 u16::from_ne_bytes(u)
248 }
249
250 impl From<bindings::bt_status_t> for BtStatus {
from(item: bindings::bt_status_t) -> Self251 fn from(item: bindings::bt_status_t) -> Self {
252 match BtStatus::from_u32(item) {
253 Some(x) => x,
254 _ => BtStatus::Unknown,
255 }
256 }
257 }
258
259 impl Into<u32> for BtStatus {
into(self) -> u32260 fn into(self) -> u32 {
261 self.to_u32().unwrap_or_default()
262 }
263 }
264
265 impl Into<i32> for BtStatus {
into(self) -> i32266 fn into(self) -> i32 {
267 self.to_i32().unwrap_or_default()
268 }
269 }
270
271 impl From<bindings::bt_bdname_t> for String {
from(item: bindings::bt_bdname_t) -> Self272 fn from(item: bindings::bt_bdname_t) -> Self {
273 ascii_to_string(&item.name, item.name.len())
274 }
275 }
276
277 #[derive(Debug, Clone)]
278 pub struct BtServiceRecord {
279 pub uuid: bindings::bluetooth::Uuid,
280 pub channel: u16,
281 pub name: String,
282 }
283
284 impl From<bindings::bt_service_record_t> for BtServiceRecord {
from(item: bindings::bt_service_record_t) -> Self285 fn from(item: bindings::bt_service_record_t) -> Self {
286 let name = item.name.iter().map(|&x| x.clone() as u8).collect::<Vec<u8>>();
287
288 BtServiceRecord {
289 uuid: item.uuid,
290 channel: item.channel,
291 name: ascii_to_string(name.as_slice(), name.len()),
292 }
293 }
294 }
295
296 #[derive(Clone, Debug, FromPrimitive, ToPrimitive, PartialEq, PartialOrd)]
297 #[repr(u32)]
298 pub enum BtScanMode {
299 None_,
300 Connectable,
301 ConnectableDiscoverable,
302 ConnectableLimitedDiscoverable,
303 }
304
305 impl From<bindings::bt_scan_mode_t> for BtScanMode {
from(item: bindings::bt_scan_mode_t) -> Self306 fn from(item: bindings::bt_scan_mode_t) -> Self {
307 BtScanMode::from_u32(item).unwrap_or(BtScanMode::None_)
308 }
309 }
310
311 #[derive(Clone, Debug, FromPrimitive, ToPrimitive, PartialEq, PartialOrd)]
312 #[repr(u32)]
313 pub enum BtDiscMode {
314 // reference to system/stack/btm/neighbor_inquiry.h
315 NonDiscoverable = 0,
316 LimitedDiscoverable = 1,
317 GeneralDiscoverable = 2,
318 }
319
320 impl From<u32> for BtDiscMode {
from(num: u32) -> Self321 fn from(num: u32) -> Self {
322 BtDiscMode::from_u32(num).unwrap_or(BtDiscMode::NonDiscoverable)
323 }
324 }
325
326 impl Into<u32> for BtDiscMode {
into(self) -> u32327 fn into(self) -> u32 {
328 self.to_u32().unwrap_or(0)
329 }
330 }
331
332 #[derive(Clone, Debug, FromPrimitive, ToPrimitive, PartialEq, PartialOrd)]
333 #[repr(u32)]
334 pub enum BtIoCap {
335 Out,
336 InOut,
337 In,
338 None_,
339 KbDisp,
340 Max,
341 Unknown = 0xff,
342 }
343
344 impl From<bindings::bt_io_cap_t> for BtIoCap {
from(item: bindings::bt_io_cap_t) -> Self345 fn from(item: bindings::bt_io_cap_t) -> Self {
346 BtIoCap::from_u32(item).unwrap_or(BtIoCap::Unknown)
347 }
348 }
349
350 pub type BtHciErrorCode = u8;
351 pub type BtLocalLeFeatures = bindings::bt_local_le_features_t;
352 pub type BtPinCode = bindings::bt_pin_code_t;
353 pub type BtRemoteVersion = bindings::bt_remote_version_t;
354 pub type BtVendorProductInfo = bindings::bt_vendor_product_info_t;
355 pub type Uuid = bindings::bluetooth::Uuid;
356 pub type Uuid128Bit = bindings::bluetooth::Uuid_UUID128Bit;
357
358 impl TryFrom<Uuid> for Vec<u8> {
359 type Error = &'static str;
360
try_from(value: Uuid) -> std::result::Result<Self, Self::Error>361 fn try_from(value: Uuid) -> std::result::Result<Self, Self::Error> {
362 Ok((&value.uu).to_vec())
363 }
364 }
365
366 impl TryFrom<Vec<u8>> for Uuid {
367 type Error = &'static str;
368
try_from(value: Vec<u8>) -> std::result::Result<Self, Self::Error>369 fn try_from(value: Vec<u8>) -> std::result::Result<Self, Self::Error> {
370 // base UUID defined in the Bluetooth specification
371 let mut uu: [u8; 16] =
372 [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x80, 0x0, 0x0, 0x80, 0x5f, 0x9b, 0x34, 0xfb];
373 match value.len() {
374 2 => {
375 uu[2..4].copy_from_slice(&value[0..2]);
376 Ok(Uuid::from(uu))
377 }
378 4 => {
379 uu[0..4].copy_from_slice(&value[0..4]);
380 Ok(Uuid::from(uu))
381 }
382 16 => {
383 uu.copy_from_slice(&value[0..16]);
384 Ok(Uuid::from(uu))
385 }
386 _ => {
387 Err("Vector size must be exactly 2 (16 bit UUID), 4 (32 bit UUID), or 16 (128 bit UUID).")
388 }
389 }
390 }
391 }
392
393 impl From<[u8; 16]> for Uuid {
from(value: [u8; 16]) -> Self394 fn from(value: [u8; 16]) -> Self {
395 Self { uu: value }
396 }
397 }
398
399 impl From<Uuid> for [u8; 16] {
from(uuid: Uuid) -> Self400 fn from(uuid: Uuid) -> Self {
401 uuid.uu
402 }
403 }
404
405 impl Hash for Uuid {
hash<H: Hasher>(&self, state: &mut H)406 fn hash<H: Hasher>(&self, state: &mut H) {
407 self.uu.hash(state);
408 }
409 }
410
411 impl Uuid {
412 /// Creates a Uuid from little endian slice of bytes
try_from_little_endian(value: &[u8]) -> std::result::Result<Uuid, &'static str>413 pub fn try_from_little_endian(value: &[u8]) -> std::result::Result<Uuid, &'static str> {
414 Uuid::try_from(value.iter().rev().cloned().collect::<Vec<u8>>())
415 }
416
417 /// Formats this UUID to a human-readable representation.
format(uuid: &Uuid128Bit, f: &mut Formatter) -> Result418 pub fn format(uuid: &Uuid128Bit, f: &mut Formatter) -> Result {
419 write!(f, "{:02x}{:02x}{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}",
420 uuid[0], uuid[1], uuid[2], uuid[3],
421 uuid[4], uuid[5],
422 uuid[6], uuid[7],
423 uuid[8], uuid[9],
424 uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15])
425 }
426 }
427
428 impl Display for Uuid {
fmt(&self, f: &mut Formatter) -> Result429 fn fmt(&self, f: &mut Formatter) -> Result {
430 Uuid::format(&self.uu, f)
431 }
432 }
433
434 /// All supported Bluetooth properties after conversion.
435 #[derive(Debug, Clone)]
436 pub enum BluetoothProperty {
437 BdName(String),
438 BdAddr(RawAddress),
439 Uuids(Vec<Uuid>),
440 ClassOfDevice(u32),
441 TypeOfDevice(BtDeviceType),
442 ServiceRecord(BtServiceRecord),
443 AdapterScanMode(BtScanMode),
444 AdapterBondedDevices(Vec<RawAddress>),
445 AdapterDiscoverableTimeout(u32),
446 RemoteFriendlyName(String),
447 RemoteRssi(i8),
448 RemoteVersionInfo(BtRemoteVersion),
449 LocalLeFeatures(BtLocalLeFeatures),
450 LocalIoCaps(BtIoCap),
451 LocalIoCapsBle(BtIoCap),
452 DynamicAudioBuffer(),
453 RemoteIsCoordinatedSetMember(bool),
454 Appearance(u16),
455 VendorProductInfo(BtVendorProductInfo),
456 RemoteDeviceTimestamp(),
457
458 Unknown(),
459 }
460
461 /// Wherever names are sent in bindings::bt_property_t, the size of the character
462 /// arrays are 256. Keep one extra byte for null termination.
463 const PROPERTY_NAME_MAX: usize = 255;
464
465 impl BluetoothProperty {
get_type(&self) -> BtPropertyType466 pub fn get_type(&self) -> BtPropertyType {
467 match &*self {
468 BluetoothProperty::BdName(_) => BtPropertyType::BdName,
469 BluetoothProperty::BdAddr(_) => BtPropertyType::BdAddr,
470 BluetoothProperty::Uuids(_) => BtPropertyType::Uuids,
471 BluetoothProperty::ClassOfDevice(_) => BtPropertyType::ClassOfDevice,
472 BluetoothProperty::TypeOfDevice(_) => BtPropertyType::TypeOfDevice,
473 BluetoothProperty::ServiceRecord(_) => BtPropertyType::ServiceRecord,
474 BluetoothProperty::AdapterScanMode(_) => BtPropertyType::AdapterScanMode,
475 BluetoothProperty::AdapterBondedDevices(_) => BtPropertyType::AdapterBondedDevices,
476 BluetoothProperty::AdapterDiscoverableTimeout(_) => {
477 BtPropertyType::AdapterDiscoverableTimeout
478 }
479 BluetoothProperty::RemoteFriendlyName(_) => BtPropertyType::RemoteFriendlyName,
480 BluetoothProperty::RemoteRssi(_) => BtPropertyType::RemoteRssi,
481 BluetoothProperty::RemoteVersionInfo(_) => BtPropertyType::RemoteVersionInfo,
482 BluetoothProperty::LocalLeFeatures(_) => BtPropertyType::LocalLeFeatures,
483 BluetoothProperty::LocalIoCaps(_) => BtPropertyType::LocalIoCaps,
484 BluetoothProperty::LocalIoCapsBle(_) => BtPropertyType::LocalIoCapsBle,
485 BluetoothProperty::DynamicAudioBuffer() => BtPropertyType::DynamicAudioBuffer,
486 BluetoothProperty::RemoteIsCoordinatedSetMember(_) => {
487 BtPropertyType::RemoteIsCoordinatedSetMember
488 }
489 BluetoothProperty::Appearance(_) => BtPropertyType::Appearance,
490 BluetoothProperty::VendorProductInfo(_) => BtPropertyType::VendorProductInfo,
491 BluetoothProperty::RemoteDeviceTimestamp() => BtPropertyType::RemoteDeviceTimestamp,
492 BluetoothProperty::Unknown() => BtPropertyType::Unknown,
493 }
494 }
495
get_len(&self) -> usize496 fn get_len(&self) -> usize {
497 match &*self {
498 BluetoothProperty::BdName(name) => cmp::min(PROPERTY_NAME_MAX, name.len() + 1),
499 BluetoothProperty::BdAddr(addr) => addr.address.len(),
500 BluetoothProperty::Uuids(uulist) => uulist.len() * mem::size_of::<Uuid>(),
501 BluetoothProperty::ClassOfDevice(_) => mem::size_of::<u32>(),
502 BluetoothProperty::TypeOfDevice(_) => mem::size_of::<BtDeviceType>(),
503 BluetoothProperty::ServiceRecord(rec) => {
504 mem::size_of::<BtServiceRecord>() + cmp::min(PROPERTY_NAME_MAX, rec.name.len() + 1)
505 }
506 BluetoothProperty::AdapterScanMode(_) => mem::size_of::<BtScanMode>(),
507 BluetoothProperty::AdapterBondedDevices(devlist) => {
508 devlist.len() * mem::size_of::<RawAddress>()
509 }
510 BluetoothProperty::AdapterDiscoverableTimeout(_) => mem::size_of::<u32>(),
511 BluetoothProperty::RemoteFriendlyName(name) => {
512 cmp::min(PROPERTY_NAME_MAX, name.len() + 1)
513 }
514 BluetoothProperty::RemoteRssi(_) => mem::size_of::<i8>(),
515 BluetoothProperty::RemoteVersionInfo(_) => mem::size_of::<BtRemoteVersion>(),
516 BluetoothProperty::LocalLeFeatures(_) => mem::size_of::<BtLocalLeFeatures>(),
517 BluetoothProperty::LocalIoCaps(_) => mem::size_of::<BtIoCap>(),
518 BluetoothProperty::LocalIoCapsBle(_) => mem::size_of::<BtIoCap>(),
519 BluetoothProperty::RemoteIsCoordinatedSetMember(_) => mem::size_of::<bool>(),
520 BluetoothProperty::Appearance(_) => mem::size_of::<u16>(),
521 BluetoothProperty::VendorProductInfo(_) => mem::size_of::<BtVendorProductInfo>(),
522
523 // TODO(abps) - Figure out sizes for these
524 BluetoothProperty::DynamicAudioBuffer() => 0,
525 BluetoothProperty::RemoteDeviceTimestamp() => 0,
526 BluetoothProperty::Unknown() => 0,
527 }
528 }
529
530 /// Given a mutable array, this will copy the data to that array and return a
531 /// LTCheckedPtrMut to it.
532 ///
533 /// The lifetime of the returned pointer is tied to that of the slice given.
get_data_ptr<'a>(&'a self, data: &'a mut [u8]) -> LTCheckedPtrMut<'a, u8>534 fn get_data_ptr<'a>(&'a self, data: &'a mut [u8]) -> LTCheckedPtrMut<'a, u8> {
535 let len = self.get_len();
536 match &*self {
537 BluetoothProperty::BdName(name) => {
538 let copy_len = len - 1;
539 data[0..copy_len].copy_from_slice(&name.as_bytes()[0..copy_len]);
540 data[copy_len] = 0;
541 }
542 BluetoothProperty::BdAddr(addr) => {
543 data.copy_from_slice(&addr.address);
544 }
545 BluetoothProperty::Uuids(uulist) => {
546 for (idx, &uuid) in uulist.iter().enumerate() {
547 let start = idx * mem::size_of::<Uuid>();
548 let end = start + mem::size_of::<Uuid>();
549 data[start..end].copy_from_slice(&uuid.uu);
550 }
551 }
552 BluetoothProperty::ClassOfDevice(cod) => {
553 data.copy_from_slice(&cod.to_ne_bytes());
554 }
555 BluetoothProperty::TypeOfDevice(tod) => {
556 data.copy_from_slice(&BtDeviceType::to_u32(tod).unwrap_or_default().to_ne_bytes());
557 }
558 BluetoothProperty::ServiceRecord(sr) => {
559 // Do an unsafe cast to binding:: type and assign the values
560 // The underlying memory location is provided by |data| which will
561 // have enough space because it uses get_len()
562 let mut record =
563 unsafe { &mut *(data.as_mut_ptr() as *mut bindings::bt_service_record_t) };
564 record.uuid = sr.uuid;
565 record.channel = sr.channel;
566 let name_len = len - mem::size_of::<BtServiceRecord>() - 1;
567 record.name[0..name_len].copy_from_slice(
568 &(sr.name.as_bytes().iter().map(|x| *x as c_char).collect::<Vec<c_char>>())
569 [0..name_len],
570 );
571 record.name[name_len] = 0;
572 }
573 BluetoothProperty::AdapterScanMode(sm) => {
574 data.copy_from_slice(&BtScanMode::to_u32(sm).unwrap_or_default().to_ne_bytes());
575 }
576 BluetoothProperty::AdapterBondedDevices(devlist) => {
577 for (idx, &dev) in devlist.iter().enumerate() {
578 let start = idx * mem::size_of::<RawAddress>();
579 let end = idx + mem::size_of::<RawAddress>();
580 data[start..end].copy_from_slice(&dev.address);
581 }
582 }
583 BluetoothProperty::AdapterDiscoverableTimeout(timeout) => {
584 data.copy_from_slice(&timeout.to_ne_bytes());
585 }
586 BluetoothProperty::RemoteFriendlyName(name) => {
587 let copy_len = len - 1;
588 data[0..copy_len].copy_from_slice(&name.as_bytes()[0..copy_len]);
589 data[copy_len] = 0;
590 }
591 BluetoothProperty::RemoteRssi(rssi) => {
592 data[0] = *rssi as u8;
593 }
594 BluetoothProperty::RemoteVersionInfo(rvi) => {
595 let ptr: *const BtRemoteVersion = rvi;
596 let slice = unsafe {
597 std::slice::from_raw_parts(ptr as *mut u8, mem::size_of::<BtRemoteVersion>())
598 };
599 data.copy_from_slice(&slice);
600 }
601 BluetoothProperty::LocalLeFeatures(llf) => {
602 let ptr: *const BtLocalLeFeatures = llf;
603 let slice = unsafe {
604 std::slice::from_raw_parts(ptr as *mut u8, mem::size_of::<BtLocalLeFeatures>())
605 };
606 data.copy_from_slice(&slice);
607 }
608 BluetoothProperty::LocalIoCaps(iocap) => {
609 data.copy_from_slice(&BtIoCap::to_u32(iocap).unwrap_or_default().to_ne_bytes());
610 }
611 BluetoothProperty::LocalIoCapsBle(iocap) => {
612 data.copy_from_slice(&BtIoCap::to_u32(iocap).unwrap_or_default().to_ne_bytes());
613 }
614 BluetoothProperty::RemoteIsCoordinatedSetMember(icsm) => {
615 data[0] = *icsm as u8;
616 }
617 BluetoothProperty::Appearance(appearance) => {
618 data.copy_from_slice(&appearance.to_ne_bytes());
619 }
620 BluetoothProperty::VendorProductInfo(vpi) => {
621 let ptr: *const BtVendorProductInfo = vpi;
622 let slice = unsafe {
623 std::slice::from_raw_parts(
624 ptr as *mut u8,
625 mem::size_of::<BtVendorProductInfo>(),
626 )
627 };
628 data.copy_from_slice(&slice);
629 }
630
631 BluetoothProperty::DynamicAudioBuffer() => (),
632 BluetoothProperty::RemoteDeviceTimestamp() => (),
633 BluetoothProperty::Unknown() => (),
634 };
635
636 data.into()
637 }
638 }
639
640 // TODO(abps) - Check that sizes are correct when given a BtProperty
641 impl From<bindings::bt_property_t> for BluetoothProperty {
from(prop: bindings::bt_property_t) -> Self642 fn from(prop: bindings::bt_property_t) -> Self {
643 let slice: &[u8] =
644 unsafe { std::slice::from_raw_parts(prop.val as *mut u8, prop.len as usize) };
645 let len = prop.len as usize;
646
647 match BtPropertyType::from(prop.type_) {
648 BtPropertyType::BdName => BluetoothProperty::BdName(ascii_to_string(slice, len)),
649 BtPropertyType::BdAddr => {
650 BluetoothProperty::BdAddr(RawAddress::from_bytes(slice).unwrap_or_default())
651 }
652 BtPropertyType::Uuids => {
653 let count = len / mem::size_of::<Uuid>();
654 BluetoothProperty::Uuids(ptr_to_vec(prop.val as *mut Uuid, count))
655 }
656 BtPropertyType::ClassOfDevice => {
657 BluetoothProperty::ClassOfDevice(u32_from_bytes(slice))
658 }
659 BtPropertyType::TypeOfDevice => BluetoothProperty::TypeOfDevice(
660 BtDeviceType::from_u32(u32_from_bytes(slice)).unwrap_or(BtDeviceType::Unknown),
661 ),
662 BtPropertyType::ServiceRecord => {
663 let v = unsafe { *(prop.val as *const bindings::bt_service_record_t) };
664 BluetoothProperty::ServiceRecord(BtServiceRecord::from(v))
665 }
666 BtPropertyType::AdapterScanMode => BluetoothProperty::AdapterScanMode(
667 BtScanMode::from_u32(u32_from_bytes(slice)).unwrap_or(BtScanMode::None_),
668 ),
669 BtPropertyType::AdapterBondedDevices => {
670 let count = len / mem::size_of::<RawAddress>();
671 BluetoothProperty::AdapterBondedDevices(ptr_to_vec(
672 prop.val as *mut RawAddress,
673 count,
674 ))
675 }
676 BtPropertyType::AdapterDiscoverableTimeout => {
677 BluetoothProperty::AdapterDiscoverableTimeout(u32_from_bytes(slice))
678 }
679 BtPropertyType::RemoteFriendlyName => {
680 BluetoothProperty::RemoteFriendlyName(ascii_to_string(slice, len))
681 }
682 BtPropertyType::RemoteRssi => BluetoothProperty::RemoteRssi(slice[0] as i8),
683 BtPropertyType::RemoteVersionInfo => {
684 let v = unsafe { *(prop.val as *const BtRemoteVersion) };
685 BluetoothProperty::RemoteVersionInfo(v.clone())
686 }
687 BtPropertyType::LocalLeFeatures => {
688 let v = unsafe { *(prop.val as *const BtLocalLeFeatures) };
689 BluetoothProperty::LocalLeFeatures(v.clone())
690 }
691 BtPropertyType::LocalIoCaps => BluetoothProperty::LocalIoCaps(
692 BtIoCap::from_u32(u32_from_bytes(slice)).unwrap_or(BtIoCap::Unknown),
693 ),
694 BtPropertyType::LocalIoCapsBle => BluetoothProperty::LocalIoCapsBle(
695 BtIoCap::from_u32(u32_from_bytes(slice)).unwrap_or(BtIoCap::Unknown),
696 ),
697 BtPropertyType::RemoteIsCoordinatedSetMember => {
698 BluetoothProperty::RemoteIsCoordinatedSetMember(slice[0] != 0)
699 }
700 BtPropertyType::Appearance => BluetoothProperty::Appearance(u16_from_bytes(slice)),
701 BtPropertyType::VendorProductInfo => {
702 let v = unsafe { *(prop.val as *const BtVendorProductInfo) };
703 BluetoothProperty::VendorProductInfo(BtVendorProductInfo::from(v))
704 }
705
706 // TODO(abps) - Figure out if these values should actually have contents
707 BtPropertyType::DynamicAudioBuffer => BluetoothProperty::DynamicAudioBuffer(),
708 BtPropertyType::RemoteDeviceTimestamp => BluetoothProperty::RemoteDeviceTimestamp(),
709 _ => BluetoothProperty::Unknown(),
710 }
711 }
712 }
713
714 impl From<BluetoothProperty> for (Box<[u8]>, bindings::bt_property_t) {
from(prop: BluetoothProperty) -> Self715 fn from(prop: BluetoothProperty) -> Self {
716 let dvec: Vec<u8> = vec![0; prop.get_len()];
717 let mut data: Box<[u8]> = dvec.into_boxed_slice();
718 let prop = bindings::bt_property_t {
719 type_: prop.get_type().into(),
720 len: prop.get_len() as i32,
721 val: prop.get_data_ptr(&mut data).cast_into::<std::os::raw::c_void>(),
722 };
723
724 (data, prop)
725 }
726 }
727
728 pub enum SupportedProfiles {
729 HidHost,
730 Hfp,
731 A2dp,
732 Gatt,
733 Sdp,
734 Socket,
735 HfClient,
736 AvrcpCtrl,
737 }
738
739 impl From<SupportedProfiles> for Vec<u8> {
from(item: SupportedProfiles) -> Self740 fn from(item: SupportedProfiles) -> Self {
741 match item {
742 SupportedProfiles::HidHost => "hidhost",
743 SupportedProfiles::Hfp => "handsfree",
744 SupportedProfiles::A2dp => "a2dp",
745 SupportedProfiles::Gatt => "gatt",
746 SupportedProfiles::Sdp => "sdp",
747 SupportedProfiles::Socket => "socket",
748 SupportedProfiles::HfClient => "handsfree_client",
749 SupportedProfiles::AvrcpCtrl => "avrcp_ctrl",
750 }
751 .bytes()
752 .chain("\0".bytes())
753 .collect::<Vec<u8>>()
754 }
755 }
756
757 #[cxx::bridge(namespace = bluetooth::topshim::rust)]
758 mod ffi {
759 unsafe extern "C++" {
760 include!("btif/btif_shim.h");
761
762 // For converting init flags from Vec<String> to const char **
763 type InitFlags;
764
765 // Convert flgas into an InitFlags object
ConvertFlags(flags: Vec<String>) -> UniquePtr<InitFlags>766 fn ConvertFlags(flags: Vec<String>) -> UniquePtr<InitFlags>;
GetFlagsPtr(self: &InitFlags) -> *mut *const c_char767 fn GetFlagsPtr(self: &InitFlags) -> *mut *const c_char;
768 }
769 }
770
771 /// The RawAddress directly exported from the bindings.
772 ///
773 /// To make use of RawAddress in cxx::bridge C++ blocks,
774 /// include the following snippet in the ffi module.
775 /// ```ignore
776 /// #[cxx::bridge(namespace = bluetooth::topshim::rust)]
777 /// mod ffi {
778 /// unsafe extern "C++" {
779 /// include!("gd/rust/topshim/common/type_alias.h");
780 /// type RawAddress = crate::btif::RawAddress;
781 /// }
782 /// // Place you shared stuff here.
783 /// }
784 /// ```
785 pub type RawAddress = bindings::RawAddress;
786 pub type OobData = bindings::bt_oob_data_s;
787
788 unsafe impl ExternType for RawAddress {
789 type Id = type_id!("bluetooth::topshim::rust::RawAddress");
790 type Kind = cxx::kind::Trivial;
791 }
792
793 impl Hash for RawAddress {
hash<H: Hasher>(&self, state: &mut H)794 fn hash<H: Hasher>(&self, state: &mut H) {
795 self.address.hash(state);
796 }
797 }
798
799 // TODO (b/264603574): Handling address hiding in rust logging statements
800 impl ToString for RawAddress {
to_string(&self) -> String801 fn to_string(&self) -> String {
802 String::from(format!(
803 "{:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X}",
804 self.address[0],
805 self.address[1],
806 self.address[2],
807 self.address[3],
808 self.address[4],
809 self.address[5]
810 ))
811 }
812 }
813
814 impl RawAddress {
815 /// Constructs a RawAddress from a slice of 6 bytes.
from_bytes(raw_addr: &[u8]) -> Option<RawAddress>816 pub fn from_bytes(raw_addr: &[u8]) -> Option<RawAddress> {
817 if raw_addr.len() != 6 {
818 return None;
819 }
820 let mut raw: [u8; 6] = [0; 6];
821 raw.copy_from_slice(raw_addr);
822 return Some(RawAddress { address: raw });
823 }
824
from_string<S: Into<String>>(addr: S) -> Option<RawAddress>825 pub fn from_string<S: Into<String>>(addr: S) -> Option<RawAddress> {
826 let addr: String = addr.into();
827 let s = addr.split(':').collect::<Vec<&str>>();
828
829 if s.len() != 6 {
830 return None;
831 }
832
833 let mut raw: [u8; 6] = [0; 6];
834 for i in 0..s.len() {
835 raw[i] = match u8::from_str_radix(s[i], 16) {
836 Ok(res) => res,
837 Err(_) => {
838 return None;
839 }
840 };
841 }
842
843 Some(RawAddress { address: raw })
844 }
845
to_byte_arr(&self) -> [u8; 6]846 pub fn to_byte_arr(&self) -> [u8; 6] {
847 self.address.clone()
848 }
849
empty() -> RawAddress850 pub fn empty() -> RawAddress {
851 unsafe { bindings::RawAddress_kEmpty }
852 }
853 }
854
855 /// Address that is safe to display in logs.
856 pub struct DisplayAddress<'a>(pub &'a RawAddress);
857 impl<'a> Display for DisplayAddress<'a> {
fmt(&self, f: &mut Formatter) -> Result858 fn fmt(&self, f: &mut Formatter) -> Result {
859 write!(f, "xx:xx:xx:xx:{:02X}:{:02X}", &self.0.address[4], &self.0.address[5])
860 }
861 }
862
863 /// An enum representing `bt_callbacks_t` from btif.
864 #[derive(Clone, Debug)]
865 pub enum BaseCallbacks {
866 AdapterState(BtState),
867 AdapterProperties(BtStatus, i32, Vec<BluetoothProperty>),
868 RemoteDeviceProperties(BtStatus, RawAddress, i32, Vec<BluetoothProperty>),
869 DeviceFound(i32, Vec<BluetoothProperty>),
870 DiscoveryState(BtDiscoveryState),
871 PinRequest(RawAddress, String, u32, bool),
872 SspRequest(RawAddress, String, u32, BtSspVariant, u32),
873 BondState(BtStatus, RawAddress, BtBondState, i32),
874 AddressConsolidate(RawAddress, RawAddress),
875 LeAddressAssociate(RawAddress, RawAddress),
876 AclState(
877 BtStatus,
878 RawAddress,
879 BtAclState,
880 BtTransport,
881 BtHciErrorCode,
882 BtConnectionDirection,
883 u16,
884 ),
885 // Unimplemented so far:
886 // thread_evt_cb
887 // energy_info_cb
888 // link_quality_report_cb
889 // switch_buffer_size_cb
890 // switch_codec_cb
891 GenerateLocalOobData(u8, OobData),
892 LeRandCallback(u64),
893 }
894
895 pub struct BaseCallbacksDispatcher {
896 pub dispatch: Box<dyn Fn(BaseCallbacks) + Send>,
897 }
898
899 type BaseCb = Arc<Mutex<BaseCallbacksDispatcher>>;
900
901 cb_variant!(BaseCb, adapter_state_cb -> BaseCallbacks::AdapterState, u32 -> BtState);
902 cb_variant!(BaseCb, adapter_properties_cb -> BaseCallbacks::AdapterProperties,
903 u32 -> BtStatus, i32, *mut bindings::bt_property_t, {
904 let _2 = ptr_to_vec(_2, _1 as usize);
905 });
906 cb_variant!(BaseCb, remote_device_properties_cb -> BaseCallbacks::RemoteDeviceProperties,
907 u32 -> BtStatus, *mut RawAddress -> RawAddress, i32, *mut bindings::bt_property_t, {
908 let _1 = unsafe { *(_1 as *const RawAddress) };
909 let _3 = ptr_to_vec(_3, _2 as usize);
910 });
911 cb_variant!(BaseCb, device_found_cb -> BaseCallbacks::DeviceFound,
912 i32, *mut bindings::bt_property_t, {
913 let _1 = ptr_to_vec(_1, _0 as usize);
914 });
915 cb_variant!(BaseCb, discovery_state_cb -> BaseCallbacks::DiscoveryState,
916 bindings::bt_discovery_state_t -> BtDiscoveryState);
917 cb_variant!(BaseCb, pin_request_cb -> BaseCallbacks::PinRequest,
918 *mut RawAddress, *mut bindings::bt_bdname_t, u32, bool, {
919 let _0 = unsafe { *(_0 as *const RawAddress)};
920 let _1 = String::from(unsafe{*_1});
921 });
922 cb_variant!(BaseCb, ssp_request_cb -> BaseCallbacks::SspRequest,
923 *mut RawAddress, *mut bindings::bt_bdname_t, u32, bindings::bt_ssp_variant_t -> BtSspVariant, u32, {
924 let _0 = unsafe { *(_0 as *const RawAddress) };
925 let _1 = String::from(unsafe{*_1});
926 });
927 cb_variant!(BaseCb, bond_state_cb -> BaseCallbacks::BondState,
928 u32 -> BtStatus, *mut RawAddress, bindings::bt_bond_state_t -> BtBondState, i32, {
929 let _1 = unsafe { *(_1 as *const RawAddress) };
930 });
931
932 cb_variant!(BaseCb, address_consolidate_cb -> BaseCallbacks::AddressConsolidate,
933 *mut RawAddress, *mut RawAddress, {
934 let _0 = unsafe { *(_0 as *const RawAddress) };
935 let _1 = unsafe { *(_1 as *const RawAddress) };
936 });
937
938 cb_variant!(BaseCb, le_address_associate_cb -> BaseCallbacks::LeAddressAssociate,
939 *mut RawAddress, *mut RawAddress, {
940 let _0 = unsafe { *(_0 as *const RawAddress) };
941 let _1 = unsafe { *(_1 as *const RawAddress) };
942 });
943
944 cb_variant!(BaseCb, acl_state_cb -> BaseCallbacks::AclState,
945 u32 -> BtStatus, *mut RawAddress, bindings::bt_acl_state_t -> BtAclState, i32 -> BtTransport, bindings::bt_hci_error_code_t -> BtHciErrorCode, bindings::bt_conn_direction_t -> BtConnectionDirection, u16 -> u16, {
946 let _1 = unsafe { *(_1 as *const RawAddress) };
947 });
948
949 cb_variant!(BaseCb, generate_local_oob_data_cb -> BaseCallbacks::GenerateLocalOobData, u8, OobData);
950
951 cb_variant!(BaseCb, le_rand_cb -> BaseCallbacks::LeRandCallback, u64);
952
953 struct RawInterfaceWrapper {
954 pub raw: *const bindings::bt_interface_t,
955 }
956
957 unsafe impl Send for RawInterfaceWrapper {}
958
959 /// Macro to call functions via function pointers. Expects the self object to
960 /// have a raw interface wrapper at `self.internal`. The actual function call is
961 /// marked unsafe since it will need to dereference a C object. This can cause
962 /// segfaults if not validated beforehand.
963 ///
964 /// Example:
965 /// ccall!(self, foobar, arg1, arg2)
966 /// Expands to: unsafe {((*self.internal.raw).foobar.unwrap())(arg1, arg2)}
967 #[macro_export]
968 macro_rules! ccall {
969 ($self:ident,$fn_name:ident) => {
970 unsafe {
971 ((*$self.internal.raw).$fn_name.unwrap())()
972 }
973 };
974 ($self:ident,$fn_name:ident, $($args:expr),*) => {
975 unsafe {
976 ((*$self.internal.raw).$fn_name.unwrap())($($args),*)
977 }
978 };
979 }
980
981 /// Macro to call const functions via cxx. Expects the self object to have the
982 /// cxx object to be called at `self.internal_cxx`.
983 ///
984 /// Example:
985 /// cxxcall!(self, foobar, arg1, arg2)
986 /// Expands to: self.internal_cxx.foobar(arg1, arg2)
987 #[macro_export]
988 macro_rules! cxxcall {
989 ($self:expr,$fn_name:ident) => {
990 $self.internal_cxx.$fn_name()
991 };
992 ($self:expr,$fn_name:ident, $($args:expr),*) => {
993 $self.internal_cxx.$fn_name($($args),*)
994 };
995 }
996
997 /// Macro to call mutable functions via cxx. Mutable functions are always
998 /// required to be defined with `self: Pin<&mut Self>`. The self object must
999 /// have the cxx object at `self.internal_cxx`.
1000 ///
1001 /// Example:
1002 /// mutcxxcall!(self, foobar, arg1, arg2)
1003 /// Expands to: self.internal_cxx.pin_mut().foobar(arg1, arg2)
1004 #[macro_export]
1005 macro_rules! mutcxxcall {
1006 ($self:expr,$fn_name:ident) => {
1007 $self.internal_cxx.pin_mut().$fn_name()
1008 };
1009 ($self:expr,$fn_name:ident, $($args:expr),*) => {
1010 $self.internal_cxx.pin_mut().$fn_name($($args),*)
1011 };
1012 }
1013
1014 #[no_mangle]
wake_lock_noop(_0: *const ::std::os::raw::c_char) -> ::std::os::raw::c_int1015 extern "C" fn wake_lock_noop(_0: *const ::std::os::raw::c_char) -> ::std::os::raw::c_int {
1016 // The wakelock mechanism is not available on this platform,
1017 // so just returning success to avoid error log.
1018 0
1019 }
1020
1021 /// Rust wrapper around `bt_interface_t`.
1022 pub struct BluetoothInterface {
1023 internal: RawInterfaceWrapper,
1024
1025 /// Set to true after `initialize` is called.
1026 pub is_init: bool,
1027
1028 // Need to take ownership of callbacks so it doesn't get freed after init
1029 callbacks: Option<Box<bindings::bt_callbacks_t>>,
1030 os_callouts: Option<Box<bindings::bt_os_callouts_t>>,
1031 }
1032
1033 impl BluetoothInterface {
is_initialized(&self) -> bool1034 pub fn is_initialized(&self) -> bool {
1035 self.is_init
1036 }
1037
1038 /// Initialize the Bluetooth interface by setting up the underlying interface.
1039 ///
1040 /// # Arguments
1041 ///
1042 /// * `callbacks` - Dispatcher struct that accepts [`BaseCallbacks`]
1043 /// * `init_flags` - List of flags sent to libbluetooth for init.
initialize( &mut self, callbacks: BaseCallbacksDispatcher, init_flags: Vec<String>, ) -> bool1044 pub fn initialize(
1045 &mut self,
1046 callbacks: BaseCallbacksDispatcher,
1047 init_flags: Vec<String>,
1048 ) -> bool {
1049 // Init flags need to be converted from string to null terminated bytes
1050 let converted: cxx::UniquePtr<ffi::InitFlags> = ffi::ConvertFlags(init_flags);
1051 let flags = (*converted).GetFlagsPtr();
1052
1053 if get_dispatchers().lock().unwrap().set::<BaseCb>(Arc::new(Mutex::new(callbacks))) {
1054 panic!("Tried to set dispatcher for BaseCallbacks but it already existed");
1055 }
1056
1057 // Fill up callbacks struct to pass to init function (will be copied so
1058 // no need to worry about ownership)
1059 let mut callbacks = Box::new(bindings::bt_callbacks_t {
1060 size: std::mem::size_of::<bindings::bt_callbacks_t>(),
1061 adapter_state_changed_cb: Some(adapter_state_cb),
1062 adapter_properties_cb: Some(adapter_properties_cb),
1063 remote_device_properties_cb: Some(remote_device_properties_cb),
1064 device_found_cb: Some(device_found_cb),
1065 discovery_state_changed_cb: Some(discovery_state_cb),
1066 pin_request_cb: Some(pin_request_cb),
1067 ssp_request_cb: Some(ssp_request_cb),
1068 bond_state_changed_cb: Some(bond_state_cb),
1069 address_consolidate_cb: Some(address_consolidate_cb),
1070 le_address_associate_cb: Some(le_address_associate_cb),
1071 acl_state_changed_cb: Some(acl_state_cb),
1072 thread_evt_cb: None,
1073 energy_info_cb: None,
1074 link_quality_report_cb: None,
1075 generate_local_oob_data_cb: Some(generate_local_oob_data_cb),
1076 switch_buffer_size_cb: None,
1077 switch_codec_cb: None,
1078 le_rand_cb: Some(le_rand_cb),
1079 });
1080
1081 let cb_ptr = LTCheckedPtrMut::from(&mut callbacks);
1082
1083 let (guest_mode, is_common_criteria_mode, config_compare_result, is_atv) =
1084 (false, false, 0, false);
1085
1086 let init = ccall!(
1087 self,
1088 init,
1089 cb_ptr.into(),
1090 guest_mode,
1091 is_common_criteria_mode,
1092 config_compare_result,
1093 flags,
1094 is_atv,
1095 std::ptr::null()
1096 );
1097
1098 self.is_init = init == 0;
1099 self.callbacks = Some(callbacks);
1100
1101 if self.is_init {
1102 // Fill up OSI function table and register it with BTIF.
1103 // TODO(b/271931441) - pass a NoOpOsCallouts structure from
1104 // gd/rust/linux/stack.
1105 let mut callouts = Box::new(bindings::bt_os_callouts_t {
1106 size: std::mem::size_of::<bindings::bt_os_callouts_t>(),
1107 set_wake_alarm: None, // Not used
1108 acquire_wake_lock: Some(wake_lock_noop),
1109 release_wake_lock: Some(wake_lock_noop),
1110 });
1111 let callouts_ptr = LTCheckedPtrMut::from(&mut callouts);
1112 ccall!(self, set_os_callouts, callouts_ptr.into());
1113 self.os_callouts = Some(callouts);
1114 }
1115
1116 return self.is_init;
1117 }
1118
cleanup(&self)1119 pub fn cleanup(&self) {
1120 ccall!(self, cleanup)
1121 }
1122
enable(&self) -> i321123 pub fn enable(&self) -> i32 {
1124 ccall!(self, enable)
1125 }
1126
disable(&self) -> i321127 pub fn disable(&self) -> i32 {
1128 ccall!(self, disable)
1129 }
1130
get_adapter_properties(&self) -> i321131 pub fn get_adapter_properties(&self) -> i32 {
1132 ccall!(self, get_adapter_properties)
1133 }
1134
get_adapter_property(&self, prop: BtPropertyType) -> i321135 pub fn get_adapter_property(&self, prop: BtPropertyType) -> i32 {
1136 let converted_type = bindings::bt_property_type_t::from(prop);
1137 ccall!(self, get_adapter_property, converted_type)
1138 }
1139
set_adapter_property(&self, prop: BluetoothProperty) -> i321140 pub fn set_adapter_property(&self, prop: BluetoothProperty) -> i32 {
1141 let prop_pair: (Box<[u8]>, bindings::bt_property_t) = prop.into();
1142 let prop_ptr = LTCheckedPtr::from_ref(&prop_pair.1);
1143 ccall!(self, set_adapter_property, prop_ptr.into())
1144 }
1145
get_remote_device_properties(&self, addr: &mut RawAddress) -> i321146 pub fn get_remote_device_properties(&self, addr: &mut RawAddress) -> i32 {
1147 let addr_ptr = LTCheckedPtrMut::from_ref(addr);
1148 ccall!(self, get_remote_device_properties, addr_ptr.into())
1149 }
1150
get_remote_device_property( &self, addr: &mut RawAddress, prop_type: BtPropertyType, ) -> i321151 pub fn get_remote_device_property(
1152 &self,
1153 addr: &mut RawAddress,
1154 prop_type: BtPropertyType,
1155 ) -> i32 {
1156 let addr_ptr = LTCheckedPtrMut::from_ref(addr);
1157 let converted_type = bindings::bt_property_type_t::from(prop_type);
1158 ccall!(self, get_remote_device_property, addr_ptr.into(), converted_type)
1159 }
1160
set_remote_device_property( &self, addr: &mut RawAddress, prop: BluetoothProperty, ) -> i321161 pub fn set_remote_device_property(
1162 &self,
1163 addr: &mut RawAddress,
1164 prop: BluetoothProperty,
1165 ) -> i32 {
1166 let prop_pair: (Box<[u8]>, bindings::bt_property_t) = prop.into();
1167 let prop_ptr = LTCheckedPtr::from_ref(&prop_pair.1);
1168 let addr_ptr = LTCheckedPtrMut::from_ref(addr);
1169 ccall!(self, set_remote_device_property, addr_ptr.into(), prop_ptr.into())
1170 }
1171
get_remote_services(&self, addr: &mut RawAddress, transport: BtTransport) -> i321172 pub fn get_remote_services(&self, addr: &mut RawAddress, transport: BtTransport) -> i32 {
1173 let addr_ptr = LTCheckedPtrMut::from_ref(addr);
1174 ccall!(self, get_remote_services, addr_ptr.into(), transport.to_i32().unwrap())
1175 }
1176
start_discovery(&self) -> i321177 pub fn start_discovery(&self) -> i32 {
1178 ccall!(self, start_discovery)
1179 }
1180
cancel_discovery(&self) -> i321181 pub fn cancel_discovery(&self) -> i32 {
1182 ccall!(self, cancel_discovery)
1183 }
1184
create_bond(&self, addr: &RawAddress, transport: BtTransport) -> i321185 pub fn create_bond(&self, addr: &RawAddress, transport: BtTransport) -> i32 {
1186 let ctransport: i32 = transport.into();
1187 let addr_ptr = LTCheckedPtr::from_ref(addr);
1188 ccall!(self, create_bond, addr_ptr.into(), ctransport)
1189 }
1190
remove_bond(&self, addr: &RawAddress) -> i321191 pub fn remove_bond(&self, addr: &RawAddress) -> i32 {
1192 let addr_ptr = LTCheckedPtr::from_ref(addr);
1193 ccall!(self, remove_bond, addr_ptr.into())
1194 }
1195
cancel_bond(&self, addr: &RawAddress) -> i321196 pub fn cancel_bond(&self, addr: &RawAddress) -> i32 {
1197 let addr_ptr = LTCheckedPtr::from_ref(addr);
1198 ccall!(self, cancel_bond, addr_ptr.into())
1199 }
1200
get_connection_state(&self, addr: &RawAddress) -> BtConnectionState1201 pub fn get_connection_state(&self, addr: &RawAddress) -> BtConnectionState {
1202 let addr_ptr = LTCheckedPtr::from_ref(addr);
1203 ccall!(self, get_connection_state, addr_ptr.into()).into()
1204 }
1205
pin_reply( &self, addr: &RawAddress, accept: u8, pin_len: u8, pin_code: &mut BtPinCode, ) -> i321206 pub fn pin_reply(
1207 &self,
1208 addr: &RawAddress,
1209 accept: u8,
1210 pin_len: u8,
1211 pin_code: &mut BtPinCode,
1212 ) -> i32 {
1213 let addr_ptr = LTCheckedPtr::from_ref(addr);
1214 let pin_code_ptr = LTCheckedPtrMut::from_ref(pin_code);
1215 ccall!(self, pin_reply, addr_ptr.into(), accept, pin_len, pin_code_ptr.into())
1216 }
1217
ssp_reply( &self, addr: &RawAddress, variant: BtSspVariant, accept: u8, passkey: u32, ) -> i321218 pub fn ssp_reply(
1219 &self,
1220 addr: &RawAddress,
1221 variant: BtSspVariant,
1222 accept: u8,
1223 passkey: u32,
1224 ) -> i32 {
1225 let addr_ptr = LTCheckedPtr::from_ref(addr);
1226 let cvariant = bindings::bt_ssp_variant_t::from(variant);
1227 ccall!(self, ssp_reply, addr_ptr.into(), cvariant, accept, passkey)
1228 }
1229
clear_event_filter(&self) -> i321230 pub fn clear_event_filter(&self) -> i32 {
1231 ccall!(self, clear_event_filter)
1232 }
1233
clear_event_mask(&self) -> i321234 pub fn clear_event_mask(&self) -> i32 {
1235 ccall!(self, clear_event_mask)
1236 }
1237
clear_filter_accept_list(&self) -> i321238 pub fn clear_filter_accept_list(&self) -> i32 {
1239 ccall!(self, clear_filter_accept_list)
1240 }
1241
disconnect_all_acls(&self) -> i321242 pub fn disconnect_all_acls(&self) -> i32 {
1243 ccall!(self, disconnect_all_acls)
1244 }
1245
allow_wake_by_hid(&self) -> i321246 pub fn allow_wake_by_hid(&self) -> i32 {
1247 ccall!(self, allow_wake_by_hid)
1248 }
1249
get_wbs_supported(&self) -> bool1250 pub fn get_wbs_supported(&self) -> bool {
1251 ccall!(self, get_wbs_supported)
1252 }
1253
get_swb_supported(&self) -> bool1254 pub fn get_swb_supported(&self) -> bool {
1255 ccall!(self, get_swb_supported)
1256 }
1257
le_rand(&self) -> i321258 pub fn le_rand(&self) -> i32 {
1259 ccall!(self, le_rand)
1260 }
1261
generate_local_oob_data(&self, transport: i32) -> i321262 pub fn generate_local_oob_data(&self, transport: i32) -> i32 {
1263 ccall!(self, generate_local_oob_data, transport as u8)
1264 }
1265
restore_filter_accept_list(&self) -> i321266 pub fn restore_filter_accept_list(&self) -> i32 {
1267 ccall!(self, restore_filter_accept_list)
1268 }
1269
set_default_event_mask_except(&self, mask: u64, le_mask: u64) -> i321270 pub fn set_default_event_mask_except(&self, mask: u64, le_mask: u64) -> i32 {
1271 ccall!(self, set_default_event_mask_except, mask, le_mask)
1272 }
1273
set_event_filter_inquiry_result_all_devices(&self) -> i321274 pub fn set_event_filter_inquiry_result_all_devices(&self) -> i32 {
1275 ccall!(self, set_event_filter_inquiry_result_all_devices)
1276 }
1277
set_event_filter_connection_setup_all_devices(&self) -> i321278 pub fn set_event_filter_connection_setup_all_devices(&self) -> i32 {
1279 ccall!(self, set_event_filter_connection_setup_all_devices)
1280 }
1281
get_profile_interface( &self, profile: SupportedProfiles, ) -> *const std::os::raw::c_void1282 pub(crate) fn get_profile_interface(
1283 &self,
1284 profile: SupportedProfiles,
1285 ) -> *const std::os::raw::c_void {
1286 let cprofile = Vec::<u8>::from(profile);
1287 let cprofile_ptr = LTCheckedPtr::from(&cprofile);
1288 ccall!(self, get_profile_interface, cprofile_ptr.cast_into::<std::os::raw::c_char>())
1289 }
1290
as_raw_ptr(&self) -> *const u81291 pub(crate) fn as_raw_ptr(&self) -> *const u8 {
1292 self.internal.raw as *const u8
1293 }
1294 }
1295
1296 pub trait ToggleableProfile {
is_enabled(&self) -> bool1297 fn is_enabled(&self) -> bool;
enable(&mut self) -> bool1298 fn enable(&mut self) -> bool;
disable(&mut self) -> bool1299 fn disable(&mut self) -> bool;
1300 }
1301
get_btinterface() -> Option<BluetoothInterface>1302 pub fn get_btinterface() -> Option<BluetoothInterface> {
1303 let mut ret: Option<BluetoothInterface> = None;
1304 let mut ifptr: *const bindings::bt_interface_t = std::ptr::null();
1305
1306 unsafe {
1307 if bindings::hal_util_load_bt_library(&mut ifptr) == 0 {
1308 ret = Some(BluetoothInterface {
1309 internal: RawInterfaceWrapper { raw: ifptr },
1310 is_init: false,
1311 callbacks: None,
1312 os_callouts: None,
1313 });
1314 }
1315 }
1316
1317 ret
1318 }
1319
1320 // Turns C-array T[] to Vec<U>.
ptr_to_vec<T: Copy, U: From<T>>(start: *const T, length: usize) -> Vec<U>1321 pub(crate) fn ptr_to_vec<T: Copy, U: From<T>>(start: *const T, length: usize) -> Vec<U> {
1322 unsafe { (0..length).map(|i| U::from(*start.offset(i as isize))).collect::<Vec<U>>() }
1323 }
1324
1325 #[cfg(test)]
1326 mod tests {
1327 use super::*;
1328
make_bdname_from_slice(slice: &[u8]) -> bindings::bt_bdname_t1329 fn make_bdname_from_slice(slice: &[u8]) -> bindings::bt_bdname_t {
1330 // Length of slice must be less than bd_name max
1331 assert!(slice.len() <= 249);
1332
1333 let mut bdname = bindings::bt_bdname_t { name: [128; 249] };
1334
1335 for (i, v) in slice.iter().enumerate() {
1336 bdname.name[i] = v.clone();
1337 }
1338
1339 bdname
1340 }
1341
1342 #[test]
test_bdname_conversions()1343 fn test_bdname_conversions() {
1344 let hello_bdname = make_bdname_from_slice(&[72, 69, 76, 76, 79, 0]);
1345 assert_eq!("HELLO".to_string(), String::from(hello_bdname));
1346
1347 let empty_bdname = make_bdname_from_slice(&[0]);
1348 assert_eq!("".to_string(), String::from(empty_bdname));
1349
1350 let no_nullterm_bdname = make_bdname_from_slice(&[72, 69, 76, 76, 79]);
1351 assert_eq!("".to_string(), String::from(no_nullterm_bdname));
1352
1353 let invalid_bdname = make_bdname_from_slice(&[128; 249]);
1354 assert_eq!("".to_string(), String::from(invalid_bdname));
1355 }
1356
1357 #[test]
test_ptr_to_vec()1358 fn test_ptr_to_vec() {
1359 let arr: [i32; 3] = [1, 2, 3];
1360 let vec: Vec<i32> = ptr_to_vec(arr.as_ptr(), arr.len());
1361 let expected: Vec<i32> = vec![1, 2, 3];
1362 assert_eq!(expected, vec);
1363 }
1364
1365 #[test]
test_property_with_string_conversions()1366 fn test_property_with_string_conversions() {
1367 {
1368 let bdname = BluetoothProperty::BdName("FooBar".into());
1369 let prop_pair: (Box<[u8]>, bindings::bt_property_t) = bdname.into();
1370 let converted: BluetoothProperty = prop_pair.1.into();
1371 assert!(match converted {
1372 BluetoothProperty::BdName(name) => "FooBar".to_string() == name,
1373 _ => false,
1374 });
1375 }
1376
1377 {
1378 let orig_record = BtServiceRecord {
1379 uuid: Uuid::from([0; 16]),
1380 channel: 3,
1381 name: "FooBar".to_string(),
1382 };
1383 let service_record = BluetoothProperty::ServiceRecord(orig_record.clone());
1384 let prop_pair: (Box<[u8]>, bindings::bt_property_t) = service_record.into();
1385 let converted: BluetoothProperty = prop_pair.1.into();
1386 assert!(match converted {
1387 BluetoothProperty::ServiceRecord(sr) => {
1388 sr.uuid == orig_record.uuid
1389 && sr.channel == orig_record.channel
1390 && sr.name == orig_record.name
1391 }
1392 _ => false,
1393 });
1394 }
1395
1396 {
1397 let rfname = BluetoothProperty::RemoteFriendlyName("FooBizz".into());
1398 let prop_pair: (Box<[u8]>, bindings::bt_property_t) = rfname.into();
1399 let converted: BluetoothProperty = prop_pair.1.into();
1400 assert!(match converted {
1401 BluetoothProperty::RemoteFriendlyName(name) => "FooBizz".to_string() == name,
1402 _ => false,
1403 });
1404 }
1405 }
1406
1407 #[test]
test_display_address()1408 fn test_display_address() {
1409 assert_eq!(
1410 format!("{}", DisplayAddress(&RawAddress::from_string("00:00:00:00:00:00").unwrap())),
1411 String::from("xx:xx:xx:xx:00:00")
1412 );
1413 assert_eq!(
1414 format!("{}", DisplayAddress(&RawAddress::from_string("1a:2b:1a:2b:1a:2b").unwrap())),
1415 String::from("xx:xx:xx:xx:1A:2B")
1416 );
1417 assert_eq!(
1418 format!("{}", DisplayAddress(&RawAddress::from_string("3C:4D:3C:4D:3C:4D").unwrap())),
1419 String::from("xx:xx:xx:xx:3C:4D")
1420 );
1421 assert_eq!(
1422 format!("{}", DisplayAddress(&RawAddress::from_string("11:35:11:35:11:35").unwrap())),
1423 String::from("xx:xx:xx:xx:11:35")
1424 );
1425 }
1426 }
1427