• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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