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