• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::btif::{BluetoothInterface, BtStatus, RawAddress, SupportedProfiles, ToggleableProfile};
2 use crate::topstack::get_dispatchers;
3 
4 use std::sync::{Arc, Mutex};
5 use topshim_macros::{cb_variant, profile_enabled_or};
6 
7 use crate::bindings::root as bindings;
8 use crate::ccall;
9 use crate::utils::LTCheckedPtrMut;
10 
11 use log::warn;
12 
13 #[derive(Debug, Default)]
14 pub struct PlayerMetadata {
15     pub title: String,
16     pub artist: String,
17     pub album: String,
18     pub length_us: i64,
19 }
20 
21 #[cxx::bridge(namespace = bluetooth::topshim::rust)]
22 pub mod ffi {
23     unsafe extern "C++" {
24         include!("gd/rust/topshim/common/type_alias.h");
25         type RawAddress = crate::btif::RawAddress;
26     }
27 
28     unsafe extern "C++" {
29         include!("btav/btav_shim.h");
30         include!("btav_sink/btav_sink_shim.h");
31 
32         type AvrcpIntf;
33 
GetAvrcpProfile(btif: *const u8) -> UniquePtr<AvrcpIntf>34         unsafe fn GetAvrcpProfile(btif: *const u8) -> UniquePtr<AvrcpIntf>;
35 
init(self: Pin<&mut AvrcpIntf>)36         fn init(self: Pin<&mut AvrcpIntf>);
cleanup(self: Pin<&mut AvrcpIntf>)37         fn cleanup(self: Pin<&mut AvrcpIntf>);
connect(self: Pin<&mut AvrcpIntf>, bt_addr: RawAddress) -> u3238         fn connect(self: Pin<&mut AvrcpIntf>, bt_addr: RawAddress) -> u32;
disconnect(self: Pin<&mut AvrcpIntf>, bt_addr: RawAddress) -> u3239         fn disconnect(self: Pin<&mut AvrcpIntf>, bt_addr: RawAddress) -> u32;
set_volume(self: Pin<&mut AvrcpIntf>, volume: i8)40         fn set_volume(self: Pin<&mut AvrcpIntf>, volume: i8);
set_playback_status(self: Pin<&mut AvrcpIntf>, status: &String)41         fn set_playback_status(self: Pin<&mut AvrcpIntf>, status: &String);
set_position(self: Pin<&mut AvrcpIntf>, position_us: i64)42         fn set_position(self: Pin<&mut AvrcpIntf>, position_us: i64);
set_metadata( self: Pin<&mut AvrcpIntf>, title: &String, artist: &String, album: &String, length_us: i64, )43         fn set_metadata(
44             self: Pin<&mut AvrcpIntf>,
45             title: &String,
46             artist: &String,
47             album: &String,
48             length_us: i64,
49         );
add_player(self: Pin<&mut AvrcpIntf>, name: &String, browsing_supported: bool) -> u1650         fn add_player(self: Pin<&mut AvrcpIntf>, name: &String, browsing_supported: bool) -> u16;
51 
52     }
53     extern "Rust" {
avrcp_device_connected(addr: RawAddress, absolute_volume_enabled: bool)54         fn avrcp_device_connected(addr: RawAddress, absolute_volume_enabled: bool);
avrcp_device_disconnected(addr: RawAddress)55         fn avrcp_device_disconnected(addr: RawAddress);
avrcp_absolute_volume_update(volume: u8)56         fn avrcp_absolute_volume_update(volume: u8);
avrcp_send_key_event(key: u8, state: u8)57         fn avrcp_send_key_event(key: u8, state: u8);
avrcp_set_active_device(addr: RawAddress)58         fn avrcp_set_active_device(addr: RawAddress);
59     }
60 }
61 
62 #[derive(Debug)]
63 pub enum AvrcpCallbacks {
64     /// Emitted when avrcp completes connection.
65     /// Params: Device address, Absolute Volume Enabled
66     AvrcpDeviceConnected(RawAddress, bool),
67     /// Emitted when avrcp device disconnected.
68     /// Params: Device address
69     AvrcpDeviceDisconnected(RawAddress),
70     /// Emitted when the absolute volume of a connected AVRCP device changed
71     /// Params: Volume
72     AvrcpAbsoluteVolumeUpdate(u8),
73     /// Emitted when received a key event from a connected AVRCP device
74     /// Params: Key, Value
75     AvrcpSendKeyEvent(u8, u8),
76     /// Emitted when received request from AVRCP interface to set a device to active
77     /// Params: Device address
78     AvrcpSetActiveDevice(RawAddress),
79 }
80 
81 pub struct AvrcpCallbacksDispatcher {
82     pub dispatch: Box<dyn Fn(AvrcpCallbacks) + Send>,
83 }
84 
85 type AvrcpCb = Arc<Mutex<AvrcpCallbacksDispatcher>>;
86 
87 cb_variant!(
88     AvrcpCb,
89     avrcp_device_connected -> AvrcpCallbacks::AvrcpDeviceConnected,
90     RawAddress, bool);
91 
92 cb_variant!(
93     AvrcpCb,
94     avrcp_device_disconnected -> AvrcpCallbacks::AvrcpDeviceDisconnected,
95     RawAddress);
96 
97 cb_variant!(
98     AvrcpCb,
99     avrcp_absolute_volume_update -> AvrcpCallbacks::AvrcpAbsoluteVolumeUpdate,
100     u8, {}
101 );
102 
103 cb_variant!(
104     AvrcpCb,
105     avrcp_send_key_event -> AvrcpCallbacks::AvrcpSendKeyEvent,
106     u8, u8, {}
107 );
108 
109 cb_variant!(
110     AvrcpCb,
111     avrcp_set_active_device -> AvrcpCallbacks::AvrcpSetActiveDevice,
112     RawAddress);
113 
114 pub struct Avrcp {
115     internal: cxx::UniquePtr<ffi::AvrcpIntf>,
116     _is_init: bool,
117     _is_enabled: bool,
118 }
119 
120 // For *const u8 opaque btif
121 unsafe impl Send for Avrcp {}
122 
123 impl ToggleableProfile for Avrcp {
is_enabled(&self) -> bool124     fn is_enabled(&self) -> bool {
125         self._is_enabled
126     }
127 
enable(&mut self) -> bool128     fn enable(&mut self) -> bool {
129         self.internal.pin_mut().init();
130         self._is_enabled = true;
131         true
132     }
133 
134     #[profile_enabled_or(false)]
disable(&mut self) -> bool135     fn disable(&mut self) -> bool {
136         self.internal.pin_mut().cleanup();
137         self._is_enabled = false;
138         true
139     }
140 }
141 
142 impl Avrcp {
new(intf: &BluetoothInterface) -> Avrcp143     pub fn new(intf: &BluetoothInterface) -> Avrcp {
144         let avrcpif: cxx::UniquePtr<ffi::AvrcpIntf>;
145         unsafe {
146             avrcpif = ffi::GetAvrcpProfile(intf.as_raw_ptr());
147         }
148 
149         Avrcp { internal: avrcpif, _is_init: false, _is_enabled: false }
150     }
151 
is_initialized(&self) -> bool152     pub fn is_initialized(&self) -> bool {
153         self._is_init
154     }
155 
initialize(&mut self, callbacks: AvrcpCallbacksDispatcher) -> bool156     pub fn initialize(&mut self, callbacks: AvrcpCallbacksDispatcher) -> bool {
157         if get_dispatchers().lock().unwrap().set::<AvrcpCb>(Arc::new(Mutex::new(callbacks))) {
158             panic!("Tried to set dispatcher for Avrcp callbacks while it already exists");
159         }
160         self._is_init = true;
161         true
162     }
163 
164     #[profile_enabled_or(BtStatus::NotReady)]
connect(&mut self, addr: RawAddress) -> BtStatus165     pub fn connect(&mut self, addr: RawAddress) -> BtStatus {
166         BtStatus::from(self.internal.pin_mut().connect(addr.into()))
167     }
168 
169     #[profile_enabled_or(BtStatus::NotReady)]
disconnect(&mut self, addr: RawAddress) -> BtStatus170     pub fn disconnect(&mut self, addr: RawAddress) -> BtStatus {
171         BtStatus::from(self.internal.pin_mut().disconnect(addr.into()))
172     }
173 
174     #[profile_enabled_or]
set_volume(&mut self, volume: i8)175     pub fn set_volume(&mut self, volume: i8) {
176         self.internal.pin_mut().set_volume(volume);
177     }
178 
179     #[profile_enabled_or(false)]
cleanup(&mut self) -> bool180     pub fn cleanup(&mut self) -> bool {
181         self.internal.pin_mut().cleanup();
182         true
183     }
184 
185     #[profile_enabled_or]
set_playback_status(&mut self, status: &String)186     pub fn set_playback_status(&mut self, status: &String) {
187         self.internal.pin_mut().set_playback_status(status);
188     }
189 
190     #[profile_enabled_or]
set_position(&mut self, position_us: i64)191     pub fn set_position(&mut self, position_us: i64) {
192         self.internal.pin_mut().set_position(position_us);
193     }
194 
195     #[profile_enabled_or]
set_metadata(&mut self, metadata: &PlayerMetadata)196     pub fn set_metadata(&mut self, metadata: &PlayerMetadata) {
197         self.internal.pin_mut().set_metadata(
198             &metadata.title,
199             &metadata.artist,
200             &metadata.album,
201             metadata.length_us,
202         );
203     }
204 
205     #[profile_enabled_or]
add_player(&mut self, name: &String, browsing_supported: bool)206     pub fn add_player(&mut self, name: &String, browsing_supported: bool) {
207         self.internal.pin_mut().add_player(name, browsing_supported);
208     }
209 }
210 
211 struct RawAvrcpCtrlWrapper {
212     raw: *const bindings::btrc_ctrl_interface_t,
213 }
214 
215 // Pointers unsafe due to ownership but this is a static pointer so Send is ok.
216 unsafe impl Send for RawAvrcpCtrlWrapper {}
217 
218 pub struct AvrcpCtrl {
219     internal: RawAvrcpCtrlWrapper,
220     callbacks: Option<Box<bindings::btrc_ctrl_callbacks_t>>,
221 }
222 
223 cb_variant!(AvrcpCtCb, avrcp_connection_state_cb -> AvrcpCtrlCallbacks::ConnectionState,
224 bool, bool, *const RawAddress, {
225     let _2 = unsafe { *_2 };
226 });
227 
228 cb_variant!(AvrcpCtCb, avrcp_getrcfeatures_cb -> AvrcpCtrlCallbacks::GetRCFeatures,
229 *const RawAddress, i32, {
230     let _0 = unsafe { *_0 };
231 });
232 
233 cb_variant!(AvrcpCtCb, avrcp_get_cover_art_psm_cb -> AvrcpCtrlCallbacks::GetCoverArtPsm,
234 *const RawAddress, u16, {
235     let _0 = unsafe { *_0 };
236 });
237 
238 cb_variant!(AvrcpCtCb, avrcp_passthrough_rsp_cb -> AvrcpCtrlCallbacks::PassthroughRsp,
239 *const RawAddress, i32, i32, {
240     let _0 = unsafe { *_0 };
241 });
242 
243 #[derive(Debug)]
244 pub enum AvrcpCtrlCallbacks {
245     PassthroughRsp(RawAddress, i32, i32),
246     ConnectionState(bool, bool, RawAddress),
247     GetRCFeatures(RawAddress, i32),
248     GetCoverArtPsm(RawAddress, u16),
249 }
250 
251 pub struct AvrcpCtrlCallbacksDispatcher {
252     pub dispatch: Box<dyn Fn(AvrcpCtrlCallbacks) + Send>,
253 }
254 
255 type AvrcpCtCb = Arc<Mutex<AvrcpCtrlCallbacksDispatcher>>;
256 
257 impl AvrcpCtrl {
new(intf: &BluetoothInterface) -> AvrcpCtrl258     pub fn new(intf: &BluetoothInterface) -> AvrcpCtrl {
259         let r = intf.get_profile_interface(SupportedProfiles::AvrcpCtrl);
260         AvrcpCtrl {
261             internal: RawAvrcpCtrlWrapper { raw: r as *const bindings::btrc_ctrl_interface_t },
262             callbacks: None,
263         }
264     }
265 
initialize(&mut self, callbacks: AvrcpCtrlCallbacksDispatcher) -> bool266     pub fn initialize(&mut self, callbacks: AvrcpCtrlCallbacksDispatcher) -> bool {
267         // Register dispatcher
268         if get_dispatchers().lock().unwrap().set::<AvrcpCtCb>(Arc::new(Mutex::new(callbacks))) {
269             panic!("Tried to set dispatcher for AvrcpCt Callbacks but it already existed");
270         }
271 
272         let callbacks = Box::new(bindings::btrc_ctrl_callbacks_t {
273             size: 21 * 8,
274             passthrough_rsp_cb: Some(avrcp_passthrough_rsp_cb),
275             groupnavigation_rsp_cb: None,
276             connection_state_cb: Some(avrcp_connection_state_cb),
277             getrcfeatures_cb: Some(avrcp_getrcfeatures_cb),
278             setplayerappsetting_rsp_cb: None,
279             playerapplicationsetting_cb: None,
280             playerapplicationsetting_changed_cb: None,
281             setabsvol_cmd_cb: None,
282             registernotification_absvol_cb: None,
283             track_changed_cb: None,
284             play_position_changed_cb: None,
285             play_status_changed_cb: None,
286             get_folder_items_cb: None,
287             change_folder_path_cb: None,
288             set_browsed_player_cb: None,
289             set_addressed_player_cb: None,
290             addressed_player_changed_cb: None,
291             now_playing_contents_changed_cb: None,
292             available_player_changed_cb: None,
293             get_cover_art_psm_cb: Some(avrcp_get_cover_art_psm_cb),
294         });
295 
296         self.callbacks = Some(callbacks);
297 
298         let cb_ptr = LTCheckedPtrMut::from(self.callbacks.as_mut().unwrap());
299 
300         ccall!(self, init, cb_ptr.into());
301 
302         true
303     }
304 
send_pass_through_cmd( &mut self, addr: RawAddress, key_code: u8, key_state: u8, ) -> BtStatus305     pub fn send_pass_through_cmd(
306         &mut self,
307         addr: RawAddress,
308         key_code: u8,
309         key_state: u8,
310     ) -> BtStatus {
311         ccall!(self, send_pass_through_cmd, &addr, key_code.into(), key_state.into()).into()
312     }
313 }
314