• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::btif::{BluetoothInterface, RawAddress, ToggleableProfile};
2 use crate::topstack::get_dispatchers;
3 
4 use std::fmt::{Debug, Formatter, Result};
5 use std::sync::{Arc, Mutex};
6 use topshim_macros::{cb_variant, log_args, profile_enabled_or, profile_enabled_or_default};
7 
8 use log::warn;
9 
10 #[cxx::bridge(namespace = bluetooth::topshim::rust)]
11 pub mod ffi {
12     unsafe extern "C++" {
13         include!("types/raw_address.h");
14         #[namespace = ""]
15         type RawAddress = crate::btif::RawAddress;
16     }
17 
18     #[derive(Debug, Copy, Clone)]
19     pub enum BtLeAudioCodecIndex {
20         SrcLc3 = 0,
21         SrcInvalid = 1_000_000,
22     }
23 
24     #[derive(Debug, Copy, Clone)]
25     pub struct BtLeAudioCodecConfig {
26         pub codec_type: i32,
27     }
28 
29     #[derive(Debug, Copy, Clone)]
30     pub enum BtLeAudioConnectionState {
31         Disconnected = 0,
32         Connecting,
33         Connected,
34         Disconnecting,
35     }
36 
37     #[derive(Debug, Copy, Clone)]
38     pub enum BtLeAudioGroupStatus {
39         Inactive = 0,
40         Active,
41         TurnedIdleDuringCall,
42     }
43 
44     #[derive(Debug, Copy, Clone)]
45     pub enum BtLeAudioGroupNodeStatus {
46         Added = 1,
47         Removed,
48     }
49 
50     #[derive(Debug, Copy, Clone)]
51     pub enum BtLeAudioUsage {
52         AudioUsageUnknown = 0,
53         AudioUsageMedia = 1,
54         AudioUsageVoiceCommunication = 2,
55     }
56 
57     #[derive(Debug, Copy, Clone)]
58     pub enum BtLeAudioContentType {
59         AudioContentTypeUnknown = 0,
60         AudioContentTypeSpeech = 1,
61         AudioContentTypeMusic = 2,
62         AudioContentTypeMovie = 3,
63         AudioContentTypeSonification = 4,
64     }
65 
66     #[derive(Debug, Copy, Clone)]
67     pub enum BtLeAudioSource {
68         AudioSourceDefault = 0,
69         AudioSourceMic = 1,
70         AudioSourceVoiceUplink = 2,
71         AudioSourceVoiceDownlink = 3,
72         AudioSourceVoiceCall = 4,
73         AudioSourceCamcorder = 5,
74         AudioSourceVoiceRecognition = 6,
75         AudioSourceVoiceCommunication = 7,
76     }
77 
78     #[derive(Debug, Copy, Clone)]
79     #[repr(i32)]
80     pub enum BtLeStreamStartedStatus {
81         Canceled = -1,
82         Idle = 0,
83         Started = 1,
84     }
85 
86     #[derive(Debug, Default)]
87     pub struct BtLePcmConfig {
88         pub data_interval_us: u32,
89         pub sample_rate: u32,
90         pub bits_per_sample: u8,
91         pub channels_count: u8,
92     }
93 
94     #[derive(Debug, Copy, Clone)]
95     pub enum BtLeAudioUnicastMonitorModeStatus {
96         StreamingRequested = 0,
97         Streaming = 1,
98         StreamingSuspended = 2,
99     }
100 
101     #[derive(Debug, Copy, Clone)]
102     pub enum BtLeAudioDirection {
103         Sink = 1,
104         Source = 2,
105         Both = 3,
106     }
107 
108     #[derive(Debug, Copy, Clone)]
109     pub enum BtLeAudioGroupStreamStatus {
110         Idle = 0,
111         Streaming,
112         Releasing,
113         ReleasingAutonomous,
114         Suspending,
115         Suspended,
116         ConfiguredAutonomous,
117         ConfiguredByUser,
118         Destroyed,
119     }
120 
121     #[derive(Debug)]
122     pub struct SourceMetadata {
123         pub usage: BtLeAudioUsage,
124         pub content_type: BtLeAudioContentType,
125         pub gain: f64,
126     }
127 
128     #[derive(Debug)]
129     pub struct SinkMetadata {
130         pub source: BtLeAudioSource,
131         pub gain: f64,
132     }
133 
134     unsafe extern "C++" {
135         include!("le_audio/le_audio_shim.h");
136 
137         type LeAudioClientIntf;
138 
GetLeAudioClientProfile(btif: *const u8) -> UniquePtr<LeAudioClientIntf>139         unsafe fn GetLeAudioClientProfile(btif: *const u8) -> UniquePtr<LeAudioClientIntf>;
140 
init(self: Pin<&mut LeAudioClientIntf>)141         fn init(self: Pin<&mut LeAudioClientIntf>);
connect(self: Pin<&mut LeAudioClientIntf>, addr: RawAddress)142         fn connect(self: Pin<&mut LeAudioClientIntf>, addr: RawAddress);
disconnect(self: Pin<&mut LeAudioClientIntf>, addr: RawAddress)143         fn disconnect(self: Pin<&mut LeAudioClientIntf>, addr: RawAddress);
set_enable_state(self: Pin<&mut LeAudioClientIntf>, addr: RawAddress, enabled: bool)144         fn set_enable_state(self: Pin<&mut LeAudioClientIntf>, addr: RawAddress, enabled: bool);
cleanup(self: Pin<&mut LeAudioClientIntf>)145         fn cleanup(self: Pin<&mut LeAudioClientIntf>);
remove_device(self: Pin<&mut LeAudioClientIntf>, addr: RawAddress)146         fn remove_device(self: Pin<&mut LeAudioClientIntf>, addr: RawAddress);
group_add_node(self: Pin<&mut LeAudioClientIntf>, group_id: i32, addr: RawAddress)147         fn group_add_node(self: Pin<&mut LeAudioClientIntf>, group_id: i32, addr: RawAddress);
group_remove_node(self: Pin<&mut LeAudioClientIntf>, group_id: i32, addr: RawAddress)148         fn group_remove_node(self: Pin<&mut LeAudioClientIntf>, group_id: i32, addr: RawAddress);
group_set_active(self: Pin<&mut LeAudioClientIntf>, group_id: i32)149         fn group_set_active(self: Pin<&mut LeAudioClientIntf>, group_id: i32);
set_codec_config_preference( self: Pin<&mut LeAudioClientIntf>, group_id: i32, input_codec_config: BtLeAudioCodecConfig, output_codec_config: BtLeAudioCodecConfig, )150         fn set_codec_config_preference(
151             self: Pin<&mut LeAudioClientIntf>,
152             group_id: i32,
153             input_codec_config: BtLeAudioCodecConfig,
154             output_codec_config: BtLeAudioCodecConfig,
155         );
set_ccid_information(self: Pin<&mut LeAudioClientIntf>, ccid: i32, context_type: i32)156         fn set_ccid_information(self: Pin<&mut LeAudioClientIntf>, ccid: i32, context_type: i32);
set_in_call(self: Pin<&mut LeAudioClientIntf>, in_call: bool)157         fn set_in_call(self: Pin<&mut LeAudioClientIntf>, in_call: bool);
send_audio_profile_preferences( self: Pin<&mut LeAudioClientIntf>, group_id: i32, is_output_preference_le_audio: bool, is_duplex_preference_le_audio: bool, )158         fn send_audio_profile_preferences(
159             self: Pin<&mut LeAudioClientIntf>,
160             group_id: i32,
161             is_output_preference_le_audio: bool,
162             is_duplex_preference_le_audio: bool,
163         );
set_unicast_monitor_mode( self: Pin<&mut LeAudioClientIntf>, direction: BtLeAudioDirection, enable: bool, )164         fn set_unicast_monitor_mode(
165             self: Pin<&mut LeAudioClientIntf>,
166             direction: BtLeAudioDirection,
167             enable: bool,
168         );
169 
host_start_audio_request(self: Pin<&mut LeAudioClientIntf>) -> bool170         fn host_start_audio_request(self: Pin<&mut LeAudioClientIntf>) -> bool;
host_stop_audio_request(self: Pin<&mut LeAudioClientIntf>)171         fn host_stop_audio_request(self: Pin<&mut LeAudioClientIntf>);
peer_start_audio_request(self: Pin<&mut LeAudioClientIntf>) -> bool172         fn peer_start_audio_request(self: Pin<&mut LeAudioClientIntf>) -> bool;
peer_stop_audio_request(self: Pin<&mut LeAudioClientIntf>)173         fn peer_stop_audio_request(self: Pin<&mut LeAudioClientIntf>);
get_host_pcm_config(self: Pin<&mut LeAudioClientIntf>) -> BtLePcmConfig174         fn get_host_pcm_config(self: Pin<&mut LeAudioClientIntf>) -> BtLePcmConfig;
get_peer_pcm_config(self: Pin<&mut LeAudioClientIntf>) -> BtLePcmConfig175         fn get_peer_pcm_config(self: Pin<&mut LeAudioClientIntf>) -> BtLePcmConfig;
get_host_stream_started(self: Pin<&mut LeAudioClientIntf>) -> BtLeStreamStartedStatus176         fn get_host_stream_started(self: Pin<&mut LeAudioClientIntf>) -> BtLeStreamStartedStatus;
get_peer_stream_started(self: Pin<&mut LeAudioClientIntf>) -> BtLeStreamStartedStatus177         fn get_peer_stream_started(self: Pin<&mut LeAudioClientIntf>) -> BtLeStreamStartedStatus;
source_metadata_changed( self: Pin<&mut LeAudioClientIntf>, metadata: Vec<SourceMetadata>, )178         fn source_metadata_changed(
179             self: Pin<&mut LeAudioClientIntf>,
180             metadata: Vec<SourceMetadata>,
181         );
sink_metadata_changed(self: Pin<&mut LeAudioClientIntf>, metadata: Vec<SinkMetadata>)182         fn sink_metadata_changed(self: Pin<&mut LeAudioClientIntf>, metadata: Vec<SinkMetadata>);
183     }
184 
185     extern "Rust" {
le_audio_initialized_callback()186         fn le_audio_initialized_callback();
le_audio_connection_state_callback(state: BtLeAudioConnectionState, addr: RawAddress)187         fn le_audio_connection_state_callback(state: BtLeAudioConnectionState, addr: RawAddress);
le_audio_group_status_callback(group_id: i32, group_status: BtLeAudioGroupStatus)188         fn le_audio_group_status_callback(group_id: i32, group_status: BtLeAudioGroupStatus);
le_audio_group_node_status_callback( bd_addr: RawAddress, group_id: i32, node_status: BtLeAudioGroupNodeStatus, )189         fn le_audio_group_node_status_callback(
190             bd_addr: RawAddress,
191             group_id: i32,
192             node_status: BtLeAudioGroupNodeStatus,
193         );
le_audio_audio_conf_callback( direction: u8, group_id: i32, snk_audio_location: i64, src_audio_location: i64, avail_cont: u16, )194         fn le_audio_audio_conf_callback(
195             direction: u8,
196             group_id: i32,
197             snk_audio_location: i64,
198             src_audio_location: i64,
199             avail_cont: u16,
200         );
le_audio_sink_audio_location_available_callback( addr: RawAddress, snk_audio_locations: i64, )201         fn le_audio_sink_audio_location_available_callback(
202             addr: RawAddress,
203             snk_audio_locations: i64,
204         );
le_audio_audio_local_codec_capabilities_callback( local_input_capa_codec_conf: &Vec<BtLeAudioCodecConfig>, local_output_capa_codec_conf: &Vec<BtLeAudioCodecConfig>, )205         fn le_audio_audio_local_codec_capabilities_callback(
206             local_input_capa_codec_conf: &Vec<BtLeAudioCodecConfig>,
207             local_output_capa_codec_conf: &Vec<BtLeAudioCodecConfig>,
208         );
le_audio_audio_group_codec_conf_callback( group_id: i32, input_codec_conf: BtLeAudioCodecConfig, output_codec_conf: BtLeAudioCodecConfig, input_selectable_codec_conf: &Vec<BtLeAudioCodecConfig>, output_selectable_codec_conf: &Vec<BtLeAudioCodecConfig>, )209         fn le_audio_audio_group_codec_conf_callback(
210             group_id: i32,
211             input_codec_conf: BtLeAudioCodecConfig,
212             output_codec_conf: BtLeAudioCodecConfig,
213             input_selectable_codec_conf: &Vec<BtLeAudioCodecConfig>,
214             output_selectable_codec_conf: &Vec<BtLeAudioCodecConfig>,
215         );
le_audio_unicast_monitor_mode_status_callback( direction: BtLeAudioDirection, status: BtLeAudioUnicastMonitorModeStatus, )216         fn le_audio_unicast_monitor_mode_status_callback(
217             direction: BtLeAudioDirection,
218             status: BtLeAudioUnicastMonitorModeStatus,
219         );
220 
le_audio_group_stream_status_callback(group_id: i32, status: BtLeAudioGroupStreamStatus)221         fn le_audio_group_stream_status_callback(group_id: i32, status: BtLeAudioGroupStreamStatus);
222     }
223 }
224 
225 pub type BtLeAudioCodecConfig = ffi::BtLeAudioCodecConfig;
226 pub type BtLeAudioCodecIndex = ffi::BtLeAudioCodecIndex;
227 pub type BtLeAudioConnectionState = ffi::BtLeAudioConnectionState;
228 pub type BtLeAudioDirection = ffi::BtLeAudioDirection;
229 pub type BtLeAudioGroupStatus = ffi::BtLeAudioGroupStatus;
230 pub type BtLeAudioGroupNodeStatus = ffi::BtLeAudioGroupNodeStatus;
231 pub type BtLePcmConfig = ffi::BtLePcmConfig;
232 pub type BtLeStreamStartedStatus = ffi::BtLeStreamStartedStatus;
233 pub type BtLeAudioUsage = ffi::BtLeAudioUsage;
234 pub type BtLeAudioContentType = ffi::BtLeAudioContentType;
235 pub type BtLeAudioSource = ffi::BtLeAudioSource;
236 pub type BtLeAudioUnicastMonitorModeStatus = ffi::BtLeAudioUnicastMonitorModeStatus;
237 pub type BtLeAudioGroupStreamStatus = ffi::BtLeAudioGroupStreamStatus;
238 pub type SourceMetadata = ffi::SourceMetadata;
239 pub type SinkMetadata = ffi::SinkMetadata;
240 
241 impl From<BtLeAudioGroupStatus> for i32 {
from(value: BtLeAudioGroupStatus) -> Self242     fn from(value: BtLeAudioGroupStatus) -> Self {
243         match value {
244             BtLeAudioGroupStatus::Inactive => 0,
245             BtLeAudioGroupStatus::Active => 1,
246             BtLeAudioGroupStatus::TurnedIdleDuringCall => 2,
247             _ => panic!("Invalid value {:?} to BtLeAudioGroupStatus", value),
248         }
249     }
250 }
251 
252 impl From<i32> for BtLeAudioGroupStatus {
from(value: i32) -> Self253     fn from(value: i32) -> Self {
254         match value {
255             0 => BtLeAudioGroupStatus::Inactive,
256             1 => BtLeAudioGroupStatus::Active,
257             2 => BtLeAudioGroupStatus::TurnedIdleDuringCall,
258             _ => panic!("Invalid value {} for BtLeAudioGroupStatus", value),
259         }
260     }
261 }
262 
263 impl Default for BtLeAudioGroupStatus {
default() -> Self264     fn default() -> Self {
265         BtLeAudioGroupStatus::Inactive
266     }
267 }
268 
269 impl From<BtLeAudioGroupNodeStatus> for i32 {
from(value: BtLeAudioGroupNodeStatus) -> Self270     fn from(value: BtLeAudioGroupNodeStatus) -> Self {
271         match value {
272             BtLeAudioGroupNodeStatus::Added => 1,
273             BtLeAudioGroupNodeStatus::Removed => 2,
274             _ => panic!("Invalid value {:?} to BtLeAudioGroupNodeStatus", value),
275         }
276     }
277 }
278 
279 impl From<i32> for BtLeAudioGroupNodeStatus {
from(value: i32) -> Self280     fn from(value: i32) -> Self {
281         match value {
282             1 => BtLeAudioGroupNodeStatus::Added,
283             2 => BtLeAudioGroupNodeStatus::Removed,
284             _ => panic!("Invalid value {} for BtLeAudioGroupNodeStatus", value),
285         }
286     }
287 }
288 
289 impl From<BtLeAudioUsage> for i32 {
from(value: BtLeAudioUsage) -> Self290     fn from(value: BtLeAudioUsage) -> Self {
291         match value {
292             BtLeAudioUsage::AudioUsageUnknown => 0,
293             BtLeAudioUsage::AudioUsageMedia => 1,
294             BtLeAudioUsage::AudioUsageVoiceCommunication => 2,
295             _ => panic!("Invalid value {:?} for BtLeAudioUsage", value),
296         }
297     }
298 }
299 
300 impl From<i32> for BtLeAudioUsage {
from(value: i32) -> Self301     fn from(value: i32) -> Self {
302         match value {
303             0 => BtLeAudioUsage::AudioUsageUnknown,
304             1 => BtLeAudioUsage::AudioUsageMedia,
305             2 => BtLeAudioUsage::AudioUsageVoiceCommunication,
306             _ => panic!("Invalid value {} for BtLeAudioUsage", value),
307         }
308     }
309 }
310 
311 impl From<BtLeAudioContentType> for i32 {
from(value: BtLeAudioContentType) -> Self312     fn from(value: BtLeAudioContentType) -> Self {
313         match value {
314             BtLeAudioContentType::AudioContentTypeUnknown => 0,
315             BtLeAudioContentType::AudioContentTypeSpeech => 1,
316             BtLeAudioContentType::AudioContentTypeMusic => 2,
317             BtLeAudioContentType::AudioContentTypeMovie => 3,
318             BtLeAudioContentType::AudioContentTypeSonification => 4,
319             _ => panic!("Invalid value {:?} for BtLeAudioContentType", value),
320         }
321     }
322 }
323 
324 impl From<i32> for BtLeAudioContentType {
from(value: i32) -> Self325     fn from(value: i32) -> Self {
326         match value {
327             0 => BtLeAudioContentType::AudioContentTypeUnknown,
328             1 => BtLeAudioContentType::AudioContentTypeSpeech,
329             2 => BtLeAudioContentType::AudioContentTypeMusic,
330             3 => BtLeAudioContentType::AudioContentTypeMovie,
331             4 => BtLeAudioContentType::AudioContentTypeSonification,
332             _ => panic!("Invalid value {} for BtLeAudioContentType", value),
333         }
334     }
335 }
336 
337 impl From<BtLeAudioSource> for i32 {
from(value: BtLeAudioSource) -> Self338     fn from(value: BtLeAudioSource) -> Self {
339         match value {
340             BtLeAudioSource::AudioSourceDefault => 0,
341             BtLeAudioSource::AudioSourceMic => 1,
342             BtLeAudioSource::AudioSourceVoiceUplink => 2,
343             BtLeAudioSource::AudioSourceVoiceDownlink => 3,
344             BtLeAudioSource::AudioSourceVoiceCall => 4,
345             BtLeAudioSource::AudioSourceCamcorder => 5,
346             BtLeAudioSource::AudioSourceVoiceRecognition => 6,
347             BtLeAudioSource::AudioSourceVoiceCommunication => 7,
348             _ => panic!("Invalid value {:?} for BtLeAudioSource", value),
349         }
350     }
351 }
352 
353 impl From<i32> for BtLeAudioSource {
from(value: i32) -> Self354     fn from(value: i32) -> Self {
355         match value {
356             0 => BtLeAudioSource::AudioSourceDefault,
357             1 => BtLeAudioSource::AudioSourceMic,
358             2 => BtLeAudioSource::AudioSourceVoiceUplink,
359             3 => BtLeAudioSource::AudioSourceVoiceDownlink,
360             4 => BtLeAudioSource::AudioSourceVoiceCall,
361             5 => BtLeAudioSource::AudioSourceCamcorder,
362             6 => BtLeAudioSource::AudioSourceVoiceRecognition,
363             7 => BtLeAudioSource::AudioSourceVoiceCommunication,
364             _ => panic!("Invalid value {} for BtLeAudioSource", value),
365         }
366     }
367 }
368 
369 impl From<BtLeStreamStartedStatus> for i32 {
from(value: BtLeStreamStartedStatus) -> Self370     fn from(value: BtLeStreamStartedStatus) -> Self {
371         match value {
372             BtLeStreamStartedStatus::Canceled => -1,
373             BtLeStreamStartedStatus::Idle => 0,
374             BtLeStreamStartedStatus::Started => 1,
375             _ => panic!("Invalid value {:?} for BtLeStreamStartedStatus", value),
376         }
377     }
378 }
379 
380 impl From<i32> for BtLeStreamStartedStatus {
from(value: i32) -> Self381     fn from(value: i32) -> Self {
382         match value {
383             -1 => BtLeStreamStartedStatus::Canceled,
384             0 => BtLeStreamStartedStatus::Idle,
385             1 => BtLeStreamStartedStatus::Started,
386             _ => panic!("Invalid value {} for BtLeStreamStartedStatus", value),
387         }
388     }
389 }
390 impl From<BtLeAudioUnicastMonitorModeStatus> for i32 {
from(value: BtLeAudioUnicastMonitorModeStatus) -> Self391     fn from(value: BtLeAudioUnicastMonitorModeStatus) -> Self {
392         match value {
393             BtLeAudioUnicastMonitorModeStatus::StreamingRequested => 0,
394             BtLeAudioUnicastMonitorModeStatus::Streaming => 1,
395             BtLeAudioUnicastMonitorModeStatus::StreamingSuspended => 2,
396             _ => panic!("Invalid value {:?} to BtLeAudioUnicastMonitorModeStatus", value),
397         }
398     }
399 }
400 
401 impl From<i32> for BtLeAudioUnicastMonitorModeStatus {
from(value: i32) -> Self402     fn from(value: i32) -> Self {
403         match value {
404             0 => BtLeAudioUnicastMonitorModeStatus::StreamingRequested,
405             1 => BtLeAudioUnicastMonitorModeStatus::Streaming,
406             2 => BtLeAudioUnicastMonitorModeStatus::StreamingSuspended,
407             _ => panic!("Invalid value {} for BtLeAudioUnicastMonitorModeStatus", value),
408         }
409     }
410 }
411 
412 impl From<BtLeAudioGroupStreamStatus> for i32 {
from(value: BtLeAudioGroupStreamStatus) -> Self413     fn from(value: BtLeAudioGroupStreamStatus) -> Self {
414         match value {
415             BtLeAudioGroupStreamStatus::Idle => 0,
416             BtLeAudioGroupStreamStatus::Streaming => 1,
417             BtLeAudioGroupStreamStatus::Releasing => 2,
418             BtLeAudioGroupStreamStatus::ReleasingAutonomous => 3,
419             BtLeAudioGroupStreamStatus::Suspending => 4,
420             BtLeAudioGroupStreamStatus::Suspended => 5,
421             BtLeAudioGroupStreamStatus::ConfiguredAutonomous => 6,
422             BtLeAudioGroupStreamStatus::ConfiguredByUser => 7,
423             BtLeAudioGroupStreamStatus::Destroyed => 8,
424             _ => panic!("Invalid value {:?} to BtLeAudioGroupStreamStatus", value),
425         }
426     }
427 }
428 
429 impl From<i32> for BtLeAudioGroupStreamStatus {
from(value: i32) -> Self430     fn from(value: i32) -> Self {
431         match value {
432             0 => BtLeAudioGroupStreamStatus::Idle,
433             1 => BtLeAudioGroupStreamStatus::Streaming,
434             2 => BtLeAudioGroupStreamStatus::Releasing,
435             3 => BtLeAudioGroupStreamStatus::ReleasingAutonomous,
436             4 => BtLeAudioGroupStreamStatus::Suspending,
437             5 => BtLeAudioGroupStreamStatus::Suspended,
438             6 => BtLeAudioGroupStreamStatus::ConfiguredAutonomous,
439             7 => BtLeAudioGroupStreamStatus::ConfiguredByUser,
440             8 => BtLeAudioGroupStreamStatus::Destroyed,
441             _ => panic!("Invalid value {} to BtLeAudioGroupStreamStatus", value),
442         }
443     }
444 }
445 
446 impl Default for BtLeAudioGroupStreamStatus {
default() -> Self447     fn default() -> Self {
448         BtLeAudioGroupStreamStatus::Idle
449     }
450 }
451 
452 impl From<BtLeAudioDirection> for i32 {
from(value: BtLeAudioDirection) -> Self453     fn from(value: BtLeAudioDirection) -> Self {
454         match value {
455             BtLeAudioDirection::Sink => 1,
456             BtLeAudioDirection::Source => 2,
457             BtLeAudioDirection::Both => 3,
458             _ => panic!("Invalid value {:?} to BtLeAudioDirection", value),
459         }
460     }
461 }
462 
463 impl From<i32> for BtLeAudioDirection {
from(value: i32) -> Self464     fn from(value: i32) -> Self {
465         match value {
466             1 => BtLeAudioDirection::Sink,
467             2 => BtLeAudioDirection::Source,
468             3 => BtLeAudioDirection::Both,
469             _ => panic!("Invalid value {} for BtLeAudioDirection", value),
470         }
471     }
472 }
473 
474 #[derive(Debug)]
475 pub enum LeAudioClientCallbacks {
476     Initialized(),
477     ConnectionState(BtLeAudioConnectionState, RawAddress),
478     GroupStatus(i32, BtLeAudioGroupStatus),
479     GroupNodeStatus(RawAddress, i32, BtLeAudioGroupNodeStatus),
480     AudioConf(u8, i32, i64, i64, u16),
481     SinkAudioLocationAvailable(RawAddress, i64),
482     AudioLocalCodecCapabilities(Vec<BtLeAudioCodecConfig>, Vec<BtLeAudioCodecConfig>),
483     AudioGroupCodecConf(
484         i32,
485         BtLeAudioCodecConfig,
486         BtLeAudioCodecConfig,
487         Vec<BtLeAudioCodecConfig>,
488         Vec<BtLeAudioCodecConfig>,
489     ),
490     UnicastMonitorModeStatus(BtLeAudioDirection, BtLeAudioUnicastMonitorModeStatus),
491     GroupStreamStatus(i32, BtLeAudioGroupStreamStatus),
492 }
493 
494 pub struct LeAudioClientCallbacksDispatcher {
495     pub dispatch: Box<dyn Fn(LeAudioClientCallbacks) + Send>,
496 }
497 
498 impl Debug for LeAudioClientCallbacksDispatcher {
fmt(&self, f: &mut Formatter<'_>) -> Result499     fn fmt(&self, f: &mut Formatter<'_>) -> Result {
500         write!(f, "LeAudioClientCallbacksDispatcher {{}}")
501     }
502 }
503 
504 type LeAudioClientCb = Arc<Mutex<LeAudioClientCallbacksDispatcher>>;
505 
506 cb_variant!(LeAudioClientCb,
507             le_audio_initialized_callback -> LeAudioClientCallbacks::Initialized);
508 
509 cb_variant!(LeAudioClientCb,
510             le_audio_connection_state_callback -> LeAudioClientCallbacks::ConnectionState,
511             BtLeAudioConnectionState, RawAddress);
512 
513 cb_variant!(LeAudioClientCb,
514             le_audio_group_status_callback -> LeAudioClientCallbacks::GroupStatus,
515             i32, BtLeAudioGroupStatus);
516 
517 cb_variant!(LeAudioClientCb,
518             le_audio_group_node_status_callback -> LeAudioClientCallbacks::GroupNodeStatus,
519             RawAddress, i32, BtLeAudioGroupNodeStatus);
520 
521 cb_variant!(LeAudioClientCb,
522             le_audio_audio_conf_callback -> LeAudioClientCallbacks::AudioConf,
523             u8, i32, i64, i64, u16);
524 
525 cb_variant!(LeAudioClientCb,
526             le_audio_sink_audio_location_available_callback -> LeAudioClientCallbacks::SinkAudioLocationAvailable,
527             RawAddress, i64);
528 
529 cb_variant!(LeAudioClientCb,
530             le_audio_unicast_monitor_mode_status_callback -> LeAudioClientCallbacks::UnicastMonitorModeStatus,
531             BtLeAudioDirection, BtLeAudioUnicastMonitorModeStatus);
532 
533 cb_variant!(LeAudioClientCb,
534             le_audio_group_stream_status_callback -> LeAudioClientCallbacks::GroupStreamStatus,
535             i32, BtLeAudioGroupStreamStatus);
536 
537 cb_variant!(LeAudioClientCb,
538 le_audio_audio_local_codec_capabilities_callback -> LeAudioClientCallbacks::AudioLocalCodecCapabilities,
539 &Vec<BtLeAudioCodecConfig>, &Vec<BtLeAudioCodecConfig>,
540 {
541     let _0: Vec<BtLeAudioCodecConfig> = _0.to_vec();
542     let _1: Vec<BtLeAudioCodecConfig> = _1.to_vec();
543 });
544 
545 cb_variant!(LeAudioClientCb,
546 le_audio_audio_group_codec_conf_callback -> LeAudioClientCallbacks::AudioGroupCodecConf,
547 i32, BtLeAudioCodecConfig, BtLeAudioCodecConfig,
548 &Vec<BtLeAudioCodecConfig>, &Vec<BtLeAudioCodecConfig>,
549 {
550     let _3: Vec<BtLeAudioCodecConfig> = _3.to_vec();
551     let _4: Vec<BtLeAudioCodecConfig> = _4.to_vec();
552 });
553 
554 pub struct LeAudioClient {
555     internal: cxx::UniquePtr<ffi::LeAudioClientIntf>,
556     is_init: bool,
557     is_enabled: bool,
558 }
559 
560 // For *const u8 opaque btif
561 // SAFETY: `LeAudioClientIntf` is thread-safe to make calls from.
562 unsafe impl Send for LeAudioClient {}
563 
564 impl ToggleableProfile for LeAudioClient {
is_enabled(&self) -> bool565     fn is_enabled(&self) -> bool {
566         self.is_enabled
567     }
568 
enable(&mut self) -> bool569     fn enable(&mut self) -> bool {
570         if self.is_enabled {
571             warn!("LeAudioClient is already enabled.");
572             return false;
573         }
574 
575         self.internal.pin_mut().init();
576         self.is_enabled = true;
577         true
578     }
579 
580     #[profile_enabled_or(false)]
disable(&mut self) -> bool581     fn disable(&mut self) -> bool {
582         if !self.is_enabled {
583             warn!("LeAudioClient is already disabled.");
584             return false;
585         }
586 
587         self.internal.pin_mut().cleanup();
588         self.is_enabled = false;
589         true
590     }
591 }
592 
593 impl LeAudioClient {
594     #[log_args]
new(intf: &BluetoothInterface) -> LeAudioClient595     pub fn new(intf: &BluetoothInterface) -> LeAudioClient {
596         // SAFETY: `intf.as_raw_ptr()` is a valid pointer to a `BluetoothInterface`
597         let lea_client_if: cxx::UniquePtr<ffi::LeAudioClientIntf> =
598             unsafe { ffi::GetLeAudioClientProfile(intf.as_raw_ptr()) };
599 
600         LeAudioClient { internal: lea_client_if, is_init: false, is_enabled: false }
601     }
602 
603     #[log_args]
is_initialized(&self) -> bool604     pub fn is_initialized(&self) -> bool {
605         self.is_init
606     }
607 
608     // `internal.init` is invoked during `ToggleableProfile::enable`
609     #[log_args]
initialize(&mut self, callbacks: LeAudioClientCallbacksDispatcher) -> bool610     pub fn initialize(&mut self, callbacks: LeAudioClientCallbacksDispatcher) -> bool {
611         if self.is_init {
612             warn!("LeAudioClient has already been initialized");
613             return false;
614         }
615 
616         if get_dispatchers().lock().unwrap().set::<LeAudioClientCb>(Arc::new(Mutex::new(callbacks)))
617         {
618             panic!("Tried to set dispatcher for LeAudioClient callbacks while it already exists");
619         }
620 
621         self.is_init = true;
622 
623         true
624     }
625 
626     #[log_args]
627     #[profile_enabled_or]
connect(&mut self, addr: RawAddress)628     pub fn connect(&mut self, addr: RawAddress) {
629         self.internal.pin_mut().connect(addr);
630     }
631 
632     #[log_args]
633     #[profile_enabled_or]
disconnect(&mut self, addr: RawAddress)634     pub fn disconnect(&mut self, addr: RawAddress) {
635         self.internal.pin_mut().disconnect(addr);
636     }
637 
638     #[log_args]
639     #[profile_enabled_or]
set_enable_state(&mut self, addr: RawAddress, enabled: bool)640     pub fn set_enable_state(&mut self, addr: RawAddress, enabled: bool) {
641         self.internal.pin_mut().set_enable_state(addr, enabled);
642     }
643 
644     #[log_args]
645     #[profile_enabled_or]
cleanup(&mut self)646     pub fn cleanup(&mut self) {
647         self.internal.pin_mut().cleanup();
648     }
649 
650     #[log_args]
651     #[profile_enabled_or]
remove_device(&mut self, addr: RawAddress)652     pub fn remove_device(&mut self, addr: RawAddress) {
653         self.internal.pin_mut().remove_device(addr);
654     }
655 
656     #[log_args]
657     #[profile_enabled_or]
group_add_node(&mut self, group_id: i32, addr: RawAddress)658     pub fn group_add_node(&mut self, group_id: i32, addr: RawAddress) {
659         self.internal.pin_mut().group_add_node(group_id, addr);
660     }
661 
662     #[log_args]
663     #[profile_enabled_or]
group_remove_node(&mut self, group_id: i32, addr: RawAddress)664     pub fn group_remove_node(&mut self, group_id: i32, addr: RawAddress) {
665         self.internal.pin_mut().group_remove_node(group_id, addr);
666     }
667 
668     #[log_args]
669     #[profile_enabled_or]
group_set_active(&mut self, group_id: i32)670     pub fn group_set_active(&mut self, group_id: i32) {
671         self.internal.pin_mut().group_set_active(group_id);
672     }
673 
674     #[log_args]
675     #[profile_enabled_or]
set_codec_config_preference( &mut self, group_id: i32, input_codec_config: BtLeAudioCodecConfig, output_codec_config: BtLeAudioCodecConfig, )676     pub fn set_codec_config_preference(
677         &mut self,
678         group_id: i32,
679         input_codec_config: BtLeAudioCodecConfig,
680         output_codec_config: BtLeAudioCodecConfig,
681     ) {
682         self.internal.pin_mut().set_codec_config_preference(
683             group_id,
684             input_codec_config,
685             output_codec_config,
686         );
687     }
688 
689     #[log_args]
690     #[profile_enabled_or]
set_ccid_information(&mut self, ccid: i32, context_type: i32)691     pub fn set_ccid_information(&mut self, ccid: i32, context_type: i32) {
692         self.internal.pin_mut().set_ccid_information(ccid, context_type);
693     }
694 
695     #[log_args]
696     #[profile_enabled_or]
set_in_call(&mut self, in_call: bool)697     pub fn set_in_call(&mut self, in_call: bool) {
698         self.internal.pin_mut().set_in_call(in_call);
699     }
700 
701     #[log_args]
702     #[profile_enabled_or]
send_audio_profile_preferences( &mut self, group_id: i32, is_output_preference_le_audio: bool, is_duplex_preference_le_audio: bool, )703     pub fn send_audio_profile_preferences(
704         &mut self,
705         group_id: i32,
706         is_output_preference_le_audio: bool,
707         is_duplex_preference_le_audio: bool,
708     ) {
709         self.internal.pin_mut().send_audio_profile_preferences(
710             group_id,
711             is_output_preference_le_audio,
712             is_duplex_preference_le_audio,
713         );
714     }
715 
716     #[log_args]
717     #[profile_enabled_or]
set_unicast_monitor_mode(&mut self, direction: BtLeAudioDirection, enable: bool)718     pub fn set_unicast_monitor_mode(&mut self, direction: BtLeAudioDirection, enable: bool) {
719         self.internal.pin_mut().set_unicast_monitor_mode(direction, enable);
720     }
721 
722     #[log_args]
723     #[profile_enabled_or(false)]
host_start_audio_request(&mut self) -> bool724     pub fn host_start_audio_request(&mut self) -> bool {
725         self.internal.pin_mut().host_start_audio_request()
726     }
727 
728     #[log_args]
729     #[profile_enabled_or]
host_stop_audio_request(&mut self)730     pub fn host_stop_audio_request(&mut self) {
731         self.internal.pin_mut().host_stop_audio_request();
732     }
733 
734     #[log_args]
735     #[profile_enabled_or(false)]
peer_start_audio_request(&mut self) -> bool736     pub fn peer_start_audio_request(&mut self) -> bool {
737         self.internal.pin_mut().peer_start_audio_request()
738     }
739 
740     #[log_args]
741     #[profile_enabled_or]
peer_stop_audio_request(&mut self)742     pub fn peer_stop_audio_request(&mut self) {
743         self.internal.pin_mut().peer_stop_audio_request();
744     }
745 
746     #[log_args]
747     #[profile_enabled_or_default]
get_host_pcm_config(&mut self) -> BtLePcmConfig748     pub fn get_host_pcm_config(&mut self) -> BtLePcmConfig {
749         self.internal.pin_mut().get_host_pcm_config()
750     }
751 
752     #[log_args]
753     #[profile_enabled_or_default]
get_peer_pcm_config(&mut self) -> BtLePcmConfig754     pub fn get_peer_pcm_config(&mut self) -> BtLePcmConfig {
755         self.internal.pin_mut().get_peer_pcm_config()
756     }
757 
758     #[log_args]
759     #[profile_enabled_or(BtLeStreamStartedStatus::Idle)]
get_host_stream_started(&mut self) -> BtLeStreamStartedStatus760     pub fn get_host_stream_started(&mut self) -> BtLeStreamStartedStatus {
761         self.internal.pin_mut().get_host_stream_started()
762     }
763 
764     #[log_args]
765     #[profile_enabled_or(BtLeStreamStartedStatus::Idle)]
get_peer_stream_started(&mut self) -> BtLeStreamStartedStatus766     pub fn get_peer_stream_started(&mut self) -> BtLeStreamStartedStatus {
767         self.internal.pin_mut().get_peer_stream_started()
768     }
769 
770     #[log_args]
771     #[profile_enabled_or]
source_metadata_changed(&mut self, metadata: Vec<SourceMetadata>)772     pub fn source_metadata_changed(&mut self, metadata: Vec<SourceMetadata>) {
773         self.internal.pin_mut().source_metadata_changed(metadata);
774     }
775 
776     #[log_args]
777     #[profile_enabled_or]
sink_metadata_changed(&mut self, metadata: Vec<SinkMetadata>)778     pub fn sink_metadata_changed(&mut self, metadata: Vec<SinkMetadata>) {
779         self.internal.pin_mut().sink_metadata_changed(metadata);
780     }
781 }
782