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::fd::RawFd;
16 use std::os::raw::c_char;
17 use std::sync::{Arc, Mutex};
18 use std::vec::Vec;
19 use topshim_macros::{cb_variant, gen_cxx_extern_trivial};
20
21 #[derive(Clone, Debug, FromPrimitive, ToPrimitive, PartialEq, PartialOrd)]
22 #[repr(u32)]
23 pub enum BtState {
24 Off = 0,
25 On,
26 }
27
28 impl From<bindings::bt_state_t> for BtState {
from(item: bindings::bt_state_t) -> Self29 fn from(item: bindings::bt_state_t) -> Self {
30 BtState::from_u32(item).unwrap_or(BtState::Off)
31 }
32 }
33
34 #[derive(Clone, Debug, FromPrimitive, ToPrimitive, PartialEq, PartialOrd, Copy)]
35 #[repr(u32)]
36 pub enum BtTransport {
37 Auto = 0,
38 Bredr,
39 Le,
40 }
41
42 impl From<i32> for BtTransport {
from(item: i32) -> Self43 fn from(item: i32) -> Self {
44 BtTransport::from_i32(item).unwrap_or(BtTransport::Auto)
45 }
46 }
47
48 impl From<BtTransport> for i32 {
from(item: BtTransport) -> Self49 fn from(item: BtTransport) -> Self {
50 item.to_i32().unwrap_or(0)
51 }
52 }
53
54 impl From<u8> for BtTransport {
from(transport: u8) -> Self55 fn from(transport: u8) -> Self {
56 BtTransport::from_u8(transport).unwrap_or(BtTransport::Auto)
57 }
58 }
59
60 impl Into<u8> for BtTransport {
into(self) -> u861 fn into(self) -> u8 {
62 self.to_u8().unwrap_or(0)
63 }
64 }
65
66 #[derive(Clone, Debug, FromPrimitive, ToPrimitive, PartialEq, PartialOrd)]
67 #[repr(u32)]
68 pub enum BtSspVariant {
69 PasskeyConfirmation = 0,
70 PasskeyEntry,
71 Consent,
72 PasskeyNotification,
73 }
74
75 impl From<bindings::bt_ssp_variant_t> for BtSspVariant {
from(item: bindings::bt_ssp_variant_t) -> Self76 fn from(item: bindings::bt_ssp_variant_t) -> Self {
77 BtSspVariant::from_u32(item).unwrap_or(BtSspVariant::PasskeyConfirmation)
78 }
79 }
80
81 impl From<BtSspVariant> for bindings::bt_ssp_variant_t {
from(item: BtSspVariant) -> Self82 fn from(item: BtSspVariant) -> Self {
83 item.to_u32().unwrap_or(0)
84 }
85 }
86
87 #[derive(Clone, Debug, FromPrimitive, ToPrimitive, PartialEq, PartialOrd)]
88 #[repr(u32)]
89 pub enum BtBondState {
90 NotBonded = 0,
91 Bonding,
92 Bonded,
93 }
94
95 impl From<bindings::bt_bond_state_t> for BtBondState {
from(item: bindings::bt_bond_state_t) -> Self96 fn from(item: bindings::bt_bond_state_t) -> Self {
97 BtBondState::from_u32(item).unwrap_or(BtBondState::NotBonded)
98 }
99 }
100
101 #[derive(Clone, Debug, FromPrimitive, ToPrimitive, PartialEq, PartialOrd)]
102 #[repr(u32)]
103 pub enum BtConnectionState {
104 NotConnected = 0,
105 ConnectedOnly = 1,
106 EncryptedBredr = 3,
107 EncryptedLe = 5,
108 EncryptedBoth = 7,
109 }
110
111 impl From<i32> for BtConnectionState {
from(item: i32) -> Self112 fn from(item: i32) -> Self {
113 let fallback = if item > 0 {
114 BtConnectionState::ConnectedOnly
115 } else {
116 BtConnectionState::NotConnected
117 };
118
119 BtConnectionState::from_i32(item).unwrap_or(fallback)
120 }
121 }
122
123 #[derive(Clone, Debug, FromPrimitive, ToPrimitive, PartialEq, PartialOrd)]
124 #[repr(u32)]
125 pub enum BtAclState {
126 Connected = 0,
127 Disconnected,
128 }
129
130 impl From<bindings::bt_acl_state_t> for BtAclState {
from(item: bindings::bt_acl_state_t) -> Self131 fn from(item: bindings::bt_acl_state_t) -> Self {
132 BtAclState::from_u32(item).unwrap_or(BtAclState::Disconnected)
133 }
134 }
135
136 #[derive(Clone, Debug, FromPrimitive, ToPrimitive, PartialEq, PartialOrd)]
137 #[repr(u32)]
138 pub enum BtDeviceType {
139 Unknown = 0,
140 Bredr,
141 Ble,
142 Dual,
143 }
144
145 #[derive(Clone, Debug, Eq, Hash, FromPrimitive, ToPrimitive, PartialEq, PartialOrd)]
146 #[repr(u32)]
147 pub enum BtPropertyType {
148 BdName = 0x1,
149 BdAddr,
150 Uuids,
151 ClassOfDevice,
152 TypeOfDevice,
153 ServiceRecord,
154 AdapterScanMode,
155 AdapterBondedDevices,
156 AdapterDiscoverableTimeout,
157 RemoteFriendlyName,
158 RemoteRssi,
159 RemoteVersionInfo,
160 LocalLeFeatures,
161 LocalIoCaps,
162 LocalIoCapsBle,
163 DynamicAudioBuffer,
164 RemoteIsCoordinatedSetMember,
165 Appearance,
166 VendorProductInfo,
167 // Unimplemented:
168 // BT_PROPERTY_REMOTE_ASHA_CAPABILITY,
169 // BT_PROPERTY_REMOTE_ASHA_TRUNCATED_HISYNCID,
170 // BT_PROPERTY_REMOTE_MODEL_NUM,
171 RemoteAddrType = 0x18,
172
173 Unknown = 0xFE,
174 RemoteDeviceTimestamp = 0xFF,
175 }
176
177 impl From<u32> for BtPropertyType {
from(item: u32) -> Self178 fn from(item: u32) -> Self {
179 BtPropertyType::from_u32(item).unwrap_or(BtPropertyType::Unknown)
180 }
181 }
182
183 impl From<BtPropertyType> for u32 {
from(item: BtPropertyType) -> Self184 fn from(item: BtPropertyType) -> Self {
185 item.to_u32().unwrap_or(0)
186 }
187 }
188
189 #[derive(Clone, Debug, FromPrimitive, ToPrimitive, PartialEq, PartialOrd)]
190 #[repr(u32)]
191 pub enum BtDiscoveryState {
192 Stopped = 0x0,
193 Started,
194 }
195
196 impl From<u32> for BtDiscoveryState {
from(item: u32) -> Self197 fn from(item: u32) -> Self {
198 BtDiscoveryState::from_u32(item).unwrap_or(BtDiscoveryState::Stopped)
199 }
200 }
201
202 #[derive(Clone, Copy, Debug, FromPrimitive, ToPrimitive, PartialEq, PartialOrd)]
203 #[repr(u32)]
204 pub enum BtStatus {
205 Success = 0,
206 Fail,
207 NotReady,
208 NoMemory,
209 Busy,
210 Done,
211 Unsupported,
212 InvalidParam,
213 Unhandled,
214 AuthFailure,
215 RemoteDeviceDown,
216 AuthRejected,
217 JniEnvironmentError,
218 JniThreadAttachError,
219 WakeLockError,
220 Timeout,
221 DeviceNotFound,
222 UnexpectedState,
223 SocketError,
224
225 // Any statuses that couldn't be cleanly converted
226 Unknown = 0xff,
227 }
228
229 #[derive(Clone, Debug, FromPrimitive, ToPrimitive, PartialEq, PartialOrd)]
230 #[repr(u32)]
231 pub enum BtConnectionDirection {
232 Unknown = 0,
233 Outgoing,
234 Incoming,
235 }
236
237 impl From<u32> for BtConnectionDirection {
from(item: u32) -> Self238 fn from(item: u32) -> Self {
239 BtConnectionDirection::from_u32(item).unwrap_or(BtConnectionDirection::Unknown)
240 }
241 }
242
ascii_to_string(data: &[u8], length: usize) -> String243 pub fn ascii_to_string(data: &[u8], length: usize) -> String {
244 // We need to reslice data because from_utf8 tries to interpret the
245 // whole slice and not just what is before the null terminated portion
246 let ascii = data
247 .iter()
248 .enumerate()
249 .take_while(|&(pos, &c)| c != 0 && pos < length)
250 .map(|(_pos, &x)| x.clone())
251 .collect::<Vec<u8>>();
252
253 return String::from_utf8(ascii).unwrap_or_default();
254 }
255
u32_from_bytes(item: &[u8]) -> u32256 fn u32_from_bytes(item: &[u8]) -> u32 {
257 let mut u: [u8; 4] = [0; 4];
258 let len = std::cmp::min(item.len(), 4);
259 u[0..len].copy_from_slice(&item);
260 u32::from_ne_bytes(u)
261 }
262
u16_from_bytes(item: &[u8]) -> u16263 fn u16_from_bytes(item: &[u8]) -> u16 {
264 let mut u: [u8; 2] = [0; 2];
265 let len = std::cmp::min(item.len(), 2);
266 u[0..len].copy_from_slice(&item);
267 u16::from_ne_bytes(u)
268 }
269
270 impl From<bindings::bt_status_t> for BtStatus {
from(item: bindings::bt_status_t) -> Self271 fn from(item: bindings::bt_status_t) -> Self {
272 match BtStatus::from_u32(item) {
273 Some(x) => x,
274 _ => BtStatus::Unknown,
275 }
276 }
277 }
278
279 impl Into<u32> for BtStatus {
into(self) -> u32280 fn into(self) -> u32 {
281 self.to_u32().unwrap_or_default()
282 }
283 }
284
285 impl Into<i32> for BtStatus {
into(self) -> i32286 fn into(self) -> i32 {
287 self.to_i32().unwrap_or_default()
288 }
289 }
290
291 impl From<bindings::bt_bdname_t> for String {
from(item: bindings::bt_bdname_t) -> Self292 fn from(item: bindings::bt_bdname_t) -> Self {
293 ascii_to_string(&item.name, item.name.len())
294 }
295 }
296
297 #[derive(Debug, Clone)]
298 pub struct BtServiceRecord {
299 pub uuid: bindings::bluetooth::Uuid,
300 pub channel: u16,
301 pub name: String,
302 }
303
304 impl From<bindings::bt_service_record_t> for BtServiceRecord {
from(item: bindings::bt_service_record_t) -> Self305 fn from(item: bindings::bt_service_record_t) -> Self {
306 let name = item.name.iter().map(|&x| x.clone() as u8).collect::<Vec<u8>>();
307
308 BtServiceRecord {
309 uuid: item.uuid,
310 channel: item.channel,
311 name: ascii_to_string(name.as_slice(), name.len()),
312 }
313 }
314 }
315
316 #[derive(Clone, Debug, FromPrimitive, ToPrimitive, PartialEq, PartialOrd)]
317 #[repr(u32)]
318 pub enum BtScanMode {
319 None_,
320 Connectable,
321 ConnectableDiscoverable,
322 ConnectableLimitedDiscoverable,
323 }
324
325 impl From<bindings::bt_scan_mode_t> for BtScanMode {
from(item: bindings::bt_scan_mode_t) -> Self326 fn from(item: bindings::bt_scan_mode_t) -> Self {
327 BtScanMode::from_u32(item).unwrap_or(BtScanMode::None_)
328 }
329 }
330
331 #[derive(Clone, Debug, FromPrimitive, ToPrimitive, PartialEq, PartialOrd)]
332 #[repr(u32)]
333 pub enum BtDiscMode {
334 // reference to system/stack/btm/neighbor_inquiry.h
335 NonDiscoverable = 0,
336 LimitedDiscoverable = 1,
337 GeneralDiscoverable = 2,
338 }
339
340 impl From<u32> for BtDiscMode {
from(num: u32) -> Self341 fn from(num: u32) -> Self {
342 BtDiscMode::from_u32(num).unwrap_or(BtDiscMode::NonDiscoverable)
343 }
344 }
345
346 impl Into<u32> for BtDiscMode {
into(self) -> u32347 fn into(self) -> u32 {
348 self.to_u32().unwrap_or(0)
349 }
350 }
351
352 #[derive(Clone, Debug, FromPrimitive, ToPrimitive, PartialEq, PartialOrd)]
353 #[repr(u32)]
354 pub enum BtThreadEvent {
355 Associate = 0,
356 Disassociate,
357 }
358
359 impl From<bindings::bt_cb_thread_evt> for BtThreadEvent {
from(item: bindings::bt_cb_thread_evt) -> Self360 fn from(item: bindings::bt_cb_thread_evt) -> Self {
361 BtThreadEvent::from_u32(item).unwrap_or(BtThreadEvent::Associate)
362 }
363 }
364
365 #[derive(Clone, Debug, FromPrimitive, ToPrimitive, PartialEq, PartialOrd)]
366 #[repr(u32)]
367 pub enum BtIoCap {
368 Out,
369 InOut,
370 In,
371 None_,
372 KbDisp,
373 Max,
374 Unknown = 0xff,
375 }
376
377 impl From<bindings::bt_io_cap_t> for BtIoCap {
from(item: bindings::bt_io_cap_t) -> Self378 fn from(item: bindings::bt_io_cap_t) -> Self {
379 BtIoCap::from_u32(item).unwrap_or(BtIoCap::Unknown)
380 }
381 }
382
383 #[derive(Clone, Debug, FromPrimitive, ToPrimitive, PartialEq, PartialOrd)]
384 #[repr(u32)]
385 pub enum BtAddrType {
386 Public,
387 Random,
388 PublicId,
389 RandomId,
390 Unknown = 0xfe,
391 Anonymous = 0xff,
392 }
393
394 impl From<u32> for BtAddrType {
from(num: u32) -> Self395 fn from(num: u32) -> Self {
396 BtAddrType::from_u32(num).unwrap_or(BtAddrType::Unknown)
397 }
398 }
399
400 impl Into<u32> for BtAddrType {
into(self) -> u32401 fn into(self) -> u32 {
402 self.to_u32().unwrap_or(0)
403 }
404 }
405
406 impl From<u8> for BtAddrType {
from(address_type: u8) -> Self407 fn from(address_type: u8) -> Self {
408 BtAddrType::from_u8(address_type).unwrap_or(BtAddrType::Unknown)
409 }
410 }
411
412 impl Into<u8> for BtAddrType {
into(self) -> u8413 fn into(self) -> u8 {
414 self.to_u8().unwrap_or(0)
415 }
416 }
417
418 pub type BtHciErrorCode = u8;
419 pub type BtLocalLeFeatures = bindings::bt_local_le_features_t;
420 pub type BtPinCode = bindings::bt_pin_code_t;
421 pub type BtRemoteVersion = bindings::bt_remote_version_t;
422 pub type BtVendorProductInfo = bindings::bt_vendor_product_info_t;
423
424 impl TryFrom<Uuid> for Vec<u8> {
425 type Error = &'static str;
426
try_from(value: Uuid) -> std::result::Result<Self, Self::Error>427 fn try_from(value: Uuid) -> std::result::Result<Self, Self::Error> {
428 Ok((&value.uu).to_vec())
429 }
430 }
431
432 impl TryFrom<Vec<u8>> for Uuid {
433 type Error = &'static str;
434
try_from(value: Vec<u8>) -> std::result::Result<Self, Self::Error>435 fn try_from(value: Vec<u8>) -> std::result::Result<Self, Self::Error> {
436 // base UUID defined in the Bluetooth specification
437 let mut uu: [u8; 16] =
438 [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x80, 0x0, 0x0, 0x80, 0x5f, 0x9b, 0x34, 0xfb];
439 match value.len() {
440 2 => {
441 uu[2..4].copy_from_slice(&value[0..2]);
442 Ok(Uuid::from(uu))
443 }
444 4 => {
445 uu[0..4].copy_from_slice(&value[0..4]);
446 Ok(Uuid::from(uu))
447 }
448 16 => {
449 uu.copy_from_slice(&value[0..16]);
450 Ok(Uuid::from(uu))
451 }
452 _ => {
453 Err("Vector size must be exactly 2 (16 bit UUID), 4 (32 bit UUID), or 16 (128 bit UUID).")
454 }
455 }
456 }
457 }
458
459 impl From<[u8; 16]> for Uuid {
from(value: [u8; 16]) -> Self460 fn from(value: [u8; 16]) -> Self {
461 Self { uu: value }
462 }
463 }
464
465 impl From<Uuid> for [u8; 16] {
from(uuid: Uuid) -> Self466 fn from(uuid: Uuid) -> Self {
467 uuid.uu
468 }
469 }
470
471 impl Hash for Uuid {
hash<H: Hasher>(&self, state: &mut H)472 fn hash<H: Hasher>(&self, state: &mut H) {
473 self.uu.hash(state);
474 }
475 }
476
477 impl Uuid {
478 const BASE_UUID_NUM: u128 = 0x0000000000001000800000805f9b34fbu128;
479 const BASE_UUID_MASK: u128 = !(0xffffffffu128 << 96);
480
481 /// Creates a Uuid from little endian slice of bytes
try_from_little_endian(value: &[u8]) -> std::result::Result<Uuid, &'static str>482 pub fn try_from_little_endian(value: &[u8]) -> std::result::Result<Uuid, &'static str> {
483 Uuid::try_from(value.iter().rev().cloned().collect::<Vec<u8>>())
484 }
485
empty() -> Uuid486 pub fn empty() -> Uuid {
487 unsafe { bindings::bluetooth::Uuid_kEmpty }
488 }
489
from_string<S: Into<String>>(raw: S) -> Option<Self>490 pub fn from_string<S: Into<String>>(raw: S) -> Option<Self> {
491 let raw: String = raw.into();
492
493 let raw = raw.chars().filter(|c| c.is_digit(16)).collect::<String>();
494 let s = raw.as_str();
495 if s.len() != 32 {
496 return None;
497 }
498
499 let mut uu = [0; 16];
500 for i in 0..16 {
501 uu[i] = u8::from_str_radix(&s[i * 2..i * 2 + 2], 16).ok()?;
502 }
503
504 Some(uu.into())
505 }
506
507 /// Parses an 128-bit UUID into a byte array of shortest representation.
get_shortest_slice(&self) -> &[u8]508 pub fn get_shortest_slice(&self) -> &[u8] {
509 if self.in_16bit_uuid_range() {
510 &self.uu[2..4]
511 } else if self.in_32bit_uuid_range() {
512 &self.uu[0..4]
513 } else {
514 &self.uu[..]
515 }
516 }
517
518 /// Checks whether the UUID value is in the 16-bit Bluetooth UUID range.
in_16bit_uuid_range(&self) -> bool519 fn in_16bit_uuid_range(&self) -> bool {
520 if !self.in_32bit_uuid_range() {
521 return false;
522 }
523 self.uu[0] == 0 && self.uu[1] == 0
524 }
525
526 /// Checks whether the UUID value is in the 32-bit Bluetooth UUID range.
in_32bit_uuid_range(&self) -> bool527 fn in_32bit_uuid_range(&self) -> bool {
528 let num = u128::from_be_bytes(self.uu);
529 (num & Self::BASE_UUID_MASK) == Self::BASE_UUID_NUM
530 }
531 }
532
533 /// Formats this UUID to a human-readable representation.
534 impl Display for Uuid {
fmt(&self, f: &mut Formatter) -> Result535 fn fmt(&self, f: &mut Formatter) -> Result {
536 write!(
537 f,
538 "{:02x}{:02x}{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}",
539 self.uu[0], self.uu[1], self.uu[2], self.uu[3],
540 self.uu[4], self.uu[5],
541 self.uu[6], self.uu[7],
542 self.uu[8], self.uu[9],
543 self.uu[10], self.uu[11], self.uu[12], self.uu[13], self.uu[14], self.uu[15]
544 )
545 }
546 }
547
548 /// UUID that is safe to display in logs.
549 pub struct DisplayUuid<'a>(pub &'a Uuid);
550 impl<'a> Display for DisplayUuid<'a> {
fmt(&self, f: &mut Formatter) -> Result551 fn fmt(&self, f: &mut Formatter) -> Result {
552 write!(
553 f,
554 "{:02x}{:02x}{:02x}{:02x}-xxxx-xxxx-xxxx-xxxx{:02x}{:02x}{:02x}{:02x}",
555 self.0.uu[0],
556 self.0.uu[1],
557 self.0.uu[2],
558 self.0.uu[3],
559 self.0.uu[12],
560 self.0.uu[13],
561 self.0.uu[14],
562 self.0.uu[15]
563 )
564 }
565 }
566
567 /// All supported Bluetooth properties after conversion.
568 #[derive(Debug, Clone)]
569 pub enum BluetoothProperty {
570 BdName(String),
571 BdAddr(RawAddress),
572 Uuids(Vec<Uuid>),
573 ClassOfDevice(u32),
574 TypeOfDevice(BtDeviceType),
575 ServiceRecord(BtServiceRecord),
576 AdapterScanMode(BtScanMode),
577 AdapterBondedDevices(Vec<RawAddress>),
578 AdapterDiscoverableTimeout(u32),
579 RemoteFriendlyName(String),
580 RemoteRssi(i8),
581 RemoteVersionInfo(BtRemoteVersion),
582 LocalLeFeatures(BtLocalLeFeatures),
583 LocalIoCaps(BtIoCap),
584 LocalIoCapsBle(BtIoCap),
585 DynamicAudioBuffer(),
586 RemoteIsCoordinatedSetMember(bool),
587 Appearance(u16),
588 VendorProductInfo(BtVendorProductInfo),
589 RemoteAddrType(BtAddrType),
590 RemoteDeviceTimestamp(),
591
592 Unknown(),
593 }
594
595 /// Unknown or invalid RSSI value.
596 /// Per Core v5.3, Vol 4, E, 7.5.4. Valid RSSI is represent in 1-byte with the range:
597 /// BR/EDR: -128 to 127
598 /// LE: -127 to 20, 127
599 /// Set 127 as invalid value also aligns with bluez.
600 pub const INVALID_RSSI: i8 = 127;
601
602 /// Wherever names are sent in bindings::bt_property_t, the size of the character
603 /// arrays are 256. Keep one extra byte for null termination.
604 const PROPERTY_NAME_MAX: usize = 255;
605
606 impl BluetoothProperty {
get_type(&self) -> BtPropertyType607 pub fn get_type(&self) -> BtPropertyType {
608 match &*self {
609 BluetoothProperty::BdName(_) => BtPropertyType::BdName,
610 BluetoothProperty::BdAddr(_) => BtPropertyType::BdAddr,
611 BluetoothProperty::Uuids(_) => BtPropertyType::Uuids,
612 BluetoothProperty::ClassOfDevice(_) => BtPropertyType::ClassOfDevice,
613 BluetoothProperty::TypeOfDevice(_) => BtPropertyType::TypeOfDevice,
614 BluetoothProperty::ServiceRecord(_) => BtPropertyType::ServiceRecord,
615 BluetoothProperty::AdapterScanMode(_) => BtPropertyType::AdapterScanMode,
616 BluetoothProperty::AdapterBondedDevices(_) => BtPropertyType::AdapterBondedDevices,
617 BluetoothProperty::AdapterDiscoverableTimeout(_) => {
618 BtPropertyType::AdapterDiscoverableTimeout
619 }
620 BluetoothProperty::RemoteFriendlyName(_) => BtPropertyType::RemoteFriendlyName,
621 BluetoothProperty::RemoteRssi(_) => BtPropertyType::RemoteRssi,
622 BluetoothProperty::RemoteVersionInfo(_) => BtPropertyType::RemoteVersionInfo,
623 BluetoothProperty::LocalLeFeatures(_) => BtPropertyType::LocalLeFeatures,
624 BluetoothProperty::LocalIoCaps(_) => BtPropertyType::LocalIoCaps,
625 BluetoothProperty::LocalIoCapsBle(_) => BtPropertyType::LocalIoCapsBle,
626 BluetoothProperty::DynamicAudioBuffer() => BtPropertyType::DynamicAudioBuffer,
627 BluetoothProperty::RemoteIsCoordinatedSetMember(_) => {
628 BtPropertyType::RemoteIsCoordinatedSetMember
629 }
630 BluetoothProperty::Appearance(_) => BtPropertyType::Appearance,
631 BluetoothProperty::VendorProductInfo(_) => BtPropertyType::VendorProductInfo,
632 BluetoothProperty::RemoteDeviceTimestamp() => BtPropertyType::RemoteDeviceTimestamp,
633 BluetoothProperty::RemoteAddrType(_) => BtPropertyType::RemoteAddrType,
634 BluetoothProperty::Unknown() => BtPropertyType::Unknown,
635 }
636 }
637
get_len(&self) -> usize638 fn get_len(&self) -> usize {
639 match &*self {
640 BluetoothProperty::BdName(name) => cmp::min(PROPERTY_NAME_MAX, name.len() + 1),
641 BluetoothProperty::BdAddr(addr) => addr.address.len(),
642 BluetoothProperty::Uuids(uulist) => uulist.len() * mem::size_of::<Uuid>(),
643 BluetoothProperty::ClassOfDevice(_) => mem::size_of::<u32>(),
644 BluetoothProperty::TypeOfDevice(_) => mem::size_of::<BtDeviceType>(),
645 BluetoothProperty::ServiceRecord(rec) => {
646 mem::size_of::<BtServiceRecord>() + cmp::min(PROPERTY_NAME_MAX, rec.name.len() + 1)
647 }
648 BluetoothProperty::AdapterScanMode(_) => mem::size_of::<BtScanMode>(),
649 BluetoothProperty::AdapterBondedDevices(devlist) => {
650 devlist.len() * mem::size_of::<RawAddress>()
651 }
652 BluetoothProperty::AdapterDiscoverableTimeout(_) => mem::size_of::<u32>(),
653 BluetoothProperty::RemoteFriendlyName(name) => {
654 cmp::min(PROPERTY_NAME_MAX, name.len() + 1)
655 }
656 BluetoothProperty::RemoteRssi(_) => mem::size_of::<i8>(),
657 BluetoothProperty::RemoteVersionInfo(_) => mem::size_of::<BtRemoteVersion>(),
658 BluetoothProperty::LocalLeFeatures(_) => mem::size_of::<BtLocalLeFeatures>(),
659 BluetoothProperty::LocalIoCaps(_) => mem::size_of::<BtIoCap>(),
660 BluetoothProperty::LocalIoCapsBle(_) => mem::size_of::<BtIoCap>(),
661 BluetoothProperty::RemoteIsCoordinatedSetMember(_) => mem::size_of::<bool>(),
662 BluetoothProperty::Appearance(_) => mem::size_of::<u16>(),
663 BluetoothProperty::VendorProductInfo(_) => mem::size_of::<BtVendorProductInfo>(),
664 BluetoothProperty::RemoteAddrType(_) => mem::size_of::<BtAddrType>(),
665
666 // TODO(abps) - Figure out sizes for these
667 BluetoothProperty::DynamicAudioBuffer() => 0,
668 BluetoothProperty::RemoteDeviceTimestamp() => 0,
669 BluetoothProperty::Unknown() => 0,
670 }
671 }
672
673 /// Given a mutable array, this will copy the data to that array and return a
674 /// LTCheckedPtrMut to it.
675 ///
676 /// 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>677 fn get_data_ptr<'a>(&'a self, data: &'a mut [u8]) -> LTCheckedPtrMut<'a, u8> {
678 let len = self.get_len();
679 match &*self {
680 BluetoothProperty::BdName(name) => {
681 let copy_len = len - 1;
682 data[0..copy_len].copy_from_slice(&name.as_bytes()[0..copy_len]);
683 data[copy_len] = 0;
684 }
685 BluetoothProperty::BdAddr(addr) => {
686 data.copy_from_slice(&addr.address);
687 }
688 BluetoothProperty::Uuids(uulist) => {
689 for (idx, &uuid) in uulist.iter().enumerate() {
690 let start = idx * mem::size_of::<Uuid>();
691 let end = start + mem::size_of::<Uuid>();
692 data[start..end].copy_from_slice(&uuid.uu);
693 }
694 }
695 BluetoothProperty::ClassOfDevice(cod) => {
696 data.copy_from_slice(&cod.to_ne_bytes());
697 }
698 BluetoothProperty::TypeOfDevice(tod) => {
699 data.copy_from_slice(&BtDeviceType::to_u32(tod).unwrap_or_default().to_ne_bytes());
700 }
701 BluetoothProperty::ServiceRecord(sr) => {
702 // Do an unsafe cast to binding:: type and assign the values
703 // The underlying memory location is provided by |data| which will
704 // have enough space because it uses get_len()
705 let record =
706 unsafe { &mut *(data.as_mut_ptr() as *mut bindings::bt_service_record_t) };
707 record.uuid = sr.uuid;
708 record.channel = sr.channel;
709 let name_len = len - mem::size_of::<BtServiceRecord>() - 1;
710 record.name[0..name_len].copy_from_slice(
711 &(sr.name.as_bytes().iter().map(|x| *x as c_char).collect::<Vec<c_char>>())
712 [0..name_len],
713 );
714 record.name[name_len] = 0;
715 }
716 BluetoothProperty::AdapterScanMode(sm) => {
717 data.copy_from_slice(&BtScanMode::to_u32(sm).unwrap_or_default().to_ne_bytes());
718 }
719 BluetoothProperty::AdapterBondedDevices(devlist) => {
720 for (idx, &dev) in devlist.iter().enumerate() {
721 let start = idx * mem::size_of::<RawAddress>();
722 let end = idx + mem::size_of::<RawAddress>();
723 data[start..end].copy_from_slice(&dev.address);
724 }
725 }
726 BluetoothProperty::AdapterDiscoverableTimeout(timeout) => {
727 data.copy_from_slice(&timeout.to_ne_bytes());
728 }
729 BluetoothProperty::RemoteFriendlyName(name) => {
730 let copy_len = len - 1;
731 data[0..copy_len].copy_from_slice(&name.as_bytes()[0..copy_len]);
732 data[copy_len] = 0;
733 }
734 BluetoothProperty::RemoteRssi(rssi) => {
735 data[0] = *rssi as u8;
736 }
737 BluetoothProperty::RemoteVersionInfo(rvi) => {
738 let ptr: *const BtRemoteVersion = rvi;
739 let slice = unsafe {
740 std::slice::from_raw_parts(ptr as *mut u8, mem::size_of::<BtRemoteVersion>())
741 };
742 data.copy_from_slice(&slice);
743 }
744 BluetoothProperty::LocalLeFeatures(llf) => {
745 let ptr: *const BtLocalLeFeatures = llf;
746 let slice = unsafe {
747 std::slice::from_raw_parts(ptr as *mut u8, mem::size_of::<BtLocalLeFeatures>())
748 };
749 data.copy_from_slice(&slice);
750 }
751 BluetoothProperty::LocalIoCaps(iocap) => {
752 data.copy_from_slice(&BtIoCap::to_u32(iocap).unwrap_or_default().to_ne_bytes());
753 }
754 BluetoothProperty::LocalIoCapsBle(iocap) => {
755 data.copy_from_slice(&BtIoCap::to_u32(iocap).unwrap_or_default().to_ne_bytes());
756 }
757 BluetoothProperty::RemoteIsCoordinatedSetMember(icsm) => {
758 data[0] = *icsm as u8;
759 }
760 BluetoothProperty::Appearance(appearance) => {
761 data.copy_from_slice(&appearance.to_ne_bytes());
762 }
763 BluetoothProperty::VendorProductInfo(vpi) => {
764 let ptr: *const BtVendorProductInfo = vpi;
765 let slice = unsafe {
766 std::slice::from_raw_parts(
767 ptr as *mut u8,
768 mem::size_of::<BtVendorProductInfo>(),
769 )
770 };
771 data.copy_from_slice(&slice);
772 }
773 BluetoothProperty::RemoteAddrType(addr_type) => {
774 data.copy_from_slice(
775 &BtAddrType::to_u32(addr_type).unwrap_or_default().to_ne_bytes(),
776 );
777 }
778
779 BluetoothProperty::DynamicAudioBuffer() => (),
780 BluetoothProperty::RemoteDeviceTimestamp() => (),
781 BluetoothProperty::Unknown() => (),
782 };
783
784 data.into()
785 }
786 }
787
788 // TODO(abps) - Check that sizes are correct when given a BtProperty
789 impl From<bindings::bt_property_t> for BluetoothProperty {
from(prop: bindings::bt_property_t) -> Self790 fn from(prop: bindings::bt_property_t) -> Self {
791 let slice: &[u8] =
792 unsafe { std::slice::from_raw_parts(prop.val as *mut u8, prop.len as usize) };
793 let len = prop.len as usize;
794
795 match BtPropertyType::from(prop.type_) {
796 BtPropertyType::BdName => BluetoothProperty::BdName(ascii_to_string(slice, len)),
797 BtPropertyType::BdAddr => {
798 BluetoothProperty::BdAddr(RawAddress::from_bytes(slice).unwrap_or_default())
799 }
800 BtPropertyType::Uuids => {
801 let count = len / mem::size_of::<Uuid>();
802 BluetoothProperty::Uuids(ptr_to_vec(prop.val as *const Uuid, count))
803 }
804 BtPropertyType::ClassOfDevice => {
805 BluetoothProperty::ClassOfDevice(u32_from_bytes(slice))
806 }
807 BtPropertyType::TypeOfDevice => BluetoothProperty::TypeOfDevice(
808 BtDeviceType::from_u32(u32_from_bytes(slice)).unwrap_or(BtDeviceType::Unknown),
809 ),
810 BtPropertyType::ServiceRecord => {
811 let v =
812 unsafe { (prop.val as *const bindings::bt_service_record_t).read_unaligned() };
813 BluetoothProperty::ServiceRecord(BtServiceRecord::from(v))
814 }
815 BtPropertyType::AdapterScanMode => BluetoothProperty::AdapterScanMode(
816 BtScanMode::from_u32(u32_from_bytes(slice)).unwrap_or(BtScanMode::None_),
817 ),
818 BtPropertyType::AdapterBondedDevices => {
819 let count = len / mem::size_of::<RawAddress>();
820 BluetoothProperty::AdapterBondedDevices(ptr_to_vec(
821 prop.val as *const RawAddress,
822 count,
823 ))
824 }
825 BtPropertyType::AdapterDiscoverableTimeout => {
826 BluetoothProperty::AdapterDiscoverableTimeout(u32_from_bytes(slice))
827 }
828 BtPropertyType::RemoteFriendlyName => {
829 BluetoothProperty::RemoteFriendlyName(ascii_to_string(slice, len))
830 }
831 BtPropertyType::RemoteRssi => BluetoothProperty::RemoteRssi(slice[0] as i8),
832 BtPropertyType::RemoteVersionInfo => {
833 let v = unsafe { (prop.val as *const BtRemoteVersion).read_unaligned() };
834 BluetoothProperty::RemoteVersionInfo(v.clone())
835 }
836 BtPropertyType::LocalLeFeatures => {
837 let v = unsafe { (prop.val as *const BtLocalLeFeatures).read_unaligned() };
838 BluetoothProperty::LocalLeFeatures(v.clone())
839 }
840 BtPropertyType::LocalIoCaps => BluetoothProperty::LocalIoCaps(
841 BtIoCap::from_u32(u32_from_bytes(slice)).unwrap_or(BtIoCap::Unknown),
842 ),
843 BtPropertyType::LocalIoCapsBle => BluetoothProperty::LocalIoCapsBle(
844 BtIoCap::from_u32(u32_from_bytes(slice)).unwrap_or(BtIoCap::Unknown),
845 ),
846 BtPropertyType::RemoteIsCoordinatedSetMember => {
847 BluetoothProperty::RemoteIsCoordinatedSetMember(slice[0] != 0)
848 }
849 BtPropertyType::Appearance => BluetoothProperty::Appearance(u16_from_bytes(slice)),
850 BtPropertyType::VendorProductInfo => {
851 let v = unsafe { (prop.val as *const BtVendorProductInfo).read_unaligned() };
852 BluetoothProperty::VendorProductInfo(BtVendorProductInfo::from(v))
853 }
854 BtPropertyType::RemoteAddrType => BluetoothProperty::RemoteAddrType(
855 BtAddrType::from_u32(u32_from_bytes(slice)).unwrap_or(BtAddrType::Unknown),
856 ),
857 // TODO(abps) - Figure out if these values should actually have contents
858 BtPropertyType::DynamicAudioBuffer => BluetoothProperty::DynamicAudioBuffer(),
859 BtPropertyType::RemoteDeviceTimestamp => BluetoothProperty::RemoteDeviceTimestamp(),
860 _ => BluetoothProperty::Unknown(),
861 }
862 }
863 }
864
865 impl From<BluetoothProperty> for (Box<[u8]>, bindings::bt_property_t) {
from(prop: BluetoothProperty) -> Self866 fn from(prop: BluetoothProperty) -> Self {
867 let dvec: Vec<u8> = vec![0; prop.get_len()];
868 let mut data: Box<[u8]> = dvec.into_boxed_slice();
869 let prop = bindings::bt_property_t {
870 type_: prop.get_type().into(),
871 len: prop.get_len() as i32,
872 val: prop.get_data_ptr(&mut data).cast_into::<std::os::raw::c_void>(),
873 };
874
875 (data, prop)
876 }
877 }
878
879 pub enum SupportedProfiles {
880 HidHost,
881 Hfp,
882 A2dp,
883 Gatt,
884 Sdp,
885 Socket,
886 HfClient,
887 AvrcpCtrl,
888 LeAudio,
889 VolumeControl,
890 CoordinatedSet,
891 }
892
893 impl From<SupportedProfiles> for Vec<u8> {
from(item: SupportedProfiles) -> Self894 fn from(item: SupportedProfiles) -> Self {
895 match item {
896 SupportedProfiles::HidHost => "hidhost",
897 SupportedProfiles::Hfp => "handsfree",
898 SupportedProfiles::A2dp => "a2dp",
899 SupportedProfiles::Gatt => "gatt",
900 SupportedProfiles::Sdp => "sdp",
901 SupportedProfiles::Socket => "socket",
902 SupportedProfiles::HfClient => "handsfree_client",
903 SupportedProfiles::AvrcpCtrl => "avrcp_ctrl",
904 SupportedProfiles::LeAudio => "le_audio",
905 SupportedProfiles::VolumeControl => "volume_control",
906 SupportedProfiles::CoordinatedSet => "csis_client",
907 }
908 .bytes()
909 .chain("\0".bytes())
910 .collect::<Vec<u8>>()
911 }
912 }
913
914 #[cxx::bridge(namespace = bluetooth::topshim::rust)]
915 mod ffi {
916 unsafe extern "C++" {
917 include!("btif/btif_shim.h");
918
919 // For converting init flags from Vec<String> to const char **
920 type InitFlags;
921
922 // Convert flgas into an InitFlags object
ConvertFlags(flags: Vec<String>) -> UniquePtr<InitFlags>923 fn ConvertFlags(flags: Vec<String>) -> UniquePtr<InitFlags>;
GetFlagsPtr(self: &InitFlags) -> *mut *const c_char924 fn GetFlagsPtr(self: &InitFlags) -> *mut *const c_char;
925 }
926 }
927
928 /// Generate impl cxx::ExternType for RawAddress and Uuid.
929 ///
930 /// To make use of RawAddress and Uuid in cxx::bridge C++ blocks,
931 /// include the following snippet in the ffi module.
932 /// ```ignore
933 /// #[cxx::bridge(namespace = bluetooth::topshim::rust)]
934 /// mod ffi {
935 /// unsafe extern "C++" {
936 /// include!("types/raw_address.h");
937 /// include!("types/bluetooth/uuid.h");
938 ///
939 /// #[namespace = ""]
940 /// type RawAddress = crate::btif::RawAddress;
941 ///
942 /// #[namespace = "bluetooth"]
943 /// type Uuid = crate::btif::Uuid;
944 /// }
945 /// // Place you shared stuff here.
946 /// }
947 /// ```
948 #[gen_cxx_extern_trivial]
949 pub type RawAddress = bindings::RawAddress;
950 #[gen_cxx_extern_trivial]
951 pub type Uuid = bindings::bluetooth::Uuid;
952
953 impl Hash for RawAddress {
hash<H: Hasher>(&self, state: &mut H)954 fn hash<H: Hasher>(&self, state: &mut H) {
955 self.address.hash(state);
956 }
957 }
958
959 impl ToString for RawAddress {
to_string(&self) -> String960 fn to_string(&self) -> String {
961 format!(
962 "{:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X}",
963 self.address[0],
964 self.address[1],
965 self.address[2],
966 self.address[3],
967 self.address[4],
968 self.address[5]
969 )
970 }
971 }
972
973 impl RawAddress {
974 /// Constructs a RawAddress from a slice of 6 bytes.
from_bytes(raw_addr: &[u8]) -> Option<RawAddress>975 pub fn from_bytes(raw_addr: &[u8]) -> Option<RawAddress> {
976 if raw_addr.len() != 6 {
977 return None;
978 }
979 let mut raw: [u8; 6] = [0; 6];
980 raw.copy_from_slice(raw_addr);
981 return Some(RawAddress { address: raw });
982 }
983
from_string<S: Into<String>>(addr: S) -> Option<RawAddress>984 pub fn from_string<S: Into<String>>(addr: S) -> Option<RawAddress> {
985 let addr: String = addr.into();
986 let s = addr.split(':').collect::<Vec<&str>>();
987
988 if s.len() != 6 {
989 return None;
990 }
991
992 let mut raw: [u8; 6] = [0; 6];
993 for i in 0..s.len() {
994 raw[i] = match u8::from_str_radix(s[i], 16) {
995 Ok(res) => res,
996 Err(_) => {
997 return None;
998 }
999 };
1000 }
1001
1002 Some(RawAddress { address: raw })
1003 }
1004
to_byte_arr(&self) -> [u8; 6]1005 pub fn to_byte_arr(&self) -> [u8; 6] {
1006 self.address.clone()
1007 }
1008
empty() -> RawAddress1009 pub fn empty() -> RawAddress {
1010 unsafe { bindings::RawAddress_kEmpty }
1011 }
1012 }
1013
1014 /// Address that is safe to display in logs.
1015 pub struct DisplayAddress<'a>(pub &'a RawAddress);
1016 impl<'a> Display for DisplayAddress<'a> {
fmt(&self, f: &mut Formatter) -> Result1017 fn fmt(&self, f: &mut Formatter) -> Result {
1018 if self.0.address.iter().all(|&x| x == 0x00) {
1019 write!(f, "00:00:00:00:00:00")
1020 } else if self.0.address.iter().all(|&x| x == 0xff) {
1021 write!(f, "ff:ff:ff:ff:ff:ff")
1022 } else {
1023 write!(f, "xx:xx:xx:xx:{:02x}:{:02x}", &self.0.address[4], &self.0.address[5])
1024 }
1025 }
1026 }
1027
1028 pub type OobData = bindings::bt_oob_data_s;
1029
1030 /// An enum representing `bt_callbacks_t` from btif.
1031 #[derive(Clone, Debug)]
1032 pub enum BaseCallbacks {
1033 AdapterState(BtState),
1034 AdapterProperties(BtStatus, i32, Vec<BluetoothProperty>),
1035 RemoteDeviceProperties(BtStatus, RawAddress, i32, Vec<BluetoothProperty>),
1036 DeviceFound(i32, Vec<BluetoothProperty>),
1037 DiscoveryState(BtDiscoveryState),
1038 PinRequest(RawAddress, String, u32, bool),
1039 SspRequest(RawAddress, BtSspVariant, u32),
1040 BondState(BtStatus, RawAddress, BtBondState, i32),
1041 AddressConsolidate(RawAddress, RawAddress),
1042 LeAddressAssociate(RawAddress, RawAddress),
1043 AclState(
1044 BtStatus,
1045 RawAddress,
1046 BtAclState,
1047 BtTransport,
1048 BtHciErrorCode,
1049 BtConnectionDirection,
1050 u16,
1051 ),
1052 ThreadEvent(BtThreadEvent),
1053 // Unimplemented so far:
1054 // dut_mode_recv_cb
1055 // le_test_mode_cb
1056 // energy_info_cb
1057 // link_quality_report_cb
1058 // switch_buffer_size_cb
1059 // switch_codec_cb
1060 GenerateLocalOobData(u8, OobData),
1061 LeRandCallback(u64),
1062 // key_missing_cb
1063 }
1064
1065 pub struct BaseCallbacksDispatcher {
1066 pub dispatch: Box<dyn Fn(BaseCallbacks) + Send>,
1067 }
1068
1069 type BaseCb = Arc<Mutex<BaseCallbacksDispatcher>>;
1070
1071 cb_variant!(BaseCb, adapter_state_cb -> BaseCallbacks::AdapterState, u32 -> BtState);
1072 cb_variant!(BaseCb, adapter_properties_cb -> BaseCallbacks::AdapterProperties,
1073 u32 -> BtStatus, i32, *mut bindings::bt_property_t, {
1074 let _2 = ptr_to_vec(_2, _1 as usize);
1075 });
1076 cb_variant!(BaseCb, remote_device_properties_cb -> BaseCallbacks::RemoteDeviceProperties,
1077 u32 -> BtStatus, *mut RawAddress -> RawAddress, i32, *mut bindings::bt_property_t, {
1078 let _1 = unsafe { *(_1 as *const RawAddress) };
1079 let _3 = ptr_to_vec(_3, _2 as usize);
1080 });
1081 cb_variant!(BaseCb, device_found_cb -> BaseCallbacks::DeviceFound,
1082 i32, *mut bindings::bt_property_t, {
1083 let _1 = ptr_to_vec(_1, _0 as usize);
1084 });
1085 cb_variant!(BaseCb, discovery_state_cb -> BaseCallbacks::DiscoveryState,
1086 bindings::bt_discovery_state_t -> BtDiscoveryState);
1087 cb_variant!(BaseCb, pin_request_cb -> BaseCallbacks::PinRequest,
1088 *mut RawAddress, *mut bindings::bt_bdname_t, u32, bool, {
1089 let _0 = unsafe { *(_0 as *const RawAddress)};
1090 let _1 = String::from(unsafe{*_1});
1091 });
1092 cb_variant!(BaseCb, ssp_request_cb -> BaseCallbacks::SspRequest,
1093 *mut RawAddress, bindings::bt_ssp_variant_t -> BtSspVariant, u32, {
1094 let _0 = unsafe { *(_0 as *const RawAddress) };
1095 });
1096 cb_variant!(BaseCb, bond_state_cb -> BaseCallbacks::BondState,
1097 u32 -> BtStatus, *mut RawAddress, bindings::bt_bond_state_t -> BtBondState, i32, {
1098 let _1 = unsafe { *(_1 as *const RawAddress) };
1099 });
1100
1101 cb_variant!(BaseCb, address_consolidate_cb -> BaseCallbacks::AddressConsolidate,
1102 *mut RawAddress, *mut RawAddress, {
1103 let _0 = unsafe { *(_0 as *const RawAddress) };
1104 let _1 = unsafe { *(_1 as *const RawAddress) };
1105 });
1106
1107 cb_variant!(BaseCb, le_address_associate_cb -> BaseCallbacks::LeAddressAssociate,
1108 *mut RawAddress, *mut RawAddress, {
1109 let _0 = unsafe { *(_0 as *const RawAddress) };
1110 let _1 = unsafe { *(_1 as *const RawAddress) };
1111 });
1112
1113 cb_variant!(BaseCb, thread_evt_cb -> BaseCallbacks::ThreadEvent, u32 -> BtThreadEvent);
1114
1115 cb_variant!(BaseCb, acl_state_cb -> BaseCallbacks::AclState,
1116 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, {
1117 let _1 = unsafe { *(_1 as *const RawAddress) };
1118 });
1119
1120 cb_variant!(BaseCb, generate_local_oob_data_cb -> BaseCallbacks::GenerateLocalOobData, u8, OobData);
1121
1122 cb_variant!(BaseCb, le_rand_cb -> BaseCallbacks::LeRandCallback, u64);
1123
1124 struct RawInterfaceWrapper {
1125 pub raw: *const bindings::bt_interface_t,
1126 }
1127
1128 unsafe impl Send for RawInterfaceWrapper {}
1129
1130 /// Macro to call functions via function pointers. Expects the self object to
1131 /// have a raw interface wrapper at `self.internal`. The actual function call is
1132 /// marked unsafe since it will need to dereference a C object. This can cause
1133 /// segfaults if not validated beforehand.
1134 ///
1135 /// Example:
1136 /// ccall!(self, foobar, arg1, arg2)
1137 /// Expands to: unsafe {((*self.internal.raw).foobar.unwrap())(arg1, arg2)}
1138 #[macro_export]
1139 macro_rules! ccall {
1140 ($self:ident,$fn_name:ident) => {
1141 unsafe {
1142 ((*$self.internal.raw).$fn_name.unwrap())()
1143 }
1144 };
1145 ($self:ident,$fn_name:ident, $($args:expr),*) => {
1146 unsafe {
1147 ((*$self.internal.raw).$fn_name.unwrap())($($args),*)
1148 }
1149 };
1150 }
1151
1152 /// Macro to call const functions via cxx. Expects the self object to have the
1153 /// cxx object to be called at `self.internal_cxx`.
1154 ///
1155 /// Example:
1156 /// cxxcall!(self, foobar, arg1, arg2)
1157 /// Expands to: self.internal_cxx.foobar(arg1, arg2)
1158 #[macro_export]
1159 macro_rules! cxxcall {
1160 ($self:expr,$fn_name:ident) => {
1161 $self.internal_cxx.$fn_name()
1162 };
1163 ($self:expr,$fn_name:ident, $($args:expr),*) => {
1164 $self.internal_cxx.$fn_name($($args),*)
1165 };
1166 }
1167
1168 /// Macro to call mutable functions via cxx. Mutable functions are always
1169 /// required to be defined with `self: Pin<&mut Self>`. The self object must
1170 /// have the cxx object at `self.internal_cxx`.
1171 ///
1172 /// Example:
1173 /// mutcxxcall!(self, foobar, arg1, arg2)
1174 /// Expands to: self.internal_cxx.pin_mut().foobar(arg1, arg2)
1175 #[macro_export]
1176 macro_rules! mutcxxcall {
1177 ($self:expr,$fn_name:ident) => {
1178 $self.internal_cxx.pin_mut().$fn_name()
1179 };
1180 ($self:expr,$fn_name:ident, $($args:expr),*) => {
1181 $self.internal_cxx.pin_mut().$fn_name($($args),*)
1182 };
1183 }
1184
1185 #[no_mangle]
wake_lock_noop(_0: *const ::std::os::raw::c_char) -> ::std::os::raw::c_int1186 extern "C" fn wake_lock_noop(_0: *const ::std::os::raw::c_char) -> ::std::os::raw::c_int {
1187 // The wakelock mechanism is not available on this platform,
1188 // so just returning success to avoid error log.
1189 0
1190 }
1191
1192 /// Rust wrapper around `bt_interface_t`.
1193 pub struct BluetoothInterface {
1194 internal: RawInterfaceWrapper,
1195
1196 /// Set to true after `initialize` is called.
1197 pub is_init: bool,
1198
1199 // Need to take ownership of callbacks so it doesn't get freed after init
1200 callbacks: Option<Box<bindings::bt_callbacks_t>>,
1201 os_callouts: Option<Box<bindings::bt_os_callouts_t>>,
1202 }
1203
1204 impl BluetoothInterface {
is_initialized(&self) -> bool1205 pub fn is_initialized(&self) -> bool {
1206 self.is_init
1207 }
1208
1209 /// Initialize the Bluetooth interface by setting up the underlying interface.
1210 ///
1211 /// # Arguments
1212 ///
1213 /// * `callbacks` - Dispatcher struct that accepts [`BaseCallbacks`]
1214 /// * `init_flags` - List of flags sent to libbluetooth for init.
initialize( &mut self, callbacks: BaseCallbacksDispatcher, init_flags: Vec<String>, ) -> bool1215 pub fn initialize(
1216 &mut self,
1217 callbacks: BaseCallbacksDispatcher,
1218 init_flags: Vec<String>,
1219 ) -> bool {
1220 // Init flags need to be converted from string to null terminated bytes
1221 let converted: cxx::UniquePtr<ffi::InitFlags> = ffi::ConvertFlags(init_flags);
1222 let flags = (*converted).GetFlagsPtr();
1223
1224 if get_dispatchers().lock().unwrap().set::<BaseCb>(Arc::new(Mutex::new(callbacks))) {
1225 panic!("Tried to set dispatcher for BaseCallbacks but it already existed");
1226 }
1227
1228 // Fill up callbacks struct to pass to init function (will be copied so
1229 // no need to worry about ownership)
1230 let mut callbacks = Box::new(bindings::bt_callbacks_t {
1231 size: std::mem::size_of::<bindings::bt_callbacks_t>(),
1232 adapter_state_changed_cb: Some(adapter_state_cb),
1233 adapter_properties_cb: Some(adapter_properties_cb),
1234 remote_device_properties_cb: Some(remote_device_properties_cb),
1235 device_found_cb: Some(device_found_cb),
1236 discovery_state_changed_cb: Some(discovery_state_cb),
1237 pin_request_cb: Some(pin_request_cb),
1238 ssp_request_cb: Some(ssp_request_cb),
1239 bond_state_changed_cb: Some(bond_state_cb),
1240 address_consolidate_cb: Some(address_consolidate_cb),
1241 le_address_associate_cb: Some(le_address_associate_cb),
1242 acl_state_changed_cb: Some(acl_state_cb),
1243 thread_evt_cb: Some(thread_evt_cb),
1244 dut_mode_recv_cb: None,
1245 le_test_mode_cb: None,
1246 energy_info_cb: None,
1247 link_quality_report_cb: None,
1248 generate_local_oob_data_cb: Some(generate_local_oob_data_cb),
1249 switch_buffer_size_cb: None,
1250 switch_codec_cb: None,
1251 le_rand_cb: Some(le_rand_cb),
1252 key_missing_cb: None,
1253 });
1254
1255 let cb_ptr = LTCheckedPtrMut::from(&mut callbacks);
1256
1257 let (guest_mode, is_common_criteria_mode, config_compare_result, is_atv) =
1258 (false, false, 0, false);
1259
1260 let init = ccall!(
1261 self,
1262 init,
1263 cb_ptr.into(),
1264 guest_mode,
1265 is_common_criteria_mode,
1266 config_compare_result,
1267 flags,
1268 is_atv,
1269 std::ptr::null()
1270 );
1271
1272 self.is_init = init == 0;
1273 self.callbacks = Some(callbacks);
1274
1275 if self.is_init {
1276 // Fill up OSI function table and register it with BTIF.
1277 // TODO(b/271931441) - pass a NoOpOsCallouts structure from
1278 // gd/rust/linux/stack.
1279 let mut callouts = Box::new(bindings::bt_os_callouts_t {
1280 size: std::mem::size_of::<bindings::bt_os_callouts_t>(),
1281 acquire_wake_lock: Some(wake_lock_noop),
1282 release_wake_lock: Some(wake_lock_noop),
1283 });
1284 let callouts_ptr = LTCheckedPtrMut::from(&mut callouts);
1285 ccall!(self, set_os_callouts, callouts_ptr.into());
1286 self.os_callouts = Some(callouts);
1287 }
1288
1289 return self.is_init;
1290 }
1291
cleanup(&self)1292 pub fn cleanup(&self) {
1293 ccall!(self, cleanup)
1294 }
1295
enable(&self) -> i321296 pub fn enable(&self) -> i32 {
1297 ccall!(self, enable)
1298 }
1299
disable(&self) -> i321300 pub fn disable(&self) -> i32 {
1301 ccall!(self, disable)
1302 }
1303
get_adapter_properties(&self) -> i321304 pub fn get_adapter_properties(&self) -> i32 {
1305 ccall!(self, get_adapter_properties)
1306 }
1307
get_adapter_property(&self, prop: BtPropertyType) -> i321308 pub fn get_adapter_property(&self, prop: BtPropertyType) -> i32 {
1309 let converted_type = bindings::bt_property_type_t::from(prop);
1310 ccall!(self, get_adapter_property, converted_type)
1311 }
1312
set_adapter_property(&self, prop: BluetoothProperty) -> i321313 pub fn set_adapter_property(&self, prop: BluetoothProperty) -> i32 {
1314 let prop_pair: (Box<[u8]>, bindings::bt_property_t) = prop.into();
1315 let prop_ptr = LTCheckedPtr::from_ref(&prop_pair.1);
1316 ccall!(self, set_adapter_property, prop_ptr.into())
1317 }
1318
get_remote_device_properties(&self, addr: &mut RawAddress) -> i321319 pub fn get_remote_device_properties(&self, addr: &mut RawAddress) -> i32 {
1320 let addr_ptr = LTCheckedPtrMut::from_ref(addr);
1321 ccall!(self, get_remote_device_properties, addr_ptr.into())
1322 }
1323
get_remote_device_property( &self, addr: &mut RawAddress, prop_type: BtPropertyType, ) -> i321324 pub fn get_remote_device_property(
1325 &self,
1326 addr: &mut RawAddress,
1327 prop_type: BtPropertyType,
1328 ) -> i32 {
1329 let addr_ptr = LTCheckedPtrMut::from_ref(addr);
1330 let converted_type = bindings::bt_property_type_t::from(prop_type);
1331 ccall!(self, get_remote_device_property, addr_ptr.into(), converted_type)
1332 }
1333
set_remote_device_property( &self, addr: &mut RawAddress, prop: BluetoothProperty, ) -> i321334 pub fn set_remote_device_property(
1335 &self,
1336 addr: &mut RawAddress,
1337 prop: BluetoothProperty,
1338 ) -> i32 {
1339 let prop_pair: (Box<[u8]>, bindings::bt_property_t) = prop.into();
1340 let prop_ptr = LTCheckedPtr::from_ref(&prop_pair.1);
1341 let addr_ptr = LTCheckedPtrMut::from_ref(addr);
1342 ccall!(self, set_remote_device_property, addr_ptr.into(), prop_ptr.into())
1343 }
1344
get_remote_services(&self, addr: &mut RawAddress, transport: BtTransport) -> i321345 pub fn get_remote_services(&self, addr: &mut RawAddress, transport: BtTransport) -> i32 {
1346 let addr_ptr = LTCheckedPtrMut::from_ref(addr);
1347 ccall!(self, get_remote_services, addr_ptr.into(), transport.to_i32().unwrap())
1348 }
1349
start_discovery(&self) -> i321350 pub fn start_discovery(&self) -> i32 {
1351 ccall!(self, start_discovery)
1352 }
1353
cancel_discovery(&self) -> i321354 pub fn cancel_discovery(&self) -> i32 {
1355 ccall!(self, cancel_discovery)
1356 }
1357
pairing_is_busy(&self) -> bool1358 pub fn pairing_is_busy(&self) -> bool {
1359 ccall!(self, pairing_is_busy)
1360 }
1361
create_bond(&self, addr: &RawAddress, transport: BtTransport) -> i321362 pub fn create_bond(&self, addr: &RawAddress, transport: BtTransport) -> i32 {
1363 let ctransport: i32 = transport.into();
1364 let addr_ptr = LTCheckedPtr::from_ref(addr);
1365 ccall!(self, create_bond, addr_ptr.into(), ctransport)
1366 }
1367
remove_bond(&self, addr: &RawAddress) -> i321368 pub fn remove_bond(&self, addr: &RawAddress) -> i32 {
1369 let addr_ptr = LTCheckedPtr::from_ref(addr);
1370 ccall!(self, remove_bond, addr_ptr.into())
1371 }
1372
cancel_bond(&self, addr: &RawAddress) -> i321373 pub fn cancel_bond(&self, addr: &RawAddress) -> i32 {
1374 let addr_ptr = LTCheckedPtr::from_ref(addr);
1375 ccall!(self, cancel_bond, addr_ptr.into())
1376 }
1377
get_connection_state(&self, addr: &RawAddress) -> BtConnectionState1378 pub fn get_connection_state(&self, addr: &RawAddress) -> BtConnectionState {
1379 let addr_ptr = LTCheckedPtr::from_ref(addr);
1380 ccall!(self, get_connection_state, addr_ptr.into()).into()
1381 }
1382
pin_reply( &self, addr: &RawAddress, accept: u8, pin_len: u8, pin_code: &mut BtPinCode, ) -> i321383 pub fn pin_reply(
1384 &self,
1385 addr: &RawAddress,
1386 accept: u8,
1387 pin_len: u8,
1388 pin_code: &mut BtPinCode,
1389 ) -> i32 {
1390 let addr_ptr = LTCheckedPtr::from_ref(addr);
1391 let pin_code_ptr = LTCheckedPtrMut::from_ref(pin_code);
1392 ccall!(self, pin_reply, addr_ptr.into(), accept, pin_len, pin_code_ptr.into())
1393 }
1394
ssp_reply( &self, addr: &RawAddress, variant: BtSspVariant, accept: u8, passkey: u32, ) -> i321395 pub fn ssp_reply(
1396 &self,
1397 addr: &RawAddress,
1398 variant: BtSspVariant,
1399 accept: u8,
1400 passkey: u32,
1401 ) -> i32 {
1402 let addr_ptr = LTCheckedPtr::from_ref(addr);
1403 let cvariant = bindings::bt_ssp_variant_t::from(variant);
1404 ccall!(self, ssp_reply, addr_ptr.into(), cvariant, accept, passkey)
1405 }
1406
clear_event_filter(&self) -> i321407 pub fn clear_event_filter(&self) -> i32 {
1408 ccall!(self, clear_event_filter)
1409 }
1410
clear_event_mask(&self) -> i321411 pub fn clear_event_mask(&self) -> i32 {
1412 ccall!(self, clear_event_mask)
1413 }
1414
clear_filter_accept_list(&self) -> i321415 pub fn clear_filter_accept_list(&self) -> i32 {
1416 ccall!(self, clear_filter_accept_list)
1417 }
1418
disconnect_all_acls(&self) -> i321419 pub fn disconnect_all_acls(&self) -> i32 {
1420 ccall!(self, disconnect_all_acls)
1421 }
1422
allow_wake_by_hid(&self) -> i321423 pub fn allow_wake_by_hid(&self) -> i32 {
1424 ccall!(self, allow_wake_by_hid)
1425 }
1426
get_wbs_supported(&self) -> bool1427 pub fn get_wbs_supported(&self) -> bool {
1428 ccall!(self, get_wbs_supported)
1429 }
1430
get_swb_supported(&self) -> bool1431 pub fn get_swb_supported(&self) -> bool {
1432 ccall!(self, get_swb_supported)
1433 }
1434
is_coding_format_supported(&self, coding_format: u8) -> bool1435 pub fn is_coding_format_supported(&self, coding_format: u8) -> bool {
1436 ccall!(self, is_coding_format_supported, coding_format)
1437 }
1438
le_rand(&self) -> i321439 pub fn le_rand(&self) -> i32 {
1440 ccall!(self, le_rand)
1441 }
1442
generate_local_oob_data(&self, transport: i32) -> i321443 pub fn generate_local_oob_data(&self, transport: i32) -> i32 {
1444 ccall!(self, generate_local_oob_data, transport as u8)
1445 }
1446
restore_filter_accept_list(&self) -> i321447 pub fn restore_filter_accept_list(&self) -> i32 {
1448 ccall!(self, restore_filter_accept_list)
1449 }
1450
set_default_event_mask_except(&self, mask: u64, le_mask: u64) -> i321451 pub fn set_default_event_mask_except(&self, mask: u64, le_mask: u64) -> i32 {
1452 ccall!(self, set_default_event_mask_except, mask, le_mask)
1453 }
1454
set_event_filter_inquiry_result_all_devices(&self) -> i321455 pub fn set_event_filter_inquiry_result_all_devices(&self) -> i32 {
1456 ccall!(self, set_event_filter_inquiry_result_all_devices)
1457 }
1458
set_event_filter_connection_setup_all_devices(&self) -> i321459 pub fn set_event_filter_connection_setup_all_devices(&self) -> i32 {
1460 ccall!(self, set_event_filter_connection_setup_all_devices)
1461 }
1462
get_profile_interface( &self, profile: SupportedProfiles, ) -> *const std::os::raw::c_void1463 pub(crate) fn get_profile_interface(
1464 &self,
1465 profile: SupportedProfiles,
1466 ) -> *const std::os::raw::c_void {
1467 let cprofile = Vec::<u8>::from(profile);
1468 let cprofile_ptr = LTCheckedPtr::from(&cprofile);
1469 ccall!(self, get_profile_interface, cprofile_ptr.cast_into::<std::os::raw::c_char>())
1470 }
1471
as_raw_ptr(&self) -> *const u81472 pub(crate) fn as_raw_ptr(&self) -> *const u8 {
1473 self.internal.raw as *const u8
1474 }
1475
dump(&self, fd: RawFd)1476 pub fn dump(&self, fd: RawFd) {
1477 ccall!(self, dump, fd, std::ptr::null_mut())
1478 }
1479 }
1480
1481 pub trait ToggleableProfile {
is_enabled(&self) -> bool1482 fn is_enabled(&self) -> bool;
enable(&mut self) -> bool1483 fn enable(&mut self) -> bool;
disable(&mut self) -> bool1484 fn disable(&mut self) -> bool;
1485 }
1486
get_btinterface() -> Option<BluetoothInterface>1487 pub fn get_btinterface() -> Option<BluetoothInterface> {
1488 let mut ret: Option<BluetoothInterface> = None;
1489 let mut ifptr: *const bindings::bt_interface_t = std::ptr::null();
1490
1491 unsafe {
1492 if bindings::hal_util_load_bt_library(&mut ifptr) == 0 {
1493 ret = Some(BluetoothInterface {
1494 internal: RawInterfaceWrapper { raw: ifptr },
1495 is_init: false,
1496 callbacks: None,
1497 os_callouts: None,
1498 });
1499 }
1500 }
1501
1502 ret
1503 }
1504
1505 // Turns C-array T[] to Vec<U>.
ptr_to_vec<T: Copy, U: From<T>>(start: *const T, length: usize) -> Vec<U>1506 pub(crate) fn ptr_to_vec<T: Copy, U: From<T>>(start: *const T, length: usize) -> Vec<U> {
1507 unsafe {
1508 (0..length).map(|i| U::from(start.offset(i as isize).read_unaligned())).collect::<Vec<U>>()
1509 }
1510 }
1511
1512 #[cfg(test)]
1513 mod tests {
1514 use super::*;
1515
make_bdname_from_slice(slice: &[u8]) -> bindings::bt_bdname_t1516 fn make_bdname_from_slice(slice: &[u8]) -> bindings::bt_bdname_t {
1517 // Length of slice must be less than bd_name max
1518 assert!(slice.len() <= 249);
1519
1520 let mut bdname = bindings::bt_bdname_t { name: [128; 249] };
1521
1522 for (i, v) in slice.iter().enumerate() {
1523 bdname.name[i] = v.clone();
1524 }
1525
1526 bdname
1527 }
1528
1529 #[test]
test_bdname_conversions()1530 fn test_bdname_conversions() {
1531 let hello_bdname = make_bdname_from_slice(&[72, 69, 76, 76, 79, 0]);
1532 assert_eq!("HELLO".to_string(), String::from(hello_bdname));
1533
1534 let empty_bdname = make_bdname_from_slice(&[0]);
1535 assert_eq!("".to_string(), String::from(empty_bdname));
1536
1537 let no_nullterm_bdname = make_bdname_from_slice(&[72, 69, 76, 76, 79]);
1538 assert_eq!("".to_string(), String::from(no_nullterm_bdname));
1539
1540 let invalid_bdname = make_bdname_from_slice(&[128; 249]);
1541 assert_eq!("".to_string(), String::from(invalid_bdname));
1542 }
1543
1544 #[test]
test_ptr_to_vec()1545 fn test_ptr_to_vec() {
1546 let arr: [i32; 3] = [1, 2, 3];
1547 let vec: Vec<i32> = ptr_to_vec(arr.as_ptr(), arr.len());
1548 let expected: Vec<i32> = vec![1, 2, 3];
1549 assert_eq!(expected, vec);
1550 }
1551
1552 #[test]
test_property_with_string_conversions()1553 fn test_property_with_string_conversions() {
1554 {
1555 let bdname = BluetoothProperty::BdName("FooBar".into());
1556 let prop_pair: (Box<[u8]>, bindings::bt_property_t) = bdname.into();
1557 let converted: BluetoothProperty = prop_pair.1.into();
1558 assert!(match converted {
1559 BluetoothProperty::BdName(name) => "FooBar".to_string() == name,
1560 _ => false,
1561 });
1562 }
1563
1564 {
1565 let orig_record = BtServiceRecord {
1566 uuid: Uuid::from([0; 16]),
1567 channel: 3,
1568 name: "FooBar".to_string(),
1569 };
1570 let service_record = BluetoothProperty::ServiceRecord(orig_record.clone());
1571 let prop_pair: (Box<[u8]>, bindings::bt_property_t) = service_record.into();
1572 let converted: BluetoothProperty = prop_pair.1.into();
1573 assert!(match converted {
1574 BluetoothProperty::ServiceRecord(sr) => {
1575 sr.uuid == orig_record.uuid
1576 && sr.channel == orig_record.channel
1577 && sr.name == orig_record.name
1578 }
1579 _ => false,
1580 });
1581 }
1582
1583 {
1584 let rfname = BluetoothProperty::RemoteFriendlyName("FooBizz".into());
1585 let prop_pair: (Box<[u8]>, bindings::bt_property_t) = rfname.into();
1586 let converted: BluetoothProperty = prop_pair.1.into();
1587 assert!(match converted {
1588 BluetoothProperty::RemoteFriendlyName(name) => "FooBizz".to_string() == name,
1589 _ => false,
1590 });
1591 }
1592 }
1593
1594 #[test]
test_display_address()1595 fn test_display_address() {
1596 assert_eq!(
1597 format!("{}", DisplayAddress(&RawAddress::from_string("00:00:00:00:00:00").unwrap())),
1598 String::from("00:00:00:00:00:00")
1599 );
1600 assert_eq!(
1601 format!("{}", DisplayAddress(&RawAddress::from_string("ff:ff:ff:ff:ff:ff").unwrap())),
1602 String::from("ff:ff:ff:ff:ff:ff")
1603 );
1604 assert_eq!(
1605 format!("{}", DisplayAddress(&RawAddress::from_string("1a:2b:1a:2b:1a:2b").unwrap())),
1606 String::from("xx:xx:xx:xx:1a:2b")
1607 );
1608 assert_eq!(
1609 format!("{}", DisplayAddress(&RawAddress::from_string("3C:4D:3C:4D:3C:4D").unwrap())),
1610 String::from("xx:xx:xx:xx:3c:4d")
1611 );
1612 assert_eq!(
1613 format!("{}", DisplayAddress(&RawAddress::from_string("11:35:11:35:11:35").unwrap())),
1614 String::from("xx:xx:xx:xx:11:35")
1615 );
1616 }
1617
1618 #[test]
test_get_shortest_slice()1619 fn test_get_shortest_slice() {
1620 let uuid_16 = Uuid::from_string("0000fef3-0000-1000-8000-00805f9b34fb").unwrap();
1621 assert_eq!(uuid_16.get_shortest_slice(), [0xfe, 0xf3]);
1622
1623 let uuid_32 = Uuid::from_string("00112233-0000-1000-8000-00805f9b34fb").unwrap();
1624 assert_eq!(uuid_32.get_shortest_slice(), [0x00, 0x11, 0x22, 0x33]);
1625
1626 let uuid_128 = Uuid::from_string("00112233-4455-6677-8899-aabbccddeeff").unwrap();
1627 assert_eq!(
1628 uuid_128.get_shortest_slice(),
1629 [
1630 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd,
1631 0xee, 0xff
1632 ]
1633 );
1634 }
1635 }
1636