1 use crate::btif::{BluetoothInterface, BtStatus, RawAddress, ToggleableProfile};
2 use crate::topstack::get_dispatchers;
3
4 use bitflags::bitflags;
5 use num_derive::{FromPrimitive, ToPrimitive};
6 use num_traits::cast::FromPrimitive;
7 use std::convert::{TryFrom, TryInto};
8 use std::fmt::{Debug, Formatter};
9 use std::sync::{Arc, Mutex};
10 use topshim_macros::{cb_variant, log_args, profile_enabled_or};
11
12 use log::warn;
13
14 #[derive(Debug, FromPrimitive, ToPrimitive, PartialEq, PartialOrd, Clone)]
15 #[repr(u8)]
16 pub enum HfpCodecId {
17 NONE = 0x00,
18 CVSD = 0x01,
19 MSBC = 0x02,
20 LC3 = 0x03,
21 }
22
23 #[derive(Debug, FromPrimitive, ToPrimitive, PartialEq, PartialOrd, Clone)]
24 #[repr(u8)]
25 pub enum EscoCodingFormat {
26 ULAW = 0x00,
27 ALAW = 0x01,
28 CVSD = 0x02,
29 TRANSPARENT = 0x03,
30 LINEAR = 0x04,
31 MSBC = 0x05,
32 LC3 = 0x06,
33 G729A = 0x07,
34 VENDOR = 0xff,
35 }
36
37 impl From<u8> for EscoCodingFormat {
from(item: u8) -> Self38 fn from(item: u8) -> Self {
39 EscoCodingFormat::from_u8(item).unwrap()
40 }
41 }
42
43 impl From<EscoCodingFormat> for u8 {
from(item: EscoCodingFormat) -> Self44 fn from(item: EscoCodingFormat) -> Self {
45 item as u8
46 }
47 }
48
49 #[derive(Debug, FromPrimitive, ToPrimitive, PartialEq, PartialOrd, Clone)]
50 #[repr(u32)]
51 pub enum BthfConnectionState {
52 Disconnected = 0,
53 Connecting,
54 Connected,
55 SlcConnected,
56 Disconnecting,
57 }
58
59 impl From<u32> for BthfConnectionState {
from(item: u32) -> Self60 fn from(item: u32) -> Self {
61 BthfConnectionState::from_u32(item).unwrap()
62 }
63 }
64
65 #[derive(Debug, FromPrimitive, PartialEq, PartialOrd, Clone)]
66 #[repr(u32)]
67 pub enum BthfAudioState {
68 Disconnected = 0,
69 Connecting,
70 Connected,
71 Disconnecting,
72 }
73
74 impl From<u32> for BthfAudioState {
from(item: u32) -> Self75 fn from(item: u32) -> Self {
76 BthfAudioState::from_u32(item).unwrap()
77 }
78 }
79
80 // This is used for codec-negotiation related methods that do not
81 // concern with the coding format. Do not confuse this with |HfpCodecFormat|.
82 bitflags! {
83 #[derive(Clone, Debug, Default)]
84 pub struct HfpCodecBitId: i32 {
85 const NONE = 0b000;
86 const CVSD = 0b001;
87 const MSBC = 0b010;
88 const LC3 = 0b100;
89 }
90 }
91
92 impl TryInto<u8> for HfpCodecBitId {
93 type Error = ();
try_into(self) -> Result<u8, Self::Error>94 fn try_into(self) -> Result<u8, Self::Error> {
95 Ok(self.bits().try_into().unwrap())
96 }
97 }
98
99 impl TryInto<i32> for HfpCodecBitId {
100 type Error = ();
try_into(self) -> Result<i32, Self::Error>101 fn try_into(self) -> Result<i32, Self::Error> {
102 Ok(self.bits())
103 }
104 }
105
106 impl TryFrom<i32> for HfpCodecBitId {
107 type Error = ();
try_from(val: i32) -> Result<Self, Self::Error>108 fn try_from(val: i32) -> Result<Self, Self::Error> {
109 Self::from_bits(val).ok_or(())
110 }
111 }
112
113 bitflags! {
114 #[derive(Clone, Copy, Debug, Default, PartialEq)]
115 pub struct HfpCodecFormat: i32 {
116 const NONE = 0b0000;
117 const CVSD = 0b0001;
118 const MSBC_TRANSPARENT = 0b0010;
119 const MSBC = 0b0100;
120 const LC3_TRANSPARENT = 0b1000;
121 }
122 }
123
124 impl TryInto<i32> for HfpCodecFormat {
125 type Error = ();
try_into(self) -> Result<i32, Self::Error>126 fn try_into(self) -> Result<i32, Self::Error> {
127 Ok(self.bits())
128 }
129 }
130
131 impl TryFrom<i32> for HfpCodecFormat {
132 type Error = ();
try_from(val: i32) -> Result<Self, Self::Error>133 fn try_from(val: i32) -> Result<Self, Self::Error> {
134 Self::from_bits(val).ok_or(())
135 }
136 }
137
138 #[cxx::bridge(namespace = bluetooth::topshim::rust)]
139 pub mod ffi {
140 unsafe extern "C++" {
141 include!("types/raw_address.h");
142 #[namespace = ""]
143 type RawAddress = crate::btif::RawAddress;
144 }
145
146 #[derive(Debug, Copy, Clone)]
147 pub struct TelephonyDeviceStatus {
148 network_available: bool,
149 roaming: bool,
150 signal_strength: i32,
151 battery_level: i32,
152 }
153
154 #[derive(Debug, Copy, Clone)]
155 pub enum CallState {
156 Idle,
157 Incoming,
158 Dialing,
159 Alerting,
160 Active, // Only used by CLCC response
161 Held, // Only used by CLCC response
162 }
163
164 #[derive(Debug, Clone)]
165 pub struct CallInfo {
166 index: i32,
167 dir_incoming: bool,
168 state: CallState,
169 number: String,
170 }
171
172 #[derive(Debug, Copy, Clone)]
173 pub struct PhoneState {
174 num_active: i32,
175 num_held: i32,
176 state: CallState,
177 }
178
179 #[derive(Debug, Copy, Clone)]
180 pub enum CallHoldCommand {
181 ReleaseHeld,
182 ReleaseActiveAcceptHeld,
183 HoldActiveAcceptHeld,
184 // We don't support it in our telephony stack because it's not necessary for qualification.
185 // But still inform the stack about this event.
186 AddHeldToConf,
187 }
188
189 unsafe extern "C++" {
190 include!("hfp/hfp_shim.h");
191
192 type HfpIntf;
193
GetHfpProfile(btif: *const u8) -> UniquePtr<HfpIntf>194 unsafe fn GetHfpProfile(btif: *const u8) -> UniquePtr<HfpIntf>;
interop_insert_call_when_sco_start(bt_addr: RawAddress) -> bool195 unsafe fn interop_insert_call_when_sco_start(bt_addr: RawAddress) -> bool;
interop_disable_hf_profile(name: *const c_char) -> bool196 unsafe fn interop_disable_hf_profile(name: *const c_char) -> bool;
init(self: Pin<&mut HfpIntf>) -> i32197 fn init(self: Pin<&mut HfpIntf>) -> i32;
connect(self: Pin<&mut HfpIntf>, bt_addr: RawAddress) -> u32198 fn connect(self: Pin<&mut HfpIntf>, bt_addr: RawAddress) -> u32;
connect_audio( self: Pin<&mut HfpIntf>, bt_addr: RawAddress, sco_offload: bool, disabled_codecs: i32, ) -> i32199 fn connect_audio(
200 self: Pin<&mut HfpIntf>,
201 bt_addr: RawAddress,
202 sco_offload: bool,
203 disabled_codecs: i32,
204 ) -> i32;
set_active_device(self: Pin<&mut HfpIntf>, bt_addr: RawAddress) -> i32205 fn set_active_device(self: Pin<&mut HfpIntf>, bt_addr: RawAddress) -> i32;
set_volume(self: Pin<&mut HfpIntf>, volume: i8, bt_addr: RawAddress) -> i32206 fn set_volume(self: Pin<&mut HfpIntf>, volume: i8, bt_addr: RawAddress) -> i32;
set_mic_volume(self: Pin<&mut HfpIntf>, volume: i8, bt_addr: RawAddress) -> u32207 fn set_mic_volume(self: Pin<&mut HfpIntf>, volume: i8, bt_addr: RawAddress) -> u32;
disconnect(self: Pin<&mut HfpIntf>, bt_addr: RawAddress) -> u32208 fn disconnect(self: Pin<&mut HfpIntf>, bt_addr: RawAddress) -> u32;
disconnect_audio(self: Pin<&mut HfpIntf>, bt_addr: RawAddress) -> i32209 fn disconnect_audio(self: Pin<&mut HfpIntf>, bt_addr: RawAddress) -> i32;
device_status_notification( self: Pin<&mut HfpIntf>, status: TelephonyDeviceStatus, addr: RawAddress, ) -> u32210 fn device_status_notification(
211 self: Pin<&mut HfpIntf>,
212 status: TelephonyDeviceStatus,
213 addr: RawAddress,
214 ) -> u32;
indicator_query_response( self: Pin<&mut HfpIntf>, device_status: TelephonyDeviceStatus, phone_state: PhoneState, addr: RawAddress, ) -> u32215 fn indicator_query_response(
216 self: Pin<&mut HfpIntf>,
217 device_status: TelephonyDeviceStatus,
218 phone_state: PhoneState,
219 addr: RawAddress,
220 ) -> u32;
current_calls_query_response( self: Pin<&mut HfpIntf>, call_list: &Vec<CallInfo>, addr: RawAddress, ) -> u32221 fn current_calls_query_response(
222 self: Pin<&mut HfpIntf>,
223 call_list: &Vec<CallInfo>,
224 addr: RawAddress,
225 ) -> u32;
phone_state_change( self: Pin<&mut HfpIntf>, phone_state: PhoneState, number: &String, addr: RawAddress, ) -> u32226 fn phone_state_change(
227 self: Pin<&mut HfpIntf>,
228 phone_state: PhoneState,
229 number: &String,
230 addr: RawAddress,
231 ) -> u32;
simple_at_response(self: Pin<&mut HfpIntf>, ok: bool, addr: RawAddress) -> u32232 fn simple_at_response(self: Pin<&mut HfpIntf>, ok: bool, addr: RawAddress) -> u32;
debug_dump(self: Pin<&mut HfpIntf>)233 fn debug_dump(self: Pin<&mut HfpIntf>);
cleanup(self: Pin<&mut HfpIntf>)234 fn cleanup(self: Pin<&mut HfpIntf>);
235
236 }
237 extern "Rust" {
hfp_connection_state_callback(state: u32, addr: RawAddress)238 fn hfp_connection_state_callback(state: u32, addr: RawAddress);
hfp_audio_state_callback(state: u32, addr: RawAddress)239 fn hfp_audio_state_callback(state: u32, addr: RawAddress);
hfp_volume_update_callback(volume: u8, addr: RawAddress)240 fn hfp_volume_update_callback(volume: u8, addr: RawAddress);
hfp_mic_volume_update_callback(volume: u8, addr: RawAddress)241 fn hfp_mic_volume_update_callback(volume: u8, addr: RawAddress);
hfp_vendor_specific_at_command_callback(at_string: String, addr: RawAddress)242 fn hfp_vendor_specific_at_command_callback(at_string: String, addr: RawAddress);
hfp_battery_level_update_callback(battery_level: u8, addr: RawAddress)243 fn hfp_battery_level_update_callback(battery_level: u8, addr: RawAddress);
hfp_wbs_caps_update_callback(wbs_supported: bool, addr: RawAddress)244 fn hfp_wbs_caps_update_callback(wbs_supported: bool, addr: RawAddress);
hfp_swb_caps_update_callback(swb_supported: bool, addr: RawAddress)245 fn hfp_swb_caps_update_callback(swb_supported: bool, addr: RawAddress);
hfp_indicator_query_callback(addr: RawAddress)246 fn hfp_indicator_query_callback(addr: RawAddress);
hfp_current_calls_query_callback(addr: RawAddress)247 fn hfp_current_calls_query_callback(addr: RawAddress);
hfp_answer_call_callback(addr: RawAddress)248 fn hfp_answer_call_callback(addr: RawAddress);
hfp_hangup_call_callback(addr: RawAddress)249 fn hfp_hangup_call_callback(addr: RawAddress);
hfp_dial_call_callback(number: String, addr: RawAddress)250 fn hfp_dial_call_callback(number: String, addr: RawAddress);
hfp_call_hold_callback(chld: CallHoldCommand, addr: RawAddress)251 fn hfp_call_hold_callback(chld: CallHoldCommand, addr: RawAddress);
hfp_debug_dump_callback( active: bool, codec_id: u16, total_num_decoded_frames: i32, pkt_loss_ratio: f64, begin_ts: u64, end_ts: u64, pkt_status_in_hex: String, pkt_status_in_binary: String, )252 fn hfp_debug_dump_callback(
253 active: bool,
254 codec_id: u16,
255 total_num_decoded_frames: i32,
256 pkt_loss_ratio: f64,
257 begin_ts: u64,
258 end_ts: u64,
259 pkt_status_in_hex: String,
260 pkt_status_in_binary: String,
261 );
262 }
263 }
264
interop_insert_call_when_sco_start(bt_addr: RawAddress) -> bool265 pub fn interop_insert_call_when_sco_start(bt_addr: RawAddress) -> bool {
266 //Call an unsafe function in c++. This is necessary for bridge C++ interop API with floss(rust).
267 unsafe { return ffi::interop_insert_call_when_sco_start(bt_addr) }
268 }
269
interop_disable_hf_profile(name: String) -> bool270 pub fn interop_disable_hf_profile(name: String) -> bool {
271 let c_name = std::ffi::CString::new(name).unwrap();
272 // Call an unsafe function in c++. This is necessary for bridge C++ interop API with floss(rust).
273 unsafe { return ffi::interop_disable_hf_profile(c_name.as_ptr()) }
274 }
275
276 pub type TelephonyDeviceStatus = ffi::TelephonyDeviceStatus;
277
278 impl TelephonyDeviceStatus {
new() -> Self279 pub fn new() -> Self {
280 TelephonyDeviceStatus {
281 network_available: true,
282 roaming: false,
283 signal_strength: 5,
284 battery_level: 5,
285 }
286 }
287 }
288
289 pub type CallState = ffi::CallState;
290 pub type CallInfo = ffi::CallInfo;
291 pub type PhoneState = ffi::PhoneState;
292 pub type CallHoldCommand = ffi::CallHoldCommand;
293
294 // CallState (non-primitive) cannot be directly cast to u8.
295 impl From<CallState> for u8 {
from(state: CallState) -> u8296 fn from(state: CallState) -> u8 {
297 match state {
298 CallState::Idle => 0,
299 CallState::Incoming => 1,
300 CallState::Dialing => 2,
301 CallState::Alerting => 3,
302 CallState::Active => 4,
303 CallState::Held => 5,
304 CallState { repr: 6_u8..=u8::MAX } => todo!(),
305 }
306 }
307 }
308
309 #[derive(Clone, Debug)]
310 pub enum HfpCallbacks {
311 ConnectionState(BthfConnectionState, RawAddress),
312 AudioState(BthfAudioState, RawAddress),
313 VolumeUpdate(u8, RawAddress),
314 MicVolumeUpdate(u8, RawAddress),
315 VendorSpecificAtCommand(String, RawAddress),
316 BatteryLevelUpdate(u8, RawAddress),
317 WbsCapsUpdate(bool, RawAddress),
318 SwbCapsUpdate(bool, RawAddress),
319 IndicatorQuery(RawAddress),
320 CurrentCallsQuery(RawAddress),
321 AnswerCall(RawAddress),
322 HangupCall(RawAddress),
323 DialCall(String, RawAddress),
324 CallHold(CallHoldCommand, RawAddress),
325 DebugDump(bool, u16, i32, f64, u64, u64, String, String),
326 }
327
328 pub struct HfpCallbacksDispatcher {
329 pub dispatch: Box<dyn Fn(HfpCallbacks) + Send>,
330 }
331
332 impl Debug for HfpCallbacksDispatcher {
fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error>333 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
334 write!(f, "HfpCallbacksDispatcher {{}}")
335 }
336 }
337
338 type HfpCb = Arc<Mutex<HfpCallbacksDispatcher>>;
339
340 cb_variant!(
341 HfpCb,
342 hfp_connection_state_callback -> HfpCallbacks::ConnectionState,
343 u32 -> BthfConnectionState, RawAddress);
344
345 cb_variant!(
346 HfpCb,
347 hfp_audio_state_callback -> HfpCallbacks::AudioState,
348 u32 -> BthfAudioState, RawAddress);
349
350 cb_variant!(
351 HfpCb,
352 hfp_volume_update_callback -> HfpCallbacks::VolumeUpdate,
353 u8, RawAddress);
354
355 cb_variant!(
356 HfpCb,
357 hfp_mic_volume_update_callback -> HfpCallbacks::MicVolumeUpdate,
358 u8, RawAddress);
359
360 cb_variant!(
361 HfpCb,
362 hfp_vendor_specific_at_command_callback -> HfpCallbacks::VendorSpecificAtCommand,
363 String, RawAddress);
364
365 cb_variant!(
366 HfpCb,
367 hfp_battery_level_update_callback -> HfpCallbacks::BatteryLevelUpdate,
368 u8, RawAddress);
369
370 cb_variant!(
371 HfpCb,
372 hfp_wbs_caps_update_callback -> HfpCallbacks::WbsCapsUpdate,
373 bool, RawAddress);
374
375 cb_variant!(
376 HfpCb,
377 hfp_swb_caps_update_callback -> HfpCallbacks::SwbCapsUpdate,
378 bool, RawAddress);
379
380 cb_variant!(
381 HfpCb,
382 hfp_indicator_query_callback -> HfpCallbacks::IndicatorQuery,
383 RawAddress);
384
385 cb_variant!(
386 HfpCb,
387 hfp_current_calls_query_callback -> HfpCallbacks::CurrentCallsQuery,
388 RawAddress);
389
390 cb_variant!(
391 HfpCb,
392 hfp_answer_call_callback -> HfpCallbacks::AnswerCall,
393 RawAddress);
394
395 cb_variant!(
396 HfpCb,
397 hfp_hangup_call_callback -> HfpCallbacks::HangupCall,
398 RawAddress);
399
400 cb_variant!(
401 HfpCb,
402 hfp_dial_call_callback -> HfpCallbacks::DialCall,
403 String, RawAddress);
404
405 cb_variant!(
406 HfpCb,
407 hfp_call_hold_callback -> HfpCallbacks::CallHold,
408 CallHoldCommand, RawAddress);
409
410 cb_variant!(
411 HfpCb,
412 hfp_debug_dump_callback -> HfpCallbacks::DebugDump,
413 bool, u16, i32, f64, u64, u64, String, String);
414
415 pub struct Hfp {
416 internal: cxx::UniquePtr<ffi::HfpIntf>,
417 _is_init: bool,
418 _is_enabled: bool,
419 }
420
421 // For *const u8 opaque btif
422 unsafe impl Send for Hfp {}
423
424 impl ToggleableProfile for Hfp {
is_enabled(&self) -> bool425 fn is_enabled(&self) -> bool {
426 self._is_enabled
427 }
428
enable(&mut self) -> bool429 fn enable(&mut self) -> bool {
430 self.internal.pin_mut().init();
431 self._is_enabled = true;
432 true
433 }
434
435 #[profile_enabled_or(false)]
disable(&mut self) -> bool436 fn disable(&mut self) -> bool {
437 self.internal.pin_mut().cleanup();
438 self._is_enabled = false;
439 true
440 }
441 }
442
443 impl Hfp {
444 #[log_args]
new(intf: &BluetoothInterface) -> Hfp445 pub fn new(intf: &BluetoothInterface) -> Hfp {
446 let hfpif: cxx::UniquePtr<ffi::HfpIntf>;
447 unsafe {
448 hfpif = ffi::GetHfpProfile(intf.as_raw_ptr());
449 }
450
451 Hfp { internal: hfpif, _is_init: false, _is_enabled: false }
452 }
453
454 #[log_args]
is_initialized(&self) -> bool455 pub fn is_initialized(&self) -> bool {
456 self._is_init
457 }
458
459 #[log_args]
initialize(&mut self, callbacks: HfpCallbacksDispatcher) -> bool460 pub fn initialize(&mut self, callbacks: HfpCallbacksDispatcher) -> bool {
461 if get_dispatchers().lock().unwrap().set::<HfpCb>(Arc::new(Mutex::new(callbacks))) {
462 panic!("Tried to set dispatcher for HFP callbacks while it already exists");
463 }
464 self._is_init = true;
465 true
466 }
467
468 #[log_args]
469 #[profile_enabled_or(BtStatus::NotReady)]
connect(&mut self, addr: RawAddress) -> BtStatus470 pub fn connect(&mut self, addr: RawAddress) -> BtStatus {
471 BtStatus::from(self.internal.pin_mut().connect(addr))
472 }
473
474 #[log_args]
475 #[profile_enabled_or(BtStatus::NotReady.into())]
connect_audio( &mut self, addr: RawAddress, sco_offload: bool, disabled_codecs: i32, ) -> i32476 pub fn connect_audio(
477 &mut self,
478 addr: RawAddress,
479 sco_offload: bool,
480 disabled_codecs: i32,
481 ) -> i32 {
482 self.internal.pin_mut().connect_audio(addr, sco_offload, disabled_codecs)
483 }
484
485 #[log_args]
486 #[profile_enabled_or(BtStatus::NotReady.into())]
set_active_device(&mut self, addr: RawAddress) -> i32487 pub fn set_active_device(&mut self, addr: RawAddress) -> i32 {
488 self.internal.pin_mut().set_active_device(addr)
489 }
490
491 #[log_args]
492 #[profile_enabled_or(BtStatus::NotReady.into())]
set_volume(&mut self, volume: i8, addr: RawAddress) -> i32493 pub fn set_volume(&mut self, volume: i8, addr: RawAddress) -> i32 {
494 self.internal.pin_mut().set_volume(volume, addr)
495 }
496
497 #[log_args]
498 #[profile_enabled_or(BtStatus::NotReady.into())]
set_mic_volume(&mut self, volume: i8, addr: RawAddress) -> BtStatus499 pub fn set_mic_volume(&mut self, volume: i8, addr: RawAddress) -> BtStatus {
500 BtStatus::from(self.internal.pin_mut().set_mic_volume(volume, addr))
501 }
502
503 #[log_args]
504 #[profile_enabled_or(BtStatus::NotReady)]
disconnect(&mut self, addr: RawAddress) -> BtStatus505 pub fn disconnect(&mut self, addr: RawAddress) -> BtStatus {
506 BtStatus::from(self.internal.pin_mut().disconnect(addr))
507 }
508
509 #[log_args]
510 #[profile_enabled_or(BtStatus::NotReady.into())]
disconnect_audio(&mut self, addr: RawAddress) -> i32511 pub fn disconnect_audio(&mut self, addr: RawAddress) -> i32 {
512 self.internal.pin_mut().disconnect_audio(addr)
513 }
514
515 #[log_args]
516 #[profile_enabled_or(BtStatus::NotReady)]
device_status_notification( &mut self, status: TelephonyDeviceStatus, addr: RawAddress, ) -> BtStatus517 pub fn device_status_notification(
518 &mut self,
519 status: TelephonyDeviceStatus,
520 addr: RawAddress,
521 ) -> BtStatus {
522 BtStatus::from(self.internal.pin_mut().device_status_notification(status, addr))
523 }
524
525 #[log_args]
526 #[profile_enabled_or(BtStatus::NotReady)]
indicator_query_response( &mut self, device_status: TelephonyDeviceStatus, phone_state: PhoneState, addr: RawAddress, ) -> BtStatus527 pub fn indicator_query_response(
528 &mut self,
529 device_status: TelephonyDeviceStatus,
530 phone_state: PhoneState,
531 addr: RawAddress,
532 ) -> BtStatus {
533 BtStatus::from(self.internal.pin_mut().indicator_query_response(
534 device_status,
535 phone_state,
536 addr,
537 ))
538 }
539
540 #[log_args]
541 #[profile_enabled_or(BtStatus::NotReady)]
current_calls_query_response( &mut self, call_list: &Vec<CallInfo>, addr: RawAddress, ) -> BtStatus542 pub fn current_calls_query_response(
543 &mut self,
544 call_list: &Vec<CallInfo>,
545 addr: RawAddress,
546 ) -> BtStatus {
547 BtStatus::from(self.internal.pin_mut().current_calls_query_response(call_list, addr))
548 }
549
550 #[log_args]
551 #[profile_enabled_or(BtStatus::NotReady)]
phone_state_change( &mut self, phone_state: PhoneState, number: &String, addr: RawAddress, ) -> BtStatus552 pub fn phone_state_change(
553 &mut self,
554 phone_state: PhoneState,
555 number: &String,
556 addr: RawAddress,
557 ) -> BtStatus {
558 BtStatus::from(self.internal.pin_mut().phone_state_change(phone_state, number, addr))
559 }
560
561 #[log_args]
562 #[profile_enabled_or(BtStatus::NotReady)]
simple_at_response(&mut self, ok: bool, addr: RawAddress) -> BtStatus563 pub fn simple_at_response(&mut self, ok: bool, addr: RawAddress) -> BtStatus {
564 BtStatus::from(self.internal.pin_mut().simple_at_response(ok, addr))
565 }
566
567 #[log_args]
568 #[profile_enabled_or]
debug_dump(&mut self)569 pub fn debug_dump(&mut self) {
570 self.internal.pin_mut().debug_dump();
571 }
572
573 #[log_args]
574 #[profile_enabled_or(false)]
cleanup(&mut self) -> bool575 pub fn cleanup(&mut self) -> bool {
576 self.internal.pin_mut().cleanup();
577 true
578 }
579 }
580