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 KeyMissing(RawAddress),
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 cb_variant!(BaseCb, key_missing_cb -> BaseCallbacks::KeyMissing, RawAddress);
1129
1130 struct RawInterfaceWrapper {
1131 pub raw: *const bindings::bt_interface_t,
1132 }
1133
1134 unsafe impl Send for RawInterfaceWrapper {}
1135
1136 /// Macro to call functions via function pointers. Expects the self object to
1137 /// have a raw interface wrapper at `self.internal`. The actual function call is
1138 /// marked unsafe since it will need to dereference a C object. This can cause
1139 /// segfaults if not validated beforehand.
1140 ///
1141 /// Example:
1142 /// ccall!(self, foobar, arg1, arg2)
1143 /// Expands to: unsafe {((*self.internal.raw).foobar.unwrap())(arg1, arg2)}
1144 #[macro_export]
1145 macro_rules! ccall {
1146 ($self:ident,$fn_name:ident) => {
1147 unsafe {
1148 ((*$self.internal.raw).$fn_name.unwrap())()
1149 }
1150 };
1151 ($self:ident,$fn_name:ident, $($args:expr),*) => {
1152 unsafe {
1153 ((*$self.internal.raw).$fn_name.unwrap())($($args),*)
1154 }
1155 };
1156 }
1157
1158 /// Macro to call const functions via cxx. Expects the self object to have the
1159 /// cxx object to be called at `self.internal_cxx`.
1160 ///
1161 /// Example:
1162 /// cxxcall!(self, foobar, arg1, arg2)
1163 /// Expands to: self.internal_cxx.foobar(arg1, arg2)
1164 #[macro_export]
1165 macro_rules! cxxcall {
1166 ($self:expr,$fn_name:ident) => {
1167 $self.internal_cxx.$fn_name()
1168 };
1169 ($self:expr,$fn_name:ident, $($args:expr),*) => {
1170 $self.internal_cxx.$fn_name($($args),*)
1171 };
1172 }
1173
1174 /// Macro to call mutable functions via cxx. Mutable functions are always
1175 /// required to be defined with `self: Pin<&mut Self>`. The self object must
1176 /// have the cxx object at `self.internal_cxx`.
1177 ///
1178 /// Example:
1179 /// mutcxxcall!(self, foobar, arg1, arg2)
1180 /// Expands to: self.internal_cxx.pin_mut().foobar(arg1, arg2)
1181 #[macro_export]
1182 macro_rules! mutcxxcall {
1183 ($self:expr,$fn_name:ident) => {
1184 $self.internal_cxx.pin_mut().$fn_name()
1185 };
1186 ($self:expr,$fn_name:ident, $($args:expr),*) => {
1187 $self.internal_cxx.pin_mut().$fn_name($($args),*)
1188 };
1189 }
1190
1191 #[no_mangle]
wake_lock_noop(_0: *const ::std::os::raw::c_char) -> ::std::os::raw::c_int1192 extern "C" fn wake_lock_noop(_0: *const ::std::os::raw::c_char) -> ::std::os::raw::c_int {
1193 // The wakelock mechanism is not available on this platform,
1194 // so just returning success to avoid error log.
1195 0
1196 }
1197
1198 /// Rust wrapper around `bt_interface_t`.
1199 pub struct BluetoothInterface {
1200 internal: RawInterfaceWrapper,
1201
1202 /// Set to true after `initialize` is called.
1203 pub is_init: bool,
1204
1205 // Need to take ownership of callbacks so it doesn't get freed after init
1206 callbacks: Option<Box<bindings::bt_callbacks_t>>,
1207 os_callouts: Option<Box<bindings::bt_os_callouts_t>>,
1208 }
1209
1210 impl BluetoothInterface {
is_initialized(&self) -> bool1211 pub fn is_initialized(&self) -> bool {
1212 self.is_init
1213 }
1214
1215 /// Initialize the Bluetooth interface by setting up the underlying interface.
1216 ///
1217 /// # Arguments
1218 ///
1219 /// * `callbacks` - Dispatcher struct that accepts [`BaseCallbacks`]
1220 /// * `hci_index` - Index of the hci adapter in use
initialize(&mut self, callbacks: BaseCallbacksDispatcher, hci_index: i32) -> bool1221 pub fn initialize(&mut self, callbacks: BaseCallbacksDispatcher, hci_index: i32) -> bool {
1222 if get_dispatchers().lock().unwrap().set::<BaseCb>(Arc::new(Mutex::new(callbacks))) {
1223 panic!("Tried to set dispatcher for BaseCallbacks but it already existed");
1224 }
1225
1226 // Fill up callbacks struct to pass to init function (will be copied so
1227 // no need to worry about ownership)
1228 let mut callbacks = Box::new(bindings::bt_callbacks_t {
1229 size: std::mem::size_of::<bindings::bt_callbacks_t>(),
1230 adapter_state_changed_cb: Some(adapter_state_cb),
1231 adapter_properties_cb: Some(adapter_properties_cb),
1232 remote_device_properties_cb: Some(remote_device_properties_cb),
1233 device_found_cb: Some(device_found_cb),
1234 discovery_state_changed_cb: Some(discovery_state_cb),
1235 pin_request_cb: Some(pin_request_cb),
1236 ssp_request_cb: Some(ssp_request_cb),
1237 bond_state_changed_cb: Some(bond_state_cb),
1238 address_consolidate_cb: Some(address_consolidate_cb),
1239 le_address_associate_cb: Some(le_address_associate_cb),
1240 acl_state_changed_cb: Some(acl_state_cb),
1241 thread_evt_cb: Some(thread_evt_cb),
1242 dut_mode_recv_cb: None,
1243 le_test_mode_cb: None,
1244 energy_info_cb: None,
1245 link_quality_report_cb: None,
1246 generate_local_oob_data_cb: Some(generate_local_oob_data_cb),
1247 switch_buffer_size_cb: None,
1248 switch_codec_cb: None,
1249 le_rand_cb: Some(le_rand_cb),
1250 key_missing_cb: Some(key_missing_cb),
1251 encryption_change_cb: None,
1252 });
1253
1254 let cb_ptr = LTCheckedPtrMut::from(&mut callbacks);
1255
1256 let (guest_mode, is_common_criteria_mode, config_compare_result, is_atv) =
1257 (false, false, 0, false);
1258
1259 ccall!(self, set_adapter_index, hci_index);
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 is_atv
1268 );
1269
1270 self.is_init = init == 0;
1271 self.callbacks = Some(callbacks);
1272
1273 if self.is_init {
1274 // Fill up OSI function table and register it with BTIF.
1275 // TODO(b/271931441) - pass a NoOpOsCallouts structure from
1276 // gd/rust/linux/stack.
1277 let mut callouts = Box::new(bindings::bt_os_callouts_t {
1278 size: std::mem::size_of::<bindings::bt_os_callouts_t>(),
1279 acquire_wake_lock: Some(wake_lock_noop),
1280 release_wake_lock: Some(wake_lock_noop),
1281 });
1282 let callouts_ptr = LTCheckedPtrMut::from(&mut callouts);
1283 ccall!(self, set_os_callouts, callouts_ptr.into());
1284 self.os_callouts = Some(callouts);
1285 }
1286
1287 return self.is_init;
1288 }
1289
cleanup(&self)1290 pub fn cleanup(&self) {
1291 ccall!(self, cleanup)
1292 }
1293
enable(&self) -> i321294 pub fn enable(&self) -> i32 {
1295 ccall!(self, enable)
1296 }
1297
disable(&self) -> i321298 pub fn disable(&self) -> i32 {
1299 ccall!(self, disable)
1300 }
1301
get_adapter_properties(&self) -> i321302 pub fn get_adapter_properties(&self) -> i32 {
1303 ccall!(self, get_adapter_properties)
1304 }
1305
get_adapter_property(&self, prop: BtPropertyType) -> i321306 pub fn get_adapter_property(&self, prop: BtPropertyType) -> i32 {
1307 let converted_type = bindings::bt_property_type_t::from(prop);
1308 ccall!(self, get_adapter_property, converted_type)
1309 }
1310
set_adapter_property(&self, prop: BluetoothProperty) -> i321311 pub fn set_adapter_property(&self, prop: BluetoothProperty) -> i32 {
1312 let prop_pair: (Box<[u8]>, bindings::bt_property_t) = prop.into();
1313 let prop_ptr = LTCheckedPtr::from_ref(&prop_pair.1);
1314 ccall!(self, set_adapter_property, prop_ptr.into())
1315 }
1316
set_scan_mode(&self, mode: BtScanMode)1317 pub fn set_scan_mode(&self, mode: BtScanMode) {
1318 ccall!(self, set_scan_mode, mode.into())
1319 }
1320
get_remote_device_properties(&self, addr: &mut RawAddress) -> i321321 pub fn get_remote_device_properties(&self, addr: &mut RawAddress) -> i32 {
1322 let addr_ptr = LTCheckedPtrMut::from_ref(addr);
1323 ccall!(self, get_remote_device_properties, addr_ptr.into())
1324 }
1325
get_remote_device_property( &self, addr: &mut RawAddress, prop_type: BtPropertyType, ) -> i321326 pub fn get_remote_device_property(
1327 &self,
1328 addr: &mut RawAddress,
1329 prop_type: BtPropertyType,
1330 ) -> i32 {
1331 let addr_ptr = LTCheckedPtrMut::from_ref(addr);
1332 let converted_type = bindings::bt_property_type_t::from(prop_type);
1333 ccall!(self, get_remote_device_property, addr_ptr.into(), converted_type)
1334 }
1335
set_remote_device_property( &self, addr: &mut RawAddress, prop: BluetoothProperty, ) -> i321336 pub fn set_remote_device_property(
1337 &self,
1338 addr: &mut RawAddress,
1339 prop: BluetoothProperty,
1340 ) -> i32 {
1341 let prop_pair: (Box<[u8]>, bindings::bt_property_t) = prop.into();
1342 let prop_ptr = LTCheckedPtr::from_ref(&prop_pair.1);
1343 let addr_ptr = LTCheckedPtrMut::from_ref(addr);
1344 ccall!(self, set_remote_device_property, addr_ptr.into(), prop_ptr.into())
1345 }
1346
get_remote_services(&self, addr: &mut RawAddress, transport: BtTransport) -> i321347 pub fn get_remote_services(&self, addr: &mut RawAddress, transport: BtTransport) -> i32 {
1348 let addr_ptr = LTCheckedPtrMut::from_ref(addr);
1349 ccall!(self, get_remote_services, addr_ptr.into(), transport.to_i32().unwrap())
1350 }
1351
start_discovery(&self) -> i321352 pub fn start_discovery(&self) -> i32 {
1353 ccall!(self, start_discovery)
1354 }
1355
cancel_discovery(&self) -> i321356 pub fn cancel_discovery(&self) -> i32 {
1357 ccall!(self, cancel_discovery)
1358 }
1359
pairing_is_busy(&self) -> bool1360 pub fn pairing_is_busy(&self) -> bool {
1361 ccall!(self, pairing_is_busy)
1362 }
1363
create_bond(&self, addr: &RawAddress, transport: BtTransport) -> i321364 pub fn create_bond(&self, addr: &RawAddress, transport: BtTransport) -> i32 {
1365 let ctransport: i32 = transport.into();
1366 let addr_ptr = LTCheckedPtr::from_ref(addr);
1367 ccall!(self, create_bond, addr_ptr.into(), ctransport)
1368 }
1369
remove_bond(&self, addr: &RawAddress) -> i321370 pub fn remove_bond(&self, addr: &RawAddress) -> i32 {
1371 let addr_ptr = LTCheckedPtr::from_ref(addr);
1372 ccall!(self, remove_bond, addr_ptr.into())
1373 }
1374
cancel_bond(&self, addr: &RawAddress) -> i321375 pub fn cancel_bond(&self, addr: &RawAddress) -> i32 {
1376 let addr_ptr = LTCheckedPtr::from_ref(addr);
1377 ccall!(self, cancel_bond, addr_ptr.into())
1378 }
1379
get_connection_state(&self, addr: &RawAddress) -> BtConnectionState1380 pub fn get_connection_state(&self, addr: &RawAddress) -> BtConnectionState {
1381 let addr_ptr = LTCheckedPtr::from_ref(addr);
1382 ccall!(self, get_connection_state, addr_ptr.into()).into()
1383 }
1384
pin_reply( &self, addr: &RawAddress, accept: u8, pin_len: u8, pin_code: &mut BtPinCode, ) -> i321385 pub fn pin_reply(
1386 &self,
1387 addr: &RawAddress,
1388 accept: u8,
1389 pin_len: u8,
1390 pin_code: &mut BtPinCode,
1391 ) -> i32 {
1392 let addr_ptr = LTCheckedPtr::from_ref(addr);
1393 let pin_code_ptr = LTCheckedPtrMut::from_ref(pin_code);
1394 ccall!(self, pin_reply, addr_ptr.into(), accept, pin_len, pin_code_ptr.into())
1395 }
1396
ssp_reply( &self, addr: &RawAddress, variant: BtSspVariant, accept: u8, passkey: u32, ) -> i321397 pub fn ssp_reply(
1398 &self,
1399 addr: &RawAddress,
1400 variant: BtSspVariant,
1401 accept: u8,
1402 passkey: u32,
1403 ) -> i32 {
1404 let addr_ptr = LTCheckedPtr::from_ref(addr);
1405 let cvariant = bindings::bt_ssp_variant_t::from(variant);
1406 ccall!(self, ssp_reply, addr_ptr.into(), cvariant, accept, passkey)
1407 }
1408
clear_event_filter(&self) -> i321409 pub fn clear_event_filter(&self) -> i32 {
1410 ccall!(self, clear_event_filter)
1411 }
1412
clear_event_mask(&self) -> i321413 pub fn clear_event_mask(&self) -> i32 {
1414 ccall!(self, clear_event_mask)
1415 }
1416
clear_filter_accept_list(&self) -> i321417 pub fn clear_filter_accept_list(&self) -> i32 {
1418 ccall!(self, clear_filter_accept_list)
1419 }
1420
disconnect_all_acls(&self) -> i321421 pub fn disconnect_all_acls(&self) -> i32 {
1422 ccall!(self, disconnect_all_acls)
1423 }
1424
allow_wake_by_hid(&self) -> i321425 pub fn allow_wake_by_hid(&self) -> i32 {
1426 ccall!(self, allow_wake_by_hid)
1427 }
1428
get_wbs_supported(&self) -> bool1429 pub fn get_wbs_supported(&self) -> bool {
1430 ccall!(self, get_wbs_supported)
1431 }
1432
get_swb_supported(&self) -> bool1433 pub fn get_swb_supported(&self) -> bool {
1434 ccall!(self, get_swb_supported)
1435 }
1436
is_coding_format_supported(&self, coding_format: u8) -> bool1437 pub fn is_coding_format_supported(&self, coding_format: u8) -> bool {
1438 ccall!(self, is_coding_format_supported, coding_format)
1439 }
1440
le_rand(&self) -> i321441 pub fn le_rand(&self) -> i32 {
1442 ccall!(self, le_rand)
1443 }
1444
generate_local_oob_data(&self, transport: i32) -> i321445 pub fn generate_local_oob_data(&self, transport: i32) -> i32 {
1446 ccall!(self, generate_local_oob_data, transport as u8)
1447 }
1448
restore_filter_accept_list(&self) -> i321449 pub fn restore_filter_accept_list(&self) -> i32 {
1450 ccall!(self, restore_filter_accept_list)
1451 }
1452
set_default_event_mask_except(&self, mask: u64, le_mask: u64) -> i321453 pub fn set_default_event_mask_except(&self, mask: u64, le_mask: u64) -> i32 {
1454 ccall!(self, set_default_event_mask_except, mask, le_mask)
1455 }
1456
set_event_filter_inquiry_result_all_devices(&self) -> i321457 pub fn set_event_filter_inquiry_result_all_devices(&self) -> i32 {
1458 ccall!(self, set_event_filter_inquiry_result_all_devices)
1459 }
1460
set_event_filter_connection_setup_all_devices(&self) -> i321461 pub fn set_event_filter_connection_setup_all_devices(&self) -> i32 {
1462 ccall!(self, set_event_filter_connection_setup_all_devices)
1463 }
1464
get_profile_interface( &self, profile: SupportedProfiles, ) -> *const std::os::raw::c_void1465 pub(crate) fn get_profile_interface(
1466 &self,
1467 profile: SupportedProfiles,
1468 ) -> *const std::os::raw::c_void {
1469 let cprofile = Vec::<u8>::from(profile);
1470 let cprofile_ptr = LTCheckedPtr::from(&cprofile);
1471 ccall!(self, get_profile_interface, cprofile_ptr.cast_into::<std::os::raw::c_char>())
1472 }
1473
as_raw_ptr(&self) -> *const u81474 pub(crate) fn as_raw_ptr(&self) -> *const u8 {
1475 self.internal.raw as *const u8
1476 }
1477
dump(&self, fd: RawFd)1478 pub fn dump(&self, fd: RawFd) {
1479 ccall!(self, dump, fd, std::ptr::null_mut())
1480 }
1481 }
1482
1483 impl Debug for BluetoothInterface {
fmt(&self, f: &mut Formatter<'_>) -> Result1484 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
1485 write!(f, "BluetoothInterface {{ is_init: {:?} }}", self.is_init)
1486 }
1487 }
1488
1489 pub trait ToggleableProfile {
is_enabled(&self) -> bool1490 fn is_enabled(&self) -> bool;
enable(&mut self) -> bool1491 fn enable(&mut self) -> bool;
disable(&mut self) -> bool1492 fn disable(&mut self) -> bool;
1493 }
1494
get_btinterface() -> BluetoothInterface1495 pub fn get_btinterface() -> BluetoothInterface {
1496 let mut ifptr: *const bindings::bt_interface_t = std::ptr::null();
1497
1498 if unsafe { bindings::hal_util_load_bt_library(&mut ifptr) } == 0 {
1499 BluetoothInterface {
1500 internal: RawInterfaceWrapper { raw: ifptr },
1501 is_init: false,
1502 callbacks: None,
1503 os_callouts: None,
1504 }
1505 } else {
1506 panic!("Failed to get BluetoothInterface");
1507 }
1508 }
1509
1510 // Turns C-array T[] to Vec<U>.
ptr_to_vec<T: Copy, U: From<T>>(start: *const T, length: usize) -> Vec<U>1511 pub(crate) fn ptr_to_vec<T: Copy, U: From<T>>(start: *const T, length: usize) -> Vec<U> {
1512 unsafe {
1513 (0..length).map(|i| U::from(start.offset(i as isize).read_unaligned())).collect::<Vec<U>>()
1514 }
1515 }
1516
1517 #[cfg(test)]
1518 mod tests {
1519 use super::*;
1520
make_bdname_from_slice(slice: &[u8]) -> bindings::bt_bdname_t1521 fn make_bdname_from_slice(slice: &[u8]) -> bindings::bt_bdname_t {
1522 // Length of slice must be less than bd_name max
1523 assert!(slice.len() <= 249);
1524
1525 let mut bdname = bindings::bt_bdname_t { name: [128; 249] };
1526
1527 for (i, v) in slice.iter().enumerate() {
1528 bdname.name[i] = v.clone();
1529 }
1530
1531 bdname
1532 }
1533
1534 #[test]
test_bdname_conversions()1535 fn test_bdname_conversions() {
1536 let hello_bdname = make_bdname_from_slice(&[72, 69, 76, 76, 79, 0]);
1537 assert_eq!("HELLO".to_string(), String::from(hello_bdname));
1538
1539 let empty_bdname = make_bdname_from_slice(&[0]);
1540 assert_eq!("".to_string(), String::from(empty_bdname));
1541
1542 let no_nullterm_bdname = make_bdname_from_slice(&[72, 69, 76, 76, 79]);
1543 assert_eq!("".to_string(), String::from(no_nullterm_bdname));
1544
1545 let invalid_bdname = make_bdname_from_slice(&[128; 249]);
1546 assert_eq!("".to_string(), String::from(invalid_bdname));
1547 }
1548
1549 #[test]
test_ptr_to_vec()1550 fn test_ptr_to_vec() {
1551 let arr: [i32; 3] = [1, 2, 3];
1552 let vec: Vec<i32> = ptr_to_vec(arr.as_ptr(), arr.len());
1553 let expected: Vec<i32> = vec![1, 2, 3];
1554 assert_eq!(expected, vec);
1555 }
1556
1557 #[test]
test_property_with_string_conversions()1558 fn test_property_with_string_conversions() {
1559 {
1560 let bdname = BluetoothProperty::BdName("FooBar".into());
1561 let prop_pair: (Box<[u8]>, bindings::bt_property_t) = bdname.into();
1562 let converted: BluetoothProperty = prop_pair.1.into();
1563 assert!(match converted {
1564 BluetoothProperty::BdName(name) => "FooBar".to_string() == name,
1565 _ => false,
1566 });
1567 }
1568
1569 {
1570 let orig_record = BtServiceRecord {
1571 uuid: Uuid::from([0; 16]),
1572 channel: 3,
1573 name: "FooBar".to_string(),
1574 };
1575 let service_record = BluetoothProperty::ServiceRecord(orig_record.clone());
1576 let prop_pair: (Box<[u8]>, bindings::bt_property_t) = service_record.into();
1577 let converted: BluetoothProperty = prop_pair.1.into();
1578 assert!(match converted {
1579 BluetoothProperty::ServiceRecord(sr) => {
1580 sr.uuid == orig_record.uuid
1581 && sr.channel == orig_record.channel
1582 && sr.name == orig_record.name
1583 }
1584 _ => false,
1585 });
1586 }
1587
1588 {
1589 let rfname = BluetoothProperty::RemoteFriendlyName("FooBizz".into());
1590 let prop_pair: (Box<[u8]>, bindings::bt_property_t) = rfname.into();
1591 let converted: BluetoothProperty = prop_pair.1.into();
1592 assert!(match converted {
1593 BluetoothProperty::RemoteFriendlyName(name) => "FooBizz".to_string() == name,
1594 _ => false,
1595 });
1596 }
1597 }
1598
1599 #[test]
test_display_address()1600 fn test_display_address() {
1601 assert_eq!(
1602 format!("{}", DisplayAddress(&RawAddress::from_string("00:00:00:00:00:00").unwrap())),
1603 String::from("00:00:00:00:00:00")
1604 );
1605 assert_eq!(
1606 format!("{}", DisplayAddress(&RawAddress::from_string("ff:ff:ff:ff:ff:ff").unwrap())),
1607 String::from("ff:ff:ff:ff:ff:ff")
1608 );
1609 assert_eq!(
1610 format!("{}", DisplayAddress(&RawAddress::from_string("1a:2b:1a:2b:1a:2b").unwrap())),
1611 String::from("xx:xx:xx:xx:1a:2b")
1612 );
1613 assert_eq!(
1614 format!("{}", DisplayAddress(&RawAddress::from_string("3C:4D:3C:4D:3C:4D").unwrap())),
1615 String::from("xx:xx:xx:xx:3c:4d")
1616 );
1617 assert_eq!(
1618 format!("{}", DisplayAddress(&RawAddress::from_string("11:35:11:35:11:35").unwrap())),
1619 String::from("xx:xx:xx:xx:11:35")
1620 );
1621 }
1622
1623 #[test]
test_get_shortest_slice()1624 fn test_get_shortest_slice() {
1625 let uuid_16 = Uuid::from_string("0000fef3-0000-1000-8000-00805f9b34fb").unwrap();
1626 assert_eq!(uuid_16.get_shortest_slice(), [0xfe, 0xf3]);
1627
1628 let uuid_32 = Uuid::from_string("00112233-0000-1000-8000-00805f9b34fb").unwrap();
1629 assert_eq!(uuid_32.get_shortest_slice(), [0x00, 0x11, 0x22, 0x33]);
1630
1631 let uuid_128 = Uuid::from_string("00112233-4455-6677-8899-aabbccddeeff").unwrap();
1632 assert_eq!(
1633 uuid_128.get_shortest_slice(),
1634 [
1635 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd,
1636 0xee, 0xff
1637 ]
1638 );
1639 }
1640 }
1641