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