1 use crate::btif::{BluetoothInterface, RawAddress}; 2 use crate::topstack::get_dispatchers; 3 4 use num_traits::cast::FromPrimitive; 5 use std::convert::{TryFrom, TryInto}; 6 use std::sync::{Arc, Mutex}; 7 use topshim_macros::cb_variant; 8 9 #[derive(Debug, FromPrimitive, ToPrimitive, PartialEq, PartialOrd)] 10 #[repr(u32)] 11 pub enum BthfConnectionState { 12 Disconnected = 0, 13 Connecting, 14 Connected, 15 SlcConnected, 16 Disconnecting, 17 } 18 19 impl From<u32> for BthfConnectionState { from(item: u32) -> Self20 fn from(item: u32) -> Self { 21 BthfConnectionState::from_u32(item).unwrap() 22 } 23 } 24 25 #[derive(Debug, FromPrimitive, PartialEq, PartialOrd)] 26 #[repr(u32)] 27 pub enum BthfAudioState { 28 Disconnected = 0, 29 Connecting, 30 Connected, 31 Disconnecting, 32 } 33 34 impl From<u32> for BthfAudioState { from(item: u32) -> Self35 fn from(item: u32) -> Self { 36 BthfAudioState::from_u32(item).unwrap() 37 } 38 } 39 40 bitflags! { 41 #[derive(Default)] 42 pub struct HfpCodecCapability: i32 { 43 const UNSUPPORTED = 0b00; 44 const CVSD = 0b01; 45 const MSBC = 0b10; 46 } 47 } 48 49 impl TryInto<i32> for HfpCodecCapability { 50 type Error = (); try_into(self) -> Result<i32, Self::Error>51 fn try_into(self) -> Result<i32, Self::Error> { 52 Ok(self.bits()) 53 } 54 } 55 56 impl TryFrom<i32> for HfpCodecCapability { 57 type Error = (); try_from(val: i32) -> Result<Self, Self::Error>58 fn try_from(val: i32) -> Result<Self, Self::Error> { 59 Self::from_bits(val).ok_or(()) 60 } 61 } 62 63 #[cxx::bridge(namespace = bluetooth::topshim::rust)] 64 pub mod ffi { 65 #[derive(Debug, Copy, Clone)] 66 pub struct RustRawAddress { 67 address: [u8; 6], 68 } 69 70 unsafe extern "C++" { 71 include!("hfp/hfp_shim.h"); 72 73 type HfpIntf; 74 GetHfpProfile(btif: *const u8) -> UniquePtr<HfpIntf>75 unsafe fn GetHfpProfile(btif: *const u8) -> UniquePtr<HfpIntf>; 76 init(self: Pin<&mut HfpIntf>) -> i3277 fn init(self: Pin<&mut HfpIntf>) -> i32; connect(self: Pin<&mut HfpIntf>, bt_addr: RustRawAddress) -> i3278 fn connect(self: Pin<&mut HfpIntf>, bt_addr: RustRawAddress) -> i32; connect_audio(self: Pin<&mut HfpIntf>, bt_addr: RustRawAddress) -> i3279 fn connect_audio(self: Pin<&mut HfpIntf>, bt_addr: RustRawAddress) -> i32; disconnect(self: Pin<&mut HfpIntf>, bt_addr: RustRawAddress) -> i3280 fn disconnect(self: Pin<&mut HfpIntf>, bt_addr: RustRawAddress) -> i32; disconnect_audio(self: Pin<&mut HfpIntf>, bt_addr: RustRawAddress) -> i3281 fn disconnect_audio(self: Pin<&mut HfpIntf>, bt_addr: RustRawAddress) -> i32; cleanup(self: Pin<&mut HfpIntf>)82 fn cleanup(self: Pin<&mut HfpIntf>); 83 84 } 85 extern "Rust" { hfp_connection_state_callback(state: u32, addr: RustRawAddress)86 fn hfp_connection_state_callback(state: u32, addr: RustRawAddress); hfp_audio_state_callback(state: u32, addr: RustRawAddress)87 fn hfp_audio_state_callback(state: u32, addr: RustRawAddress); 88 } 89 } 90 91 impl From<RawAddress> for ffi::RustRawAddress { from(addr: RawAddress) -> Self92 fn from(addr: RawAddress) -> Self { 93 ffi::RustRawAddress { address: addr.val } 94 } 95 } 96 97 impl Into<RawAddress> for ffi::RustRawAddress { into(self) -> RawAddress98 fn into(self) -> RawAddress { 99 RawAddress { val: self.address } 100 } 101 } 102 103 #[derive(Debug)] 104 pub enum HfpCallbacks { 105 ConnectionState(BthfConnectionState, RawAddress), 106 AudioState(BthfAudioState, RawAddress), 107 } 108 109 pub struct HfpCallbacksDispatcher { 110 pub dispatch: Box<dyn Fn(HfpCallbacks) + Send>, 111 } 112 113 type HfpCb = Arc<Mutex<HfpCallbacksDispatcher>>; 114 115 cb_variant!( 116 HfpCb, 117 hfp_connection_state_callback -> HfpCallbacks::ConnectionState, 118 u32 -> BthfConnectionState, ffi::RustRawAddress -> RawAddress, { 119 let _1 = _1.into(); 120 } 121 ); 122 123 cb_variant!( 124 HfpCb, 125 hfp_audio_state_callback -> HfpCallbacks::AudioState, 126 u32 -> BthfAudioState, ffi::RustRawAddress -> RawAddress, { 127 let _1 = _1.into(); 128 } 129 ); 130 131 pub struct Hfp { 132 internal: cxx::UniquePtr<ffi::HfpIntf>, 133 _is_init: bool, 134 } 135 136 // For *const u8 opaque btif 137 unsafe impl Send for Hfp {} 138 139 impl Hfp { new(intf: &BluetoothInterface) -> Hfp140 pub fn new(intf: &BluetoothInterface) -> Hfp { 141 let hfpif: cxx::UniquePtr<ffi::HfpIntf>; 142 unsafe { 143 hfpif = ffi::GetHfpProfile(intf.as_raw_ptr()); 144 } 145 146 Hfp { internal: hfpif, _is_init: false } 147 } 148 initialize(&mut self, callbacks: HfpCallbacksDispatcher) -> bool149 pub fn initialize(&mut self, callbacks: HfpCallbacksDispatcher) -> bool { 150 if get_dispatchers().lock().unwrap().set::<HfpCb>(Arc::new(Mutex::new(callbacks))) { 151 panic!("Tried to set dispatcher for HFP callbacks while it already exists"); 152 } 153 self.internal.pin_mut().init(); 154 true 155 } 156 connect(&mut self, addr: RawAddress)157 pub fn connect(&mut self, addr: RawAddress) { 158 self.internal.pin_mut().connect(addr.into()); 159 } 160 connect_audio(&mut self, addr: RawAddress) -> i32161 pub fn connect_audio(&mut self, addr: RawAddress) -> i32 { 162 self.internal.pin_mut().connect_audio(addr.into()) 163 } 164 disconnect(&mut self, addr: RawAddress)165 pub fn disconnect(&mut self, addr: RawAddress) { 166 self.internal.pin_mut().disconnect(addr.into()); 167 } 168 disconnect_audio(&mut self, addr: RawAddress) -> i32169 pub fn disconnect_audio(&mut self, addr: RawAddress) -> i32 { 170 self.internal.pin_mut().disconnect_audio(addr.into()) 171 } 172 cleanup(&mut self) -> bool173 pub fn cleanup(&mut self) -> bool { 174 self.internal.pin_mut().cleanup(); 175 true 176 } 177 } 178