blob: 10d3c8d26c3daede8f23523e708bffed8f11526c [file] [log] [blame]
use crate::btif::{BluetoothInterface, RawAddress};
use crate::topstack::get_dispatchers;
use num_traits::cast::FromPrimitive;
use std::sync::{Arc, Mutex};
use topshim_macros::cb_variant;
#[derive(Debug, FromPrimitive, PartialEq, PartialOrd)]
#[repr(u32)]
pub enum BthfConnectionState {
Disconnected = 0,
Connecting,
Connected,
Disconnecting,
}
impl From<u32> for BthfConnectionState {
fn from(item: u32) -> Self {
BthfConnectionState::from_u32(item).unwrap()
}
}
#[cxx::bridge(namespace = bluetooth::topshim::rust)]
pub mod ffi {
#[derive(Debug, Copy, Clone)]
pub struct RustRawAddress {
address: [u8; 6],
}
unsafe extern "C++" {
include!("hfp/hfp_shim.h");
type HfpIntf;
unsafe fn GetHfpProfile(btif: *const u8) -> UniquePtr<HfpIntf>;
fn init(self: Pin<&mut HfpIntf>) -> i32;
fn connect(self: Pin<&mut HfpIntf>, bt_addr: RustRawAddress) -> i32;
fn disconnect(self: Pin<&mut HfpIntf>, bt_addr: RustRawAddress) -> i32;
fn cleanup(self: Pin<&mut HfpIntf>);
}
extern "Rust" {
fn hfp_connection_state_callback(state: u32, addr: RustRawAddress);
}
}
impl From<RawAddress> for ffi::RustRawAddress {
fn from(addr: RawAddress) -> Self {
ffi::RustRawAddress { address: addr.val }
}
}
impl Into<RawAddress> for ffi::RustRawAddress {
fn into(self) -> RawAddress {
RawAddress { val: self.address }
}
}
#[derive(Debug)]
pub enum HfpCallbacks {
ConnectionState(BthfConnectionState, RawAddress),
}
pub struct HfpCallbacksDispatcher {
pub dispatch: Box<dyn Fn(HfpCallbacks) + Send>,
}
type HfpCb = Arc<Mutex<HfpCallbacksDispatcher>>;
cb_variant!(
HfpCb,
hfp_connection_state_callback -> HfpCallbacks::ConnectionState,
u32 -> BthfConnectionState, ffi::RustRawAddress -> RawAddress, {
let _1 = _1.into();
}
);
pub struct Hfp {
internal: cxx::UniquePtr<ffi::HfpIntf>,
_is_init: bool,
}
// For *const u8 opaque btif
unsafe impl Send for Hfp {}
impl Hfp {
pub fn new(intf: &BluetoothInterface) -> Hfp {
let hfpif: cxx::UniquePtr<ffi::HfpIntf>;
unsafe {
hfpif = ffi::GetHfpProfile(intf.as_raw_ptr());
}
Hfp { internal: hfpif, _is_init: false }
}
pub fn initialize(&mut self, callbacks: HfpCallbacksDispatcher) -> bool {
if get_dispatchers().lock().unwrap().set::<HfpCb>(Arc::new(Mutex::new(callbacks))) {
panic!("Tried to set dispatcher for HFP callbacks while it already exists");
}
self.internal.pin_mut().init();
true
}
pub fn connect(&mut self, addr: RawAddress) {
self.internal.pin_mut().connect(addr.into());
}
pub fn disconnect(&mut self, addr: RawAddress) {
self.internal.pin_mut().disconnect(addr.into());
}
pub fn cleanup(&mut self) -> bool {
self.internal.pin_mut().cleanup();
true
}
}