Skip to main content

embassy_usb_host/class/uac/
descriptors.rs

1//! USB Audio Class (UAC) descriptor parsing and management.
2
3use heapless::Vec;
4use heapless::index_map::FnvIndexMap;
5
6use super::codes::*;
7use crate::descriptor::descriptor_type::{CS_ENDPOINT, CS_INTERFACE, INTERFACE_ASSOCIATION};
8use crate::descriptor::{
9    ConfigurationDescriptor, DescriptorVisitor, EndpointDescriptor, InterfaceDescriptor as GenericInterfaceDescriptor,
10    StringIndex, USBDescriptor, VisitError,
11};
12
13const MAX_AUDIO_STREAMING_INTERFACES: usize = 16;
14const MAX_ALTERNATE_SETTINGS: usize = 4;
15const MAX_CLOCK_DESCRIPTORS: usize = 8;
16const MAX_UNIT_DESCRIPTORS: usize = 16;
17const MAX_TERMINAL_DESCRIPTORS: usize = 16;
18
19/// Collection of audio interfaces representing a complete UAC audio function.
20///
21/// This struct contains all the interfaces that make up a USB Audio Class device,
22/// including the interface association descriptor, control interface, and streaming interfaces.
23#[derive(Debug, PartialEq)]
24#[cfg_attr(feature = "defmt", derive(defmt::Format))]
25pub struct AudioInterfaceCollection {
26    /// Interface association descriptor that groups the audio interfaces together.
27    pub interface_association_descriptor: InterfaceAssociationDescriptor,
28    /// Audio control interface containing clocks, terminals, and units.
29    pub control_interface: AudioControlInterface,
30    /// Collection of audio streaming interfaces for data transfer.
31    pub audio_streaming_interfaces: Vec<AudioStreamingInterface, MAX_AUDIO_STREAMING_INTERFACES>,
32}
33
34/// Errors that can occur during audio interface parsing.
35#[derive(Debug, PartialEq)]
36#[cfg_attr(feature = "defmt", derive(defmt::Format))]
37pub enum AudioInterfaceError {
38    /// A buffer is full and cannot accept more items.
39    BufferFull(&'static str),
40    /// No audio control interface was found in the configuration.
41    MissingControlInterface,
42    /// Audio control interface header descriptor is missing.
43    MissingControlInterfaceHeader,
44    /// An invalid descriptor was encountered during parsing.
45    InvalidDescriptor,
46    /// No audio configuration was found in the device.
47    NoAudioConfiguration,
48    /// Audio streaming class descriptor is missing.
49    MissingAudioStreamingClassDescriptor,
50}
51
52struct AudioCollectionBuilder {
53    iad: Option<InterfaceAssociationDescriptor>,
54    // Interface group cached until the CS_INTERFACE header arrives in on_other.
55    // Non-empty means a group is pending; cleared when the header is consumed.
56    interfaces: Vec<InterfaceDescriptor, MAX_ALTERNATE_SETTINGS>,
57    control: Option<AudioControlInterface>,
58    streaming: Vec<AudioStreamingInterface, MAX_AUDIO_STREAMING_INTERFACES>,
59    error: Option<AudioInterfaceError>,
60}
61
62impl AudioCollectionBuilder {
63    fn new() -> Self {
64        Self {
65            iad: None,
66            interfaces: Vec::new(),
67            control: None,
68            streaming: Vec::new(),
69            error: None,
70        }
71    }
72
73    fn build(self) -> Result<AudioInterfaceCollection, AudioInterfaceError> {
74        if let Some(e) = self.error {
75            return Err(e);
76        }
77        Ok(AudioInterfaceCollection {
78            interface_association_descriptor: self.iad.ok_or(AudioInterfaceError::NoAudioConfiguration)?,
79            control_interface: self.control.ok_or(AudioInterfaceError::MissingControlInterface)?,
80            audio_streaming_interfaces: self.streaming,
81        })
82    }
83}
84
85impl<'a> DescriptorVisitor<'a> for AudioCollectionBuilder {
86    type Error = AudioInterfaceError;
87
88    fn on_interface(&mut self, iface: &GenericInterfaceDescriptor<'a>) -> bool {
89        let Some(ref iad) = self.iad else {
90            return true;
91        };
92
93        if iface.interface_number >= iad.first_interface + iad.num_interfaces {
94            return false; // stop iteration
95        }
96
97        if iface.interface_class != interface::AUDIO {
98            return true; // ignore
99        }
100
101        if iface.interface_protocol != function_protocol::AF_VERSION_02_00 {
102            debug!(
103                "Skipping interface with unsupported protocol: {:#04x}",
104                iface.interface_protocol
105            );
106            return true;
107        }
108
109        match iface.interface_subclass {
110            interface::subclass::AUDIOCONTROL => {
111                if self.control.is_some() {
112                    warn!("Audio Control Interface already parsed, skipping");
113                    return true;
114                }
115                if !self.interfaces.is_empty() {
116                    self.error = Some(AudioInterfaceError::MissingAudioStreamingClassDescriptor);
117                    return false;
118                }
119                trace!("Processing Audio Control Interface");
120                self.interfaces = Vec::from_slice(&[InterfaceDescriptor::from(iface)]).unwrap();
121            }
122            interface::subclass::AUDIOSTREAMING => {
123                let is_alternate = self
124                    .interfaces
125                    .first()
126                    .is_some_and(|i| i.interface_number == iface.interface_number);
127                if is_alternate {
128                    if self.interfaces.push(InterfaceDescriptor::from(iface)).is_err() {
129                        self.error = Some(AudioInterfaceError::BufferFull("Too many interfaces"));
130                        return false;
131                    }
132                    return true;
133                }
134                if !self.interfaces.is_empty() {
135                    self.error = Some(match self.interfaces[0].interface_subclass {
136                        interface::subclass::AUDIOCONTROL => AudioInterfaceError::MissingControlInterfaceHeader,
137                        _ => AudioInterfaceError::MissingAudioStreamingClassDescriptor,
138                    });
139                    return false;
140                }
141                trace!("Processing Audio Streaming Interface");
142                self.interfaces = Vec::from_slice(&[InterfaceDescriptor::from(iface)]).unwrap();
143            }
144            _ => {
145                trace!("Skipping unknown audio subclass: {:#04x}", iface.interface_subclass);
146            }
147        }
148        true
149    }
150
151    fn on_endpoint(&mut self, iface: &GenericInterfaceDescriptor<'a>, ep: &EndpointDescriptor) -> bool {
152        match iface.interface_subclass {
153            interface::subclass::AUDIOSTREAMING => {
154                if let Some(si) = self.streaming.last_mut() {
155                    if ep.attributes == 0b010001 {
156                        si.feedback_endpoint_descriptor = Some(*ep);
157                    } else {
158                        si.endpoint_descriptor = Some(*ep);
159                    }
160                }
161            }
162            interface::subclass::AUDIOCONTROL => {
163                if let Some(ac) = &mut self.control {
164                    ac.interrupt_endpoint_descriptor = Some(*ep);
165                }
166            }
167            _ => {}
168        }
169        true
170    }
171
172    fn on_other(&mut self, _iface: Option<&GenericInterfaceDescriptor<'a>>, raw: &[u8]) -> Result<bool, Self::Error> {
173        if raw.len() < 2 {
174            return Ok(true);
175        }
176        match raw[1] {
177            INTERFACE_ASSOCIATION => {
178                if self.iad.is_none() {
179                    if let Ok(iad) = InterfaceAssociationDescriptor::try_from_bytes(raw) {
180                        if iad.is_audio_association() {
181                            self.iad = Some(iad);
182                        }
183                    }
184                }
185            }
186            CS_INTERFACE => {
187                if !self.interfaces.is_empty() {
188                    match self.interfaces[0].interface_subclass {
189                        interface::subclass::AUDIOCONTROL => {
190                            if let Ok(header) = AudioControlHeaderDescriptor::try_from_bytes(raw) {
191                                let interfaces = core::mem::take(&mut self.interfaces);
192                                debug!(
193                                    "Found Audio Control Header: version={}.{}",
194                                    header.audio_device_class.0, header.audio_device_class.1
195                                );
196                                self.control = Some(AudioControlInterface::new(interfaces, header));
197                                return Ok(true);
198                            }
199                        }
200                        interface::subclass::AUDIOSTREAMING => {
201                            if let Ok(class_desc) = AudioStreamingClassDescriptor::try_from_bytes(raw) {
202                                let interfaces = core::mem::take(&mut self.interfaces);
203                                trace!("Found Audio Streaming Class Descriptor: {:?}", class_desc.format);
204                                self.streaming
205                                    .push(AudioStreamingInterface::new(interfaces, class_desc))
206                                    .map_err(|_| {
207                                        AudioInterfaceError::BufferFull("Too many audio streaming interfaces")
208                                    })?;
209                                return Ok(true);
210                            }
211                        }
212                        _ => {}
213                    }
214                }
215                // Accumulate into whichever interface is currently in progress.
216                if let Some(si) = self.streaming.last_mut() {
217                    if let Ok(format_type) = FormatTypeDescriptor::try_from_bytes(raw) {
218                        si.format_type_descriptor = Some(format_type);
219                    }
220                } else if let Some(ac) = &mut self.control {
221                    ac.add_cs_interface(raw)?;
222                }
223            }
224            CS_ENDPOINT => {
225                if let Some(si) = self.streaming.last_mut() {
226                    if let Ok(audio_ep) = AudioEndpointDescriptor::try_from_bytes(raw) {
227                        si.audio_endpoint_descriptor = Some(audio_ep);
228                    }
229                }
230            }
231            _ => {}
232        }
233        Ok(true)
234    }
235}
236
237impl AudioInterfaceCollection {
238    /// Attempts to parse an audio interface collection from a configuration descriptor.
239    ///
240    /// This method searches for an interface association descriptor for audio,
241    /// then parses the control interface and all streaming interfaces.
242    ///
243    /// Returns an [`AudioInterfaceCollection`] on success, or an [`AudioInterfaceError`] if parsing fails.
244    pub fn try_from_configuration(cfg: &ConfigurationDescriptor) -> Result<Self, AudioInterfaceError> {
245        let mut builder = AudioCollectionBuilder::new();
246        cfg.visit_descriptors(&mut builder).map_err(|e| match e {
247            VisitError::BadDescriptor => AudioInterfaceError::InvalidDescriptor,
248            VisitError::Visitor(e) => e,
249        })?;
250        builder.build()
251    }
252}
253
254/// USB interface association descriptor for grouping related interfaces.
255///
256/// This descriptor is used to associate multiple interfaces that belong to the same function,
257/// such as an audio function with control and streaming interfaces.
258#[derive(Debug, PartialEq)]
259#[cfg_attr(feature = "defmt", derive(defmt::Format))]
260pub struct InterfaceAssociationDescriptor {
261    /// First interface number in the association.
262    pub first_interface: u8,
263    /// Number of interfaces in the association.
264    pub num_interfaces: u8,
265    /// Function class code.
266    pub class: u8,
267    /// Function subclass code.
268    pub subclass: u8,
269    /// Function protocol code.
270    pub protocol: u8,
271    /// Index of string descriptor describing the function.
272    pub interface_name: StringIndex,
273}
274
275impl USBDescriptor for InterfaceAssociationDescriptor {
276    const SIZE: usize = 8;
277    const DESC_TYPE: u8 = INTERFACE_ASSOCIATION;
278    type Error = ();
279
280    fn try_from_bytes(bytes: &[u8]) -> Result<Self, Self::Error> {
281        if bytes.len() < Self::SIZE {
282            return Err(());
283        }
284        if bytes[1] != Self::DESC_TYPE {
285            return Err(());
286        }
287        Ok(Self {
288            first_interface: bytes[2],
289            num_interfaces: bytes[3],
290            class: bytes[4],
291            subclass: bytes[5],
292            protocol: bytes[6],
293            interface_name: bytes[7],
294        })
295    }
296}
297
298impl InterfaceAssociationDescriptor {
299    /// Returns true if this interface association is for an audio function.
300    pub fn is_audio_association(&self) -> bool {
301        self.class == AUDIO_FUNCTION && self.protocol == function_protocol::AF_VERSION_02_00
302    }
303}
304
305/// USB interface descriptor for audio interfaces.
306#[derive(Copy, Clone, Debug, PartialEq)]
307#[cfg_attr(feature = "defmt", derive(defmt::Format))]
308pub struct InterfaceDescriptor {
309    /// Length of this descriptor in bytes.
310    pub len: u8,
311    /// Type of this descriptor. Must be 0x04.
312    pub descriptor_type: u8,
313    /// Number of this interface.
314    pub interface_number: u8,
315    /// Value used to select this alternate setting for the interface.
316    pub alternate_setting: u8,
317    /// Number of endpoints used by this interface.
318    pub num_endpoints: u8,
319    /// USB interface class code.
320    pub interface_class: u8,
321    /// USB interface subclass code.
322    pub interface_subclass: u8,
323    /// USB interface protocol code.
324    pub interface_protocol: u8,
325    /// Index of string descriptor describing this interface.
326    pub interface_name: StringIndex,
327}
328
329impl From<&GenericInterfaceDescriptor<'_>> for InterfaceDescriptor {
330    fn from(g: &GenericInterfaceDescriptor<'_>) -> Self {
331        Self {
332            len: g.len,
333            descriptor_type: g.descriptor_type,
334            interface_number: g.interface_number,
335            alternate_setting: g.alternate_setting,
336            num_endpoints: g.num_endpoints,
337            interface_class: g.interface_class,
338            interface_subclass: g.interface_subclass,
339            interface_protocol: g.interface_protocol,
340            interface_name: g.interface_name,
341        }
342    }
343}
344
345//--------------------------------------------------------------------------------------------------
346// Audio Control
347
348/// Audio control interface containing all control-related descriptors.
349///
350/// This struct contains the header descriptor, clock descriptors, unit descriptors,
351/// terminal descriptors, and optional interrupt endpoint descriptor.
352#[derive(Debug, PartialEq)]
353pub struct AudioControlInterface {
354    /// Interface descriptors for this control interface.
355    pub interface_descriptors: Vec<InterfaceDescriptor, MAX_ALTERNATE_SETTINGS>,
356    /// Audio control header descriptor.
357    pub header_descriptor: AudioControlHeaderDescriptor,
358    /// Optional interrupt endpoint descriptor for control notifications.
359    pub interrupt_endpoint_descriptor: Option<EndpointDescriptor>,
360    /// Map of clock descriptors indexed by clock ID.
361    pub clock_descriptors: FnvIndexMap<u8, ClockDescriptor, MAX_CLOCK_DESCRIPTORS>,
362    /// Map of unit descriptors indexed by unit ID.
363    pub unit_descriptors: FnvIndexMap<u8, UnitDescriptor, MAX_UNIT_DESCRIPTORS>,
364    /// Map of terminal descriptors indexed by terminal ID.
365    pub terminal_descriptors: FnvIndexMap<u8, TerminalDescriptor, MAX_TERMINAL_DESCRIPTORS>,
366}
367
368// heapless::IndexMap does not implement `defmt::Format`; summarize maps by length.
369#[cfg(feature = "defmt")]
370impl defmt::Format for AudioControlInterface {
371    fn format(&self, fmt: defmt::Formatter<'_>) {
372        defmt::write!(
373            fmt,
374            "AudioControlInterface {{ interface_descriptors: {=?}, header_descriptor: {=?}, interrupt_endpoint_descriptor: {=?}, clock_descriptors_len: {=usize}, unit_descriptors_len: {=usize}, terminal_descriptors_len: {=usize} }}",
375            self.interface_descriptors,
376            self.header_descriptor,
377            self.interrupt_endpoint_descriptor,
378            self.clock_descriptors.len(),
379            self.unit_descriptors.len(),
380            self.terminal_descriptors.len(),
381        );
382    }
383}
384
385impl AudioControlInterface {
386    fn new(interfaces: Vec<InterfaceDescriptor, MAX_ALTERNATE_SETTINGS>, header: AudioControlHeaderDescriptor) -> Self {
387        Self {
388            interface_descriptors: interfaces,
389            header_descriptor: header,
390            interrupt_endpoint_descriptor: None,
391            clock_descriptors: FnvIndexMap::new(),
392            unit_descriptors: FnvIndexMap::new(),
393            terminal_descriptors: FnvIndexMap::new(),
394        }
395    }
396
397    fn add_cs_interface(&mut self, raw: &[u8]) -> Result<(), AudioInterfaceError> {
398        match ClockDescriptor::try_from_bytes(raw) {
399            Ok(clock) => {
400                self.clock_descriptors
401                    .insert(clock.clock_id(), clock)
402                    .map_err(|_| AudioInterfaceError::BufferFull("Too many clock descriptors"))?;
403            }
404            Err(AudioInterfaceError::InvalidDescriptor) => {}
405            Err(e) => return Err(e),
406        }
407        if let Ok(terminal) = TerminalDescriptor::try_from_bytes(raw) {
408            self.terminal_descriptors
409                .insert(terminal.terminal_id(), terminal)
410                .map_err(|_| AudioInterfaceError::BufferFull("Too many terminal descriptors"))?;
411        }
412        if let Ok(unit) = UnitDescriptor::try_from_bytes(raw) {
413            self.unit_descriptors
414                .insert(unit.unit_id(), unit)
415                .map_err(|_| AudioInterfaceError::BufferFull("Too many unit descriptors"))?;
416        }
417        Ok(())
418    }
419}
420
421/// Audio control header descriptor containing version and category information.
422#[derive(Debug, PartialEq)]
423#[cfg_attr(feature = "defmt", derive(defmt::Format))]
424pub struct AudioControlHeaderDescriptor {
425    /// Audio device class version (major, minor).
426    pub audio_device_class: (u8, u8),
427    /// Category of the audio device.
428    pub category: u8,
429    /// Bitmap of supported controls.
430    pub controls_bitmap: u8,
431}
432
433impl USBDescriptor for AudioControlHeaderDescriptor {
434    const SIZE: usize = 9;
435    const DESC_TYPE: u8 = CS_INTERFACE;
436    type Error = ();
437
438    fn try_from_bytes(bytes: &[u8]) -> Result<Self, Self::Error> {
439        if bytes.len() < Self::SIZE {
440            return Err(());
441        }
442        if bytes[1] != Self::DESC_TYPE {
443            return Err(());
444        }
445        if bytes[2] != ac_descriptor::HEADER {
446            return Err(());
447        }
448        Ok(Self {
449            audio_device_class: (bytes[4], bytes[3]),
450            category: bytes[5],
451            controls_bitmap: bytes[8],
452        })
453    }
454}
455
456/// Enumeration of clock descriptor types.
457#[derive(Debug, Clone, PartialEq, Eq)]
458#[cfg_attr(feature = "defmt", derive(defmt::Format))]
459pub enum ClockDescriptor {
460    /// Clock source descriptor.
461    Source(ClockSourceDescriptor),
462    /// Clock selector descriptor.
463    Selector(ClockSelectorDescriptor),
464    /// Clock multiplier descriptor.
465    Multiplier(ClockMultiplierDescriptor),
466}
467
468impl ClockDescriptor {
469    fn try_from_bytes(bytes: &[u8]) -> Result<Self, AudioInterfaceError> {
470        if bytes.len() < 4 {
471            return Err(AudioInterfaceError::InvalidDescriptor);
472        }
473        if bytes[1] != CS_INTERFACE {
474            return Err(AudioInterfaceError::InvalidDescriptor);
475        }
476        match bytes[2] {
477            ac_descriptor::CLOCK_SOURCE => Ok(Self::Source(ClockSourceDescriptor::try_from_bytes(bytes)?)),
478            ac_descriptor::CLOCK_SELECTOR => Ok(Self::Selector(ClockSelectorDescriptor::try_from_bytes(bytes)?)),
479            ac_descriptor::CLOCK_MULTIPLIER => Ok(Self::Multiplier(ClockMultiplierDescriptor::try_from_bytes(bytes)?)),
480            _ => Err(AudioInterfaceError::InvalidDescriptor),
481        }
482    }
483
484    /// Returns the clock ID for this descriptor.
485    pub fn clock_id(&self) -> u8 {
486        match self {
487            Self::Source(desc) => desc.clock_id,
488            Self::Selector(desc) => desc.clock_id,
489            Self::Multiplier(desc) => desc.clock_id,
490        }
491    }
492}
493
494/// Clock source descriptor defining an audio clock source.
495#[derive(Debug, Clone, PartialEq, Eq)]
496#[cfg_attr(feature = "defmt", derive(defmt::Format))]
497pub struct ClockSourceDescriptor {
498    /// Unique identifier for this clock source.
499    pub clock_id: u8,
500    /// Bitmap of clock source attributes.
501    pub attributes_bitmap: u8,
502    /// Bitmap of supported controls.
503    pub controls_bitmap: u8,
504    /// Associated terminal ID.
505    pub associated_terminal: u8,
506    /// Index of string descriptor describing this clock source.
507    pub clock_name: StringIndex,
508}
509
510impl USBDescriptor for ClockSourceDescriptor {
511    const SIZE: usize = 8;
512    const DESC_TYPE: u8 = CS_INTERFACE;
513    type Error = AudioInterfaceError;
514
515    fn try_from_bytes(bytes: &[u8]) -> Result<Self, Self::Error> {
516        if bytes.len() < Self::SIZE {
517            return Err(AudioInterfaceError::InvalidDescriptor);
518        }
519        if bytes[1] != Self::DESC_TYPE {
520            return Err(AudioInterfaceError::InvalidDescriptor);
521        }
522        if bytes[2] != ac_descriptor::CLOCK_SOURCE {
523            return Err(AudioInterfaceError::InvalidDescriptor);
524        }
525        Ok(Self {
526            clock_id: bytes[3],
527            attributes_bitmap: bytes[4],
528            controls_bitmap: bytes[5],
529            associated_terminal: bytes[6],
530            clock_name: bytes[7],
531        })
532    }
533}
534
535/// Clock selector descriptor for selecting between multiple clock sources.
536#[derive(Debug, Clone, PartialEq, Eq)]
537#[cfg_attr(feature = "defmt", derive(defmt::Format))]
538pub struct ClockSelectorDescriptor {
539    /// Unique identifier for this clock selector.
540    pub clock_id: u8,
541    /// List of source clock IDs that can be selected.
542    pub source_ids: Vec<u8, MAX_CLOCK_DESCRIPTORS>,
543    /// Bitmap of supported controls.
544    pub controls_bitmap: u8,
545    /// Index of string descriptor describing this clock selector.
546    pub clock_name: StringIndex,
547}
548
549impl ClockSelectorDescriptor {
550    fn try_from_bytes(bytes: &[u8]) -> Result<Self, AudioInterfaceError> {
551        if bytes.len() < 7 {
552            return Err(AudioInterfaceError::InvalidDescriptor);
553        }
554        if bytes[1] != CS_INTERFACE {
555            return Err(AudioInterfaceError::InvalidDescriptor);
556        }
557        if bytes[2] != ac_descriptor::CLOCK_SELECTOR {
558            return Err(AudioInterfaceError::InvalidDescriptor);
559        }
560        let mut source_ids = Vec::new();
561        let num_source_ids = bytes[4] as usize;
562        for i in 0..num_source_ids {
563            source_ids
564                .push(bytes[5 + i])
565                .map_err(|_| AudioInterfaceError::BufferFull("Too many clock source ids"))?;
566        }
567        Ok(Self {
568            clock_id: bytes[3],
569            source_ids,
570            controls_bitmap: bytes[5 + num_source_ids as usize],
571            clock_name: bytes[6 + num_source_ids as usize],
572        })
573    }
574}
575
576/// Clock multiplier descriptor for frequency multiplication.
577#[derive(Debug, Clone, PartialEq, Eq)]
578#[cfg_attr(feature = "defmt", derive(defmt::Format))]
579pub struct ClockMultiplierDescriptor {
580    /// Unique identifier for this clock multiplier.
581    pub clock_id: u8,
582    /// Source clock ID.
583    pub source_id: u8,
584    /// Bitmap of supported controls.
585    pub controls_bitmap: u8,
586    /// Index of string descriptor describing this clock multiplier.
587    pub clock_name: StringIndex,
588}
589
590impl USBDescriptor for ClockMultiplierDescriptor {
591    const SIZE: usize = 7;
592    const DESC_TYPE: u8 = CS_INTERFACE;
593    type Error = AudioInterfaceError;
594
595    fn try_from_bytes(bytes: &[u8]) -> Result<Self, AudioInterfaceError> {
596        if bytes.len() < Self::SIZE {
597            return Err(AudioInterfaceError::InvalidDescriptor);
598        }
599        if bytes[1] != Self::DESC_TYPE {
600            return Err(AudioInterfaceError::InvalidDescriptor);
601        }
602        if bytes[2] != ac_descriptor::CLOCK_MULTIPLIER {
603            return Err(AudioInterfaceError::InvalidDescriptor);
604        }
605        Ok(Self {
606            clock_id: bytes[3],
607            source_id: bytes[4],
608            controls_bitmap: bytes[5],
609            clock_name: bytes[6],
610        })
611    }
612}
613
614/// Enumeration of terminal descriptor types.
615#[derive(Debug, Clone, PartialEq, Eq)]
616#[cfg_attr(feature = "defmt", derive(defmt::Format))]
617pub enum TerminalDescriptor {
618    /// Input terminal descriptor.
619    Input(InputTerminalDescriptor),
620    /// Output terminal descriptor.
621    Output(OutputTerminalDescriptor),
622}
623
624impl TerminalDescriptor {
625    fn try_from_bytes(bytes: &[u8]) -> Result<Self, ()> {
626        if bytes.len() < 3 {
627            return Err(());
628        }
629        if bytes[1] != CS_INTERFACE {
630            return Err(());
631        }
632        match bytes[2] {
633            ac_descriptor::INPUT_TERMINAL => Ok(Self::Input(InputTerminalDescriptor::try_from_bytes(bytes)?)),
634            ac_descriptor::OUTPUT_TERMINAL => Ok(Self::Output(OutputTerminalDescriptor::try_from_bytes(bytes)?)),
635            _ => Err(()),
636        }
637    }
638
639    /// Returns the terminal ID for this descriptor.
640    pub fn terminal_id(&self) -> u8 {
641        match self {
642            Self::Input(desc) => desc.terminal_id,
643            Self::Output(desc) => desc.terminal_id,
644        }
645    }
646
647    /// Returns the terminal type for this descriptor.
648    pub fn terminal_type(&self) -> TerminalType {
649        match self {
650            Self::Input(desc) => desc.terminal_type,
651            Self::Output(desc) => desc.terminal_type,
652        }
653    }
654
655    /// Returns the clock source ID associated with this terminal.
656    pub fn clock_source_id(&self) -> u8 {
657        match self {
658            Self::Input(desc) => desc.clock_source_id,
659            Self::Output(desc) => desc.clock_source_id,
660        }
661    }
662
663    /// Returns the terminal name string index.
664    pub fn terminal_name(&self) -> StringIndex {
665        match self {
666            Self::Input(desc) => desc.terminal_name,
667            Self::Output(desc) => desc.terminal_name,
668        }
669    }
670}
671
672/// Enumeration of terminal types as defined by the USB Audio Class specification.
673#[derive(Debug, Clone, Copy, PartialEq, Eq)]
674#[cfg_attr(feature = "defmt", derive(defmt::Format))]
675pub enum TerminalType {
676    /// Unknown terminal type with raw value.
677    Unknown(u16),
678
679    // USB Terminal Types
680    /// USB undefined terminal.
681    UsbUndefined,
682    /// USB streaming terminal.
683    UsbStreaming,
684    /// USB vendor-specific terminal.
685    UsbVendorSpecific,
686
687    // Input Terminal Types
688    /// Input undefined terminal.
689    InputUndefined,
690    /// Microphone terminal.
691    Microphone,
692    /// Desktop microphone terminal.
693    DesktopMicrophone,
694    /// Personal microphone terminal.
695    PersonalMicrophone,
696    /// Omni-directional microphone terminal.
697    OmniMicrophone,
698    /// Microphone array terminal.
699    MicrophoneArray,
700    /// Processing microphone array terminal.
701    ProcessingMicrophoneArray,
702
703    // Output Terminal Types
704    /// Output undefined terminal.
705    OutputUndefined,
706    /// Speaker terminal.
707    Speaker,
708    /// Headphones terminal.
709    Headphones,
710    /// Head-mounted display audio terminal.
711    HeadMountedDisplay,
712    /// Desktop speaker terminal.
713    DesktopSpeaker,
714    /// Room speaker terminal.
715    RoomSpeaker,
716    /// Communication speaker terminal.
717    CommunicationSpeaker,
718    /// Low frequency effects speaker terminal.
719    LowFrequencyEffectsSpeaker,
720
721    // Bi-directional Terminal Types
722    /// Bi-directional undefined terminal.
723    BiDirectionalUndefined,
724    /// Handset terminal.
725    Handset,
726    /// Headset terminal.
727    Headset,
728    /// Speakerphone terminal.
729    SpeakerPhone,
730    /// Echo suppressing speakerphone terminal.
731    EchoSuppressing,
732    /// Echo canceling speakerphone terminal.
733    EchoCanceling,
734
735    // Telephony Terminal Types
736    /// Telephony undefined terminal.
737    TelephonyUndefined,
738    /// Phone line terminal.
739    PhoneLine,
740    /// Telephone terminal.
741    Telephone,
742    /// Down line phone terminal.
743    DownLinePhone,
744
745    // External Terminal Types
746    /// External undefined terminal.
747    ExternalUndefined,
748    /// Analog connector terminal.
749    AnalogConnector,
750    /// Digital audio interface terminal.
751    DigitalAudioInterface,
752    /// Line connector terminal.
753    LineConnector,
754    /// Legacy audio connector terminal.
755    LegacyAudioConnector,
756    /// SPDIF interface terminal.
757    SpdifInterface,
758    /// DA 1394 stream terminal.
759    Da1394Stream,
760    /// DVD audio stream terminal.
761    DvdAudioStream,
762    /// AVC stream terminal.
763    AvcStream,
764}
765
766fn terminal_type_from_u16(terminal_type: u16) -> TerminalType {
767    use TerminalType::*;
768
769    use crate::class::uac::codes::terminal_type::*;
770
771    match terminal_type {
772        usb::UNDEFINED => UsbUndefined,
773        usb::STREAMING => UsbStreaming,
774        usb::VENDOR_SPECIFIC => UsbVendorSpecific,
775
776        input::UNDEFINED => InputUndefined,
777        input::MICROPHONE => Microphone,
778        input::DESKTOP_MICROPHONE => DesktopMicrophone,
779        input::PERSONAL_MICROPHONE => PersonalMicrophone,
780        input::OMNI_DIRECTIONAL_MICROPHONE => OmniMicrophone,
781        input::MICROPHONE_ARRAY => MicrophoneArray,
782        input::PROCESSING_MICROPHONE_ARRAY => ProcessingMicrophoneArray,
783
784        output::UNDEFINED => OutputUndefined,
785        output::SPEAKER => Speaker,
786        output::HEADPHONES => Headphones,
787        output::HEAD_MOUNTED_DISPLAY_AUDIO => HeadMountedDisplay,
788        output::DESKTOP_SPEAKER => DesktopSpeaker,
789        output::ROOM_SPEAKER => RoomSpeaker,
790        output::COMMUNICATION_SPEAKER => CommunicationSpeaker,
791        output::LOW_FREQUENCY_EFFECTS_SPEAKER => LowFrequencyEffectsSpeaker,
792
793        bidirectional::UNDEFINED => BiDirectionalUndefined,
794        bidirectional::HANDSET => Handset,
795        bidirectional::HEADSET => Headset,
796        bidirectional::SPEAKERPHONE_NO_ECHO => SpeakerPhone,
797        bidirectional::ECHO_SUPPRESSING_SPEAKERPHONE => EchoSuppressing,
798        bidirectional::ECHO_CANCELING_SPEAKERPHONE => EchoCanceling,
799
800        telephony::UNDEFINED => TelephonyUndefined,
801        telephony::PHONE_LINE => PhoneLine,
802        telephony::TELEPHONE => Telephone,
803        telephony::DOWN_LINE_PHONE => DownLinePhone,
804
805        external::UNDEFINED => ExternalUndefined,
806        external::ANALOG_CONNECTOR => AnalogConnector,
807        external::DIGITAL_AUDIO_INTERFACE => DigitalAudioInterface,
808        external::LINE_CONNECTOR => LineConnector,
809        external::LEGACY_AUDIO_CONNECTOR => LegacyAudioConnector,
810        external::SPDIF_INTERFACE => SpdifInterface,
811        external::DA_STREAM_1394 => Da1394Stream,
812        external::DV_STREAM_SOUNDTRACK_1394 => DvdAudioStream,
813        external::ADAT_LIGHTPIPE => AvcStream,
814
815        _ => Unknown(terminal_type),
816    }
817}
818
819/// Input terminal descriptor for audio input sources.
820#[derive(Debug, Clone, PartialEq, Eq)]
821#[cfg_attr(feature = "defmt", derive(defmt::Format))]
822pub struct InputTerminalDescriptor {
823    /// Unique identifier for this input terminal.
824    pub terminal_id: u8,
825    /// Type of this input terminal.
826    pub terminal_type: TerminalType,
827    /// Associated terminal ID.
828    pub associated_terminal_id: u8,
829    /// Clock source ID associated with this terminal.
830    pub clock_source_id: u8,
831    /// Number of channels supported by this terminal.
832    pub num_channels: u8,
833    /// Bitmap of channel configuration.
834    pub channel_config_bitmap: u32,
835    /// Index of string descriptor for channel names.
836    pub channel_names: StringIndex,
837    /// Bitmap of supported controls.
838    pub controls_bitmap: u16,
839    /// Index of string descriptor describing this terminal.
840    pub terminal_name: StringIndex,
841}
842
843impl USBDescriptor for InputTerminalDescriptor {
844    const SIZE: usize = 17;
845    const DESC_TYPE: u8 = CS_INTERFACE;
846    type Error = ();
847
848    fn try_from_bytes(bytes: &[u8]) -> Result<Self, Self::Error> {
849        if bytes.len() != Self::SIZE {
850            return Err(());
851        }
852        if bytes[1] != Self::DESC_TYPE {
853            return Err(());
854        }
855        if bytes[2] != ac_descriptor::INPUT_TERMINAL {
856            return Err(());
857        }
858        Ok(Self {
859            terminal_id: bytes[3],
860            terminal_type: terminal_type_from_u16(u16::from_le_bytes([bytes[4], bytes[5]])),
861            associated_terminal_id: bytes[6],
862            clock_source_id: bytes[7],
863            num_channels: bytes[8],
864            channel_config_bitmap: u32::from_le_bytes([bytes[9], bytes[10], bytes[11], bytes[12]]),
865            channel_names: bytes[13],
866            controls_bitmap: u16::from_le_bytes([bytes[14], bytes[15]]),
867            terminal_name: bytes[16],
868        })
869    }
870}
871
872/// Output terminal descriptor for audio output destinations.
873#[derive(Debug, Clone, PartialEq, Eq)]
874#[cfg_attr(feature = "defmt", derive(defmt::Format))]
875pub struct OutputTerminalDescriptor {
876    /// Unique identifier for this output terminal.
877    pub terminal_id: u8,
878    /// Type of this output terminal.
879    pub terminal_type: TerminalType,
880    /// Associated terminal ID.
881    pub associated_terminal_id: u8,
882    /// Source unit or terminal ID.
883    pub source_id: u8,
884    /// Clock source ID associated with this terminal.
885    pub clock_source_id: u8,
886    /// Bitmap of supported controls.
887    pub controls_bitmap: u16,
888    /// Index of string descriptor describing this terminal.
889    pub terminal_name: StringIndex,
890}
891
892impl USBDescriptor for OutputTerminalDescriptor {
893    const SIZE: usize = 12;
894    const DESC_TYPE: u8 = CS_INTERFACE;
895    type Error = ();
896
897    fn try_from_bytes(bytes: &[u8]) -> Result<Self, Self::Error> {
898        if bytes.len() != Self::SIZE {
899            return Err(());
900        }
901        if bytes[1] != Self::DESC_TYPE {
902            return Err(());
903        }
904        if bytes[2] != ac_descriptor::OUTPUT_TERMINAL {
905            return Err(());
906        }
907        Ok(Self {
908            terminal_id: bytes[3],
909            terminal_type: terminal_type_from_u16(u16::from_le_bytes([bytes[4], bytes[5]])),
910            associated_terminal_id: bytes[6],
911            source_id: bytes[7],
912            clock_source_id: bytes[8],
913            controls_bitmap: u16::from_le_bytes([bytes[9], bytes[10]]),
914            terminal_name: bytes[11],
915        })
916    }
917}
918
919/// Enumeration of unit descriptor types for audio processing units.
920#[derive(Debug, Clone, PartialEq, Eq)]
921#[cfg_attr(feature = "defmt", derive(defmt::Format))]
922pub enum UnitDescriptor {
923    /// Mixer unit with unit ID.
924    Mixer(u8),
925    /// Selector unit with unit ID.
926    Selector(u8),
927    /// Feature unit with unit ID.
928    Feature(u8),
929    /// Processing unit with unit ID.
930    Processing(u8),
931    /// Effect unit with unit ID.
932    Effect(u8),
933    /// Sample rate converter unit with unit ID.
934    SampleRateConverter(u8),
935    /// Extension unit with unit ID.
936    Extension(u8),
937}
938
939impl USBDescriptor for UnitDescriptor {
940    const SIZE: usize = 4; // This is not the true size; Will become variable
941    const DESC_TYPE: u8 = CS_INTERFACE;
942    type Error = ();
943
944    fn try_from_bytes(bytes: &[u8]) -> Result<Self, Self::Error> {
945        if bytes.len() < Self::SIZE {
946            return Err(());
947        }
948        if bytes[1] != Self::DESC_TYPE {
949            return Err(());
950        }
951        match bytes[2] {
952            ac_descriptor::MIXER_UNIT => Ok(Self::Mixer(bytes[3])),
953            ac_descriptor::SELECTOR_UNIT => Ok(Self::Selector(bytes[3])),
954            ac_descriptor::FEATURE_UNIT => Ok(Self::Feature(bytes[3])),
955            ac_descriptor::PROCESSING_UNIT => Ok(Self::Processing(bytes[3])),
956            ac_descriptor::EFFECT_UNIT => Ok(Self::Effect(bytes[3])),
957            ac_descriptor::SAMPLE_RATE_CONVERTER => Ok(Self::SampleRateConverter(bytes[3])),
958            ac_descriptor::EXTENSION_UNIT => Ok(Self::Extension(bytes[3])),
959            _ => Err(()),
960        }
961    }
962}
963
964impl UnitDescriptor {
965    /// Returns the unit ID for this descriptor.
966    pub fn unit_id(&self) -> u8 {
967        match self {
968            Self::Mixer(id) => *id,
969            Self::Selector(id) => *id,
970            Self::Feature(id) => *id,
971            Self::Processing(id) => *id,
972            Self::Effect(id) => *id,
973            Self::SampleRateConverter(id) => *id,
974            Self::Extension(id) => *id,
975        }
976    }
977}
978
979//--------------------------------------------------------------------------------------------------
980// Audio Streaming
981
982/// Audio streaming interface containing streaming-related descriptors.
983///
984/// This struct contains the interface descriptors, class descriptor, endpoint descriptors,
985/// and format type descriptor for an audio streaming interface.
986#[derive(Debug, Clone, PartialEq)]
987#[cfg_attr(feature = "defmt", derive(defmt::Format))]
988pub struct AudioStreamingInterface {
989    /// Interface descriptors for this streaming interface.
990    pub interface_descriptors: Vec<InterfaceDescriptor, MAX_ALTERNATE_SETTINGS>,
991    /// Audio streaming class descriptor.
992    pub class_descriptor: AudioStreamingClassDescriptor,
993    /// Main endpoint descriptor for audio data.
994    pub endpoint_descriptor: Option<EndpointDescriptor>,
995    /// Optional feedback endpoint descriptor for clock synchronization.
996    pub feedback_endpoint_descriptor: Option<EndpointDescriptor>,
997    /// Audio-specific endpoint descriptor.
998    pub audio_endpoint_descriptor: Option<AudioEndpointDescriptor>,
999    /// Format type descriptor defining the audio format.
1000    pub format_type_descriptor: Option<FormatTypeDescriptor>,
1001    // TODO: Encoder, decoder descriptors
1002}
1003
1004impl AudioStreamingInterface {
1005    fn new(
1006        interfaces: Vec<InterfaceDescriptor, MAX_ALTERNATE_SETTINGS>,
1007        class_desc: AudioStreamingClassDescriptor,
1008    ) -> Self {
1009        Self {
1010            interface_descriptors: interfaces,
1011            class_descriptor: class_desc,
1012            endpoint_descriptor: None,
1013            feedback_endpoint_descriptor: None,
1014            audio_endpoint_descriptor: None,
1015            format_type_descriptor: None,
1016        }
1017    }
1018}
1019
1020/// Audio streaming class descriptor containing format and channel information.
1021#[derive(Debug, Clone, PartialEq)]
1022#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1023pub struct AudioStreamingClassDescriptor {
1024    /// Terminal link ID connecting to the control interface.
1025    pub terminal_link_id: u8,
1026    /// Bitmap of supported controls.
1027    pub controls_bitmap: u8,
1028    /// Audio format type supported by this interface.
1029    pub format: format_type::Format,
1030    /// Number of channels supported.
1031    pub num_channels: u8,
1032    /// Bitmap of channel configuration.
1033    pub channel_config_bitmap: u32,
1034    /// Index of string descriptor for channel names.
1035    pub channel_name: StringIndex,
1036}
1037
1038impl USBDescriptor for AudioStreamingClassDescriptor {
1039    const SIZE: usize = 16;
1040    const DESC_TYPE: u8 = CS_INTERFACE;
1041    type Error = ();
1042
1043    fn try_from_bytes(bytes: &[u8]) -> Result<Self, Self::Error> {
1044        if bytes.len() < Self::SIZE {
1045            return Err(());
1046        }
1047        if bytes[1] != Self::DESC_TYPE {
1048            return Err(());
1049        }
1050        if bytes[2] != as_descriptor::GENERAL {
1051            return Err(());
1052        }
1053        let format =
1054            format_type::Format::from_u32(bytes[5], u32::from_le_bytes([bytes[6], bytes[7], bytes[8], bytes[9]]));
1055        if format.is_none() {
1056            error!("Invalid format type descriptor: type {:?}", bytes[5]);
1057            return Err(());
1058        }
1059        Ok(Self {
1060            terminal_link_id: bytes[3],
1061            controls_bitmap: bytes[4],
1062            format: format.unwrap(),
1063            num_channels: bytes[10],
1064            channel_config_bitmap: u32::from_le_bytes([bytes[11], bytes[12], bytes[13], bytes[14]]),
1065            channel_name: bytes[15],
1066        })
1067    }
1068}
1069
1070/// Audio-specific endpoint descriptor containing audio endpoint attributes.
1071#[derive(Debug, Clone, PartialEq)]
1072#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1073pub struct AudioEndpointDescriptor {
1074    /// Bitmap of endpoint attributes.
1075    pub attributes_bitmap: u8,
1076    /// Bitmap of supported controls.
1077    pub controls_bitmap: u8,
1078    /// Units for lock delay (1=milliseconds, 2=samples).
1079    pub lock_delay_units: u8,
1080    /// Lock delay value in the specified units.
1081    pub lock_delay: u16,
1082}
1083
1084impl USBDescriptor for AudioEndpointDescriptor {
1085    const SIZE: usize = 6;
1086    const DESC_TYPE: u8 = descriptor_type::CS_ENDPOINT;
1087    type Error = ();
1088
1089    fn try_from_bytes(bytes: &[u8]) -> Result<Self, Self::Error> {
1090        if bytes.len() < Self::SIZE {
1091            return Err(());
1092        }
1093        if bytes[1] != Self::DESC_TYPE {
1094            return Err(());
1095        }
1096        if bytes[2] != as_descriptor::GENERAL {
1097            return Err(());
1098        }
1099        Ok(Self {
1100            attributes_bitmap: bytes[3],
1101            controls_bitmap: bytes[4],
1102            lock_delay_units: bytes[5],
1103            lock_delay: u16::from_le_bytes([bytes[6], bytes[7]]),
1104        })
1105    }
1106}
1107
1108/// Enumeration of format type descriptors for different audio formats.
1109#[derive(Debug, Clone, PartialEq)]
1110#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1111pub enum FormatTypeDescriptor {
1112    /// Type I format (PCM, PCM8, etc.).
1113    I(FormatTypeI),
1114    /// Type II format (MPEG, AC-3, etc.).
1115    II(FormatTypeII),
1116    /// Type III format (IEC1937_AC-3, IEC1937_MPEG-1_Layer1, etc.).
1117    III(FormatTypeIII),
1118    /// Type IV format.
1119    IV,
1120    /// Extended Type I format.
1121    ExtendedI(FormatTypeExtendedI),
1122    /// Extended Type II format.
1123    ExtendedII(FormatTypeExtendedII),
1124    /// Extended Type III format.
1125    ExtendedIII(FormatTypeExtendedIII),
1126}
1127
1128impl FormatTypeDescriptor {
1129    fn try_from_bytes(bytes: &[u8]) -> Result<Self, ()> {
1130        if bytes.len() < 4 {
1131            // minimum length of a format type descriptor
1132            return Err(());
1133        }
1134        let len = bytes[0] as usize;
1135        if bytes[1] != CS_INTERFACE {
1136            return Err(());
1137        }
1138        if bytes[2] != as_descriptor::FORMAT_TYPE {
1139            return Err(());
1140        }
1141        match bytes[3] {
1142            format_type::I => {
1143                if len != 6 {
1144                    return Err(());
1145                }
1146                Ok(Self::I(FormatTypeI {
1147                    subslot_size: bytes[4],
1148                    bit_resolution: bytes[5],
1149                }))
1150            }
1151            format_type::II => {
1152                if len != 8 {
1153                    return Err(());
1154                }
1155                Ok(Self::II(FormatTypeII {
1156                    max_bit_rate: u16::from_le_bytes([bytes[4], bytes[5]]),
1157                    slots_per_frame: u16::from_le_bytes([bytes[6], bytes[7]]),
1158                }))
1159            }
1160            format_type::III => {
1161                if len != 6 {
1162                    return Err(());
1163                }
1164                Ok(Self::III(FormatTypeIII {
1165                    subslot_size: bytes[4],
1166                    bit_resolution: bytes[5],
1167                }))
1168            }
1169            format_type::IV => Ok(Self::IV),
1170            format_type::EXT_I => {
1171                if len != 9 {
1172                    return Err(());
1173                }
1174                Ok(Self::ExtendedI(FormatTypeExtendedI {
1175                    subslot_size: bytes[4],
1176                    bit_resolution: bytes[5],
1177                    header_length: bytes[6],
1178                    control_size: bytes[7],
1179                    sideband_protocol: bytes[8],
1180                }))
1181            }
1182            format_type::EXT_II => {
1183                if len != 10 {
1184                    return Err(());
1185                }
1186                Ok(Self::ExtendedII(FormatTypeExtendedII {
1187                    max_bit_rate: u16::from_le_bytes([bytes[4], bytes[5]]),
1188                    samples_per_frame: u16::from_le_bytes([bytes[6], bytes[7]]),
1189                    header_length: bytes[8],
1190                    sideband_protocol: bytes[9],
1191                }))
1192            }
1193            format_type::EXT_III => {
1194                if len != 8 {
1195                    return Err(());
1196                }
1197                Ok(Self::ExtendedIII(FormatTypeExtendedIII {
1198                    subslot_size: bytes[4],
1199                    bit_resolution: bytes[5],
1200                    header_length: bytes[6],
1201                    sideband_protocol: bytes[7],
1202                }))
1203            }
1204            _ => Err(()),
1205        }
1206    }
1207}
1208
1209/// Type I format descriptor for PCM-like formats.
1210#[derive(Debug, Clone, PartialEq)]
1211#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1212pub struct FormatTypeI {
1213    /// Size of each subslot in bytes.
1214    pub subslot_size: u8,
1215    /// Bit resolution of the audio data.
1216    pub bit_resolution: u8,
1217}
1218
1219/// Type II format descriptor for compressed formats.
1220#[derive(Debug, Clone, PartialEq)]
1221#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1222pub struct FormatTypeII {
1223    /// Maximum bit rate in bits per second.
1224    pub max_bit_rate: u16,
1225    /// Number of slots per frame.
1226    pub slots_per_frame: u16,
1227}
1228
1229/// Type III format descriptor for IEC formats.
1230#[derive(Debug, Clone, PartialEq)]
1231#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1232pub struct FormatTypeIII {
1233    /// Size of each subslot in bytes.
1234    pub subslot_size: u8,
1235    /// Bit resolution of the audio data.
1236    pub bit_resolution: u8,
1237}
1238
1239/// Extended Type I format descriptor.
1240#[derive(Debug, Clone, PartialEq)]
1241#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1242pub struct FormatTypeExtendedI {
1243    /// Size of each subslot in bytes.
1244    pub subslot_size: u8,
1245    /// Bit resolution of the audio data.
1246    pub bit_resolution: u8,
1247    /// Length of the format-specific header.
1248    pub header_length: u8,
1249    /// Size of control data.
1250    pub control_size: u8,
1251    /// Sideband protocol identifier.
1252    pub sideband_protocol: u8,
1253}
1254
1255/// Extended Type II format descriptor.
1256#[derive(Debug, Clone, PartialEq)]
1257#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1258pub struct FormatTypeExtendedII {
1259    /// Maximum bit rate in bits per second.
1260    pub max_bit_rate: u16,
1261    /// Number of samples per frame.
1262    pub samples_per_frame: u16,
1263    /// Length of the format-specific header.
1264    pub header_length: u8,
1265    /// Sideband protocol identifier.
1266    pub sideband_protocol: u8,
1267}
1268
1269/// Extended Type III format descriptor.
1270#[derive(Debug, Clone, PartialEq)]
1271#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1272pub struct FormatTypeExtendedIII {
1273    /// Size of each subslot in bytes.
1274    pub subslot_size: u8,
1275    /// Bit resolution of the audio data.
1276    pub bit_resolution: u8,
1277    /// Length of the format-specific header.
1278    pub header_length: u8,
1279    /// Sideband protocol identifier.
1280    pub sideband_protocol: u8,
1281}
1282
1283//--------------------------------------------------------------------------------------------------
1284
1285#[cfg(test)]
1286mod test {
1287    use env_logger;
1288    use heapless::Vec;
1289
1290    use super::*;
1291    use crate::descriptor::ConfigurationDescriptor;
1292
1293    #[test]
1294    fn test_parse() {
1295        // Initialize logger
1296        let _ = env_logger::try_init();
1297
1298        let mut buffer: [u8; 512] = [0; 512];
1299        let descriptors = [
1300            8, 11, 0, 4, 1, 0, 32, 0, // Interface Association Descriptor
1301            9, 4, 0, 0, 0, 1, 1, 32, 7, // Audio Control Interface
1302            9, 36, 1, 0, 2, 8, 223, 0, 0, // Audio Control Header Descriptor
1303            8, 36, 10, 40, 1, 7, 0, 16, // Clock Source Descriptor
1304            17, 36, 2, 2, 1, 1, 0, 40, 16, 0, 0, 0, 0, 18, 0, 0, 2, // Input Terminal Descriptor
1305            // Feature Unit Descriptor
1306            74, 36, 6, 10, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1307            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1308            0, 0, 15, //
1309            12, 36, 3, 20, 1, 3, 0, 10, 40, 0, 0, 5, // Output Terminal Descriptor
1310            17, 36, 2, 1, 1, 2, 0, 40, 16, 0, 0, 0, 0, 50, 0, 0, 3, // Input Terminal Descriptor
1311            // Feature Unit Descriptor
1312            74, 36, 6, 11, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1313            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1314            0, 0, 14, //
1315            12, 36, 3, 22, 1, 1, 0, 11, 40, 0, 0, 4, // Output Terminal Descriptor
1316            9, 4, 1, 0, 0, 1, 2, 32, 8, // Audio Streaming Interface Descriptor (Alt Setting 0)
1317            9, 4, 1, 1, 2, 1, 2, 32, 9, // Audio Streaming Interface Descriptor (Alt Setting 1)
1318            16, 36, 1, 2, 0, 1, 1, 0, 0, 0, 16, 0, 0, 0, 0, 18, // AS Interface Descriptor (General)
1319            6, 36, 2, 1, 4, 24, // Format Type Descriptor
1320            7, 5, 1, 5, 0, 2, 1, // Endpoint Descriptor
1321            8, 37, 1, 0, 0, 2, 8, 0, // AS Endpoint Descriptor
1322            7, 5, 129, 17, 4, 0, 4, // Endpoint Descriptor (Feedback)
1323            9, 4, 2, 0, 0, 1, 2, 32, 10, // Audio Streaming Interface Descriptor (Alt Setting 0)
1324            9, 4, 2, 1, 1, 1, 2, 32, 11, // Audio Streaming Interface Descriptor (Alt Setting 1)
1325            16, 36, 1, 22, 0, 1, 1, 0, 0, 0, 16, 0, 0, 0, 0, 50, // AS Interface Descriptor (General)
1326            6, 36, 2, 1, 4, 24, // Format Type Descriptor
1327            7, 5, 130, 5, 0, 2, 1, // Endpoint Descriptor
1328            8, 37, 1, 0, 0, 2, 8, 0, // AS Endpoint Descriptor
1329            9, 4, 3, 0, 0, 1, 1, 0, 0, // Audio Control Interface (UAC 1)
1330            9, 36, 1, 0, 1, 9, 0, 1, 1, // Audio Control Header Descriptor
1331            9, 4, 4, 0, 2, 1, 3, 0, 0, // MIDI Streaming Interface Descriptor
1332            7, 36, 1, 0, 1, 61, 0, // MS Interface Header Descriptor
1333            6, 36, 2, 1, 51, 0, // MIDI IN Jack Descriptor (Embedded)
1334            6, 36, 2, 2, 52, 82, // MIDI IN Jack Descriptor (External)
1335            9, 36, 3, 1, 55, 1, 52, 1, 0, // MIDI OUT Jack Descriptor (Embedded)
1336            9, 36, 3, 2, 56, 1, 51, 1, 83, // MIDI OUT Jack Descriptor (External)
1337            7, 5, 131, 2, 0, 2, 0, // Endpoint Descriptor (OUT)
1338            5, 37, 1, 1, 55, // MS Endpoint Descriptor
1339            7, 5, 2, 2, 0, 2, 0, // Endpoint Descriptor (IN)
1340            5, 37, 1, 1, 51, // MS Endpoint Descriptor
1341            9, 4, 5, 0, 0, 254, 1, 1, 0, // DFU Interface Descriptor
1342            7, 33, 7, 250, 0, 64, 0, // DFU Functional Descriptor
1343        ];
1344        buffer[..descriptors.len()].copy_from_slice(&descriptors);
1345        let descriptor = ConfigurationDescriptor {
1346            len: 0,
1347            descriptor_type: 0,
1348            total_len: 0,
1349            num_interfaces: 0,
1350            configuration_value: 1,
1351            configuration_name: 0,
1352            attributes: 0,
1353            max_power: 0,
1354            buffer: &buffer,
1355        };
1356        let mut expected_clock_descriptors = FnvIndexMap::<u8, ClockDescriptor, MAX_CLOCK_DESCRIPTORS>::new();
1357        let mut expected_unit_descriptors = FnvIndexMap::<u8, UnitDescriptor, MAX_UNIT_DESCRIPTORS>::new();
1358        let mut expected_terminal_descriptors = FnvIndexMap::<u8, TerminalDescriptor, MAX_TERMINAL_DESCRIPTORS>::new();
1359        expected_clock_descriptors
1360            .insert(
1361                40,
1362                ClockDescriptor::Source(ClockSourceDescriptor {
1363                    clock_id: 40,
1364                    attributes_bitmap: 1,
1365                    controls_bitmap: 7,
1366                    associated_terminal: 0,
1367                    clock_name: 16,
1368                }),
1369            )
1370            .unwrap();
1371        expected_unit_descriptors
1372            .insert(10, UnitDescriptor::Feature(10))
1373            .unwrap();
1374        expected_unit_descriptors
1375            .insert(11, UnitDescriptor::Feature(11))
1376            .unwrap();
1377        expected_terminal_descriptors
1378            .insert(
1379                2,
1380                TerminalDescriptor::Input(InputTerminalDescriptor {
1381                    terminal_id: 2,
1382                    terminal_type: TerminalType::UsbStreaming,
1383                    associated_terminal_id: 0,
1384                    clock_source_id: 40,
1385                    num_channels: 16,
1386                    channel_config_bitmap: 0,
1387                    channel_names: 18,
1388                    controls_bitmap: 0,
1389                    terminal_name: 2,
1390                }),
1391            )
1392            .unwrap();
1393        expected_terminal_descriptors
1394            .insert(
1395                20,
1396                TerminalDescriptor::Output(OutputTerminalDescriptor {
1397                    terminal_id: 20,
1398                    terminal_type: TerminalType::Speaker,
1399                    associated_terminal_id: 0,
1400                    source_id: 10,
1401                    clock_source_id: 40,
1402                    controls_bitmap: 0,
1403                    terminal_name: 5,
1404                }),
1405            )
1406            .unwrap();
1407        expected_terminal_descriptors
1408            .insert(
1409                1,
1410                TerminalDescriptor::Input(InputTerminalDescriptor {
1411                    terminal_id: 1,
1412                    terminal_type: TerminalType::Microphone,
1413                    associated_terminal_id: 0,
1414                    clock_source_id: 40,
1415                    num_channels: 16,
1416                    channel_config_bitmap: 0,
1417                    channel_names: 50,
1418                    controls_bitmap: 0,
1419                    terminal_name: 3,
1420                }),
1421            )
1422            .unwrap();
1423        expected_terminal_descriptors
1424            .insert(
1425                22,
1426                TerminalDescriptor::Output(OutputTerminalDescriptor {
1427                    terminal_id: 22,
1428                    terminal_type: TerminalType::UsbStreaming,
1429                    associated_terminal_id: 0,
1430                    source_id: 11,
1431                    clock_source_id: 40,
1432                    controls_bitmap: 0,
1433                    terminal_name: 4,
1434                }),
1435            )
1436            .unwrap();
1437
1438        let expected = AudioInterfaceCollection {
1439            interface_association_descriptor: InterfaceAssociationDescriptor {
1440                first_interface: 0,
1441                num_interfaces: 4,
1442                class: 1,
1443                subclass: 0,
1444                protocol: 32,
1445                interface_name: 0,
1446            },
1447            control_interface: AudioControlInterface {
1448                interface_descriptors: Vec::from_slice(&[InterfaceDescriptor {
1449                    len: 9,
1450                    descriptor_type: 4,
1451                    interface_number: 0,
1452                    alternate_setting: 0,
1453                    num_endpoints: 0,
1454                    interface_class: 1,
1455                    interface_subclass: 1,
1456                    interface_protocol: 32,
1457                    interface_name: 7,
1458                }])
1459                .unwrap(),
1460                header_descriptor: AudioControlHeaderDescriptor {
1461                    audio_device_class: (2, 0),
1462                    category: 8,
1463                    controls_bitmap: 0,
1464                },
1465                interrupt_endpoint_descriptor: None,
1466                clock_descriptors: expected_clock_descriptors,
1467                unit_descriptors: expected_unit_descriptors,
1468                terminal_descriptors: expected_terminal_descriptors,
1469            },
1470            audio_streaming_interfaces: Vec::from_slice(&[
1471                AudioStreamingInterface {
1472                    interface_descriptors: Vec::from_slice(&[
1473                        InterfaceDescriptor {
1474                            len: 9,
1475                            descriptor_type: 4,
1476                            interface_number: 1,
1477                            alternate_setting: 0,
1478                            num_endpoints: 0,
1479                            interface_class: 1,
1480                            interface_subclass: 2,
1481                            interface_protocol: 32,
1482                            interface_name: 8,
1483                        },
1484                        InterfaceDescriptor {
1485                            len: 9,
1486                            descriptor_type: 4,
1487                            interface_number: 1,
1488                            alternate_setting: 1,
1489                            num_endpoints: 2,
1490                            interface_class: 1,
1491                            interface_subclass: 2,
1492                            interface_protocol: 32,
1493                            interface_name: 9,
1494                        },
1495                    ])
1496                    .unwrap(),
1497                    class_descriptor: AudioStreamingClassDescriptor {
1498                        terminal_link_id: 2,
1499                        controls_bitmap: 0,
1500                        format: format_type::Format::Type1(format_type::Type1::PCM),
1501                        num_channels: 16,
1502                        channel_config_bitmap: 0,
1503                        channel_name: 18,
1504                    },
1505                    endpoint_descriptor: Some(EndpointDescriptor {
1506                        len: 7,
1507                        descriptor_type: 5,
1508                        endpoint_address: 1,
1509                        attributes: 5,
1510                        max_packet_size: 512,
1511                        interval: 1,
1512                    }),
1513                    feedback_endpoint_descriptor: Some(EndpointDescriptor {
1514                        len: 7,
1515                        descriptor_type: 5,
1516                        endpoint_address: 129,
1517                        attributes: 17,
1518                        max_packet_size: 4,
1519                        interval: 4,
1520                    }),
1521                    audio_endpoint_descriptor: Some(AudioEndpointDescriptor {
1522                        attributes_bitmap: 0,
1523                        controls_bitmap: 0,
1524                        lock_delay_units: 2,
1525                        lock_delay: 8,
1526                    }),
1527                    format_type_descriptor: Some(FormatTypeDescriptor::I(FormatTypeI {
1528                        subslot_size: 4,
1529                        bit_resolution: 24,
1530                    })),
1531                },
1532                AudioStreamingInterface {
1533                    interface_descriptors: Vec::from_slice(&[
1534                        InterfaceDescriptor {
1535                            len: 9,
1536                            descriptor_type: 4,
1537                            interface_number: 2,
1538                            alternate_setting: 0,
1539                            num_endpoints: 0,
1540                            interface_class: 1,
1541                            interface_subclass: 2,
1542                            interface_protocol: 32,
1543                            interface_name: 10,
1544                        },
1545                        InterfaceDescriptor {
1546                            len: 9,
1547                            descriptor_type: 4,
1548                            interface_number: 2,
1549                            alternate_setting: 1,
1550                            num_endpoints: 1,
1551                            interface_class: 1,
1552                            interface_subclass: 2,
1553                            interface_protocol: 32,
1554                            interface_name: 11,
1555                        },
1556                    ])
1557                    .unwrap(),
1558                    class_descriptor: AudioStreamingClassDescriptor {
1559                        terminal_link_id: 22,
1560                        controls_bitmap: 0,
1561                        format: format_type::Format::Type1(format_type::Type1::PCM),
1562                        num_channels: 16,
1563                        channel_config_bitmap: 0,
1564                        channel_name: 50,
1565                    },
1566                    endpoint_descriptor: Some(EndpointDescriptor {
1567                        len: 7,
1568                        descriptor_type: 5,
1569                        endpoint_address: 130,
1570                        attributes: 5,
1571                        max_packet_size: 512,
1572                        interval: 1,
1573                    }),
1574                    feedback_endpoint_descriptor: None,
1575                    audio_endpoint_descriptor: Some(AudioEndpointDescriptor {
1576                        attributes_bitmap: 0,
1577                        controls_bitmap: 0,
1578                        lock_delay_units: 2,
1579                        lock_delay: 8,
1580                    }),
1581                    format_type_descriptor: Some(FormatTypeDescriptor::I(FormatTypeI {
1582                        subslot_size: 4,
1583                        bit_resolution: 24,
1584                    })),
1585                },
1586            ])
1587            .unwrap(),
1588        };
1589        let audio_interface_collection = AudioInterfaceCollection::try_from_configuration(&descriptor).unwrap();
1590        // info!("{:#?}", audio_interface_collection);
1591        assert_eq!(audio_interface_collection, expected);
1592    }
1593}