1 use crate::btif::BluetoothInterface; 2 use crate::topstack::get_dispatchers; 3 4 use std::sync::{Arc, Mutex}; 5 use topshim_macros::cb_variant; 6 7 #[cxx::bridge(namespace = bluetooth::topshim::rust)] 8 pub mod ffi { 9 unsafe extern "C++" { 10 include!("btav/btav_shim.h"); 11 12 type AvrcpIntf; 13 GetAvrcpProfile(btif: *const u8) -> UniquePtr<AvrcpIntf>14 unsafe fn GetAvrcpProfile(btif: *const u8) -> UniquePtr<AvrcpIntf>; 15 init(self: Pin<&mut AvrcpIntf>)16 fn init(self: Pin<&mut AvrcpIntf>); cleanup(self: Pin<&mut AvrcpIntf>)17 fn cleanup(self: Pin<&mut AvrcpIntf>); set_volume(self: Pin<&mut AvrcpIntf>, volume: i8)18 fn set_volume(self: Pin<&mut AvrcpIntf>, volume: i8); 19 20 } 21 extern "Rust" { avrcp_absolute_volume_enabled(enabled: bool)22 fn avrcp_absolute_volume_enabled(enabled: bool); avrcp_absolute_volume_update(volume: i8)23 fn avrcp_absolute_volume_update(volume: i8); 24 } 25 } 26 27 #[derive(Debug)] 28 pub enum AvrcpCallbacks { 29 AvrcpAbsoluteVolumeEnabled(bool), 30 AvrcpAbsoluteVolumeUpdate(i8), 31 } 32 33 pub struct AvrcpCallbacksDispatcher { 34 pub dispatch: Box<dyn Fn(AvrcpCallbacks) + Send>, 35 } 36 37 type AvrcpCb = Arc<Mutex<AvrcpCallbacksDispatcher>>; 38 39 cb_variant!( 40 AvrcpCb, 41 avrcp_absolute_volume_enabled -> AvrcpCallbacks::AvrcpAbsoluteVolumeEnabled, 42 bool, {} 43 ); 44 45 cb_variant!( 46 AvrcpCb, 47 avrcp_absolute_volume_update -> AvrcpCallbacks::AvrcpAbsoluteVolumeUpdate, 48 i8, {} 49 ); 50 51 pub struct Avrcp { 52 internal: cxx::UniquePtr<ffi::AvrcpIntf>, 53 _is_init: bool, 54 } 55 56 // For *const u8 opaque btif 57 unsafe impl Send for Avrcp {} 58 59 impl Avrcp { new(intf: &BluetoothInterface) -> Avrcp60 pub fn new(intf: &BluetoothInterface) -> Avrcp { 61 let avrcpif: cxx::UniquePtr<ffi::AvrcpIntf>; 62 unsafe { 63 avrcpif = ffi::GetAvrcpProfile(intf.as_raw_ptr()); 64 } 65 66 Avrcp { internal: avrcpif, _is_init: false } 67 } 68 initialize(&mut self, callbacks: AvrcpCallbacksDispatcher) -> bool69 pub fn initialize(&mut self, callbacks: AvrcpCallbacksDispatcher) -> bool { 70 if get_dispatchers().lock().unwrap().set::<AvrcpCb>(Arc::new(Mutex::new(callbacks))) { 71 panic!("Tried to set dispatcher for Avrcp callbacks while it already exists"); 72 } 73 self.internal.pin_mut().init(); 74 true 75 } 76 cleanup(&mut self) -> bool77 pub fn cleanup(&mut self) -> bool { 78 self.internal.pin_mut().cleanup(); 79 true 80 } 81 set_volume(&mut self, volume: i8)82 pub fn set_volume(&mut self, volume: i8) { 83 self.internal.pin_mut().set_volume(volume); 84 } 85 } 86