1use 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#[derive(Debug, PartialEq)]
24#[cfg_attr(feature = "defmt", derive(defmt::Format))]
25pub struct AudioInterfaceCollection {
26 pub interface_association_descriptor: InterfaceAssociationDescriptor,
28 pub control_interface: AudioControlInterface,
30 pub audio_streaming_interfaces: Vec<AudioStreamingInterface, MAX_AUDIO_STREAMING_INTERFACES>,
32}
33
34#[derive(Debug, PartialEq)]
36#[cfg_attr(feature = "defmt", derive(defmt::Format))]
37pub enum AudioInterfaceError {
38 BufferFull(&'static str),
40 MissingControlInterface,
42 MissingControlInterfaceHeader,
44 InvalidDescriptor,
46 NoAudioConfiguration,
48 MissingAudioStreamingClassDescriptor,
50}
51
52struct AudioCollectionBuilder {
53 iad: Option<InterfaceAssociationDescriptor>,
54 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; }
96
97 if iface.interface_class != interface::AUDIO {
98 return true; }
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 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 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#[derive(Debug, PartialEq)]
259#[cfg_attr(feature = "defmt", derive(defmt::Format))]
260pub struct InterfaceAssociationDescriptor {
261 pub first_interface: u8,
263 pub num_interfaces: u8,
265 pub class: u8,
267 pub subclass: u8,
269 pub protocol: u8,
271 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 pub fn is_audio_association(&self) -> bool {
301 self.class == AUDIO_FUNCTION && self.protocol == function_protocol::AF_VERSION_02_00
302 }
303}
304
305#[derive(Copy, Clone, Debug, PartialEq)]
307#[cfg_attr(feature = "defmt", derive(defmt::Format))]
308pub struct InterfaceDescriptor {
309 pub len: u8,
311 pub descriptor_type: u8,
313 pub interface_number: u8,
315 pub alternate_setting: u8,
317 pub num_endpoints: u8,
319 pub interface_class: u8,
321 pub interface_subclass: u8,
323 pub interface_protocol: u8,
325 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#[derive(Debug, PartialEq)]
353pub struct AudioControlInterface {
354 pub interface_descriptors: Vec<InterfaceDescriptor, MAX_ALTERNATE_SETTINGS>,
356 pub header_descriptor: AudioControlHeaderDescriptor,
358 pub interrupt_endpoint_descriptor: Option<EndpointDescriptor>,
360 pub clock_descriptors: FnvIndexMap<u8, ClockDescriptor, MAX_CLOCK_DESCRIPTORS>,
362 pub unit_descriptors: FnvIndexMap<u8, UnitDescriptor, MAX_UNIT_DESCRIPTORS>,
364 pub terminal_descriptors: FnvIndexMap<u8, TerminalDescriptor, MAX_TERMINAL_DESCRIPTORS>,
366}
367
368#[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#[derive(Debug, PartialEq)]
423#[cfg_attr(feature = "defmt", derive(defmt::Format))]
424pub struct AudioControlHeaderDescriptor {
425 pub audio_device_class: (u8, u8),
427 pub category: u8,
429 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#[derive(Debug, Clone, PartialEq, Eq)]
458#[cfg_attr(feature = "defmt", derive(defmt::Format))]
459pub enum ClockDescriptor {
460 Source(ClockSourceDescriptor),
462 Selector(ClockSelectorDescriptor),
464 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 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#[derive(Debug, Clone, PartialEq, Eq)]
496#[cfg_attr(feature = "defmt", derive(defmt::Format))]
497pub struct ClockSourceDescriptor {
498 pub clock_id: u8,
500 pub attributes_bitmap: u8,
502 pub controls_bitmap: u8,
504 pub associated_terminal: u8,
506 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#[derive(Debug, Clone, PartialEq, Eq)]
537#[cfg_attr(feature = "defmt", derive(defmt::Format))]
538pub struct ClockSelectorDescriptor {
539 pub clock_id: u8,
541 pub source_ids: Vec<u8, MAX_CLOCK_DESCRIPTORS>,
543 pub controls_bitmap: u8,
545 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#[derive(Debug, Clone, PartialEq, Eq)]
578#[cfg_attr(feature = "defmt", derive(defmt::Format))]
579pub struct ClockMultiplierDescriptor {
580 pub clock_id: u8,
582 pub source_id: u8,
584 pub controls_bitmap: u8,
586 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#[derive(Debug, Clone, PartialEq, Eq)]
616#[cfg_attr(feature = "defmt", derive(defmt::Format))]
617pub enum TerminalDescriptor {
618 Input(InputTerminalDescriptor),
620 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 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 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 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 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#[derive(Debug, Clone, Copy, PartialEq, Eq)]
674#[cfg_attr(feature = "defmt", derive(defmt::Format))]
675pub enum TerminalType {
676 Unknown(u16),
678
679 UsbUndefined,
682 UsbStreaming,
684 UsbVendorSpecific,
686
687 InputUndefined,
690 Microphone,
692 DesktopMicrophone,
694 PersonalMicrophone,
696 OmniMicrophone,
698 MicrophoneArray,
700 ProcessingMicrophoneArray,
702
703 OutputUndefined,
706 Speaker,
708 Headphones,
710 HeadMountedDisplay,
712 DesktopSpeaker,
714 RoomSpeaker,
716 CommunicationSpeaker,
718 LowFrequencyEffectsSpeaker,
720
721 BiDirectionalUndefined,
724 Handset,
726 Headset,
728 SpeakerPhone,
730 EchoSuppressing,
732 EchoCanceling,
734
735 TelephonyUndefined,
738 PhoneLine,
740 Telephone,
742 DownLinePhone,
744
745 ExternalUndefined,
748 AnalogConnector,
750 DigitalAudioInterface,
752 LineConnector,
754 LegacyAudioConnector,
756 SpdifInterface,
758 Da1394Stream,
760 DvdAudioStream,
762 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#[derive(Debug, Clone, PartialEq, Eq)]
821#[cfg_attr(feature = "defmt", derive(defmt::Format))]
822pub struct InputTerminalDescriptor {
823 pub terminal_id: u8,
825 pub terminal_type: TerminalType,
827 pub associated_terminal_id: u8,
829 pub clock_source_id: u8,
831 pub num_channels: u8,
833 pub channel_config_bitmap: u32,
835 pub channel_names: StringIndex,
837 pub controls_bitmap: u16,
839 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#[derive(Debug, Clone, PartialEq, Eq)]
874#[cfg_attr(feature = "defmt", derive(defmt::Format))]
875pub struct OutputTerminalDescriptor {
876 pub terminal_id: u8,
878 pub terminal_type: TerminalType,
880 pub associated_terminal_id: u8,
882 pub source_id: u8,
884 pub clock_source_id: u8,
886 pub controls_bitmap: u16,
888 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#[derive(Debug, Clone, PartialEq, Eq)]
921#[cfg_attr(feature = "defmt", derive(defmt::Format))]
922pub enum UnitDescriptor {
923 Mixer(u8),
925 Selector(u8),
927 Feature(u8),
929 Processing(u8),
931 Effect(u8),
933 SampleRateConverter(u8),
935 Extension(u8),
937}
938
939impl USBDescriptor for UnitDescriptor {
940 const SIZE: usize = 4; 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 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#[derive(Debug, Clone, PartialEq)]
987#[cfg_attr(feature = "defmt", derive(defmt::Format))]
988pub struct AudioStreamingInterface {
989 pub interface_descriptors: Vec<InterfaceDescriptor, MAX_ALTERNATE_SETTINGS>,
991 pub class_descriptor: AudioStreamingClassDescriptor,
993 pub endpoint_descriptor: Option<EndpointDescriptor>,
995 pub feedback_endpoint_descriptor: Option<EndpointDescriptor>,
997 pub audio_endpoint_descriptor: Option<AudioEndpointDescriptor>,
999 pub format_type_descriptor: Option<FormatTypeDescriptor>,
1001 }
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#[derive(Debug, Clone, PartialEq)]
1022#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1023pub struct AudioStreamingClassDescriptor {
1024 pub terminal_link_id: u8,
1026 pub controls_bitmap: u8,
1028 pub format: format_type::Format,
1030 pub num_channels: u8,
1032 pub channel_config_bitmap: u32,
1034 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#[derive(Debug, Clone, PartialEq)]
1072#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1073pub struct AudioEndpointDescriptor {
1074 pub attributes_bitmap: u8,
1076 pub controls_bitmap: u8,
1078 pub lock_delay_units: u8,
1080 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#[derive(Debug, Clone, PartialEq)]
1110#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1111pub enum FormatTypeDescriptor {
1112 I(FormatTypeI),
1114 II(FormatTypeII),
1116 III(FormatTypeIII),
1118 IV,
1120 ExtendedI(FormatTypeExtendedI),
1122 ExtendedII(FormatTypeExtendedII),
1124 ExtendedIII(FormatTypeExtendedIII),
1126}
1127
1128impl FormatTypeDescriptor {
1129 fn try_from_bytes(bytes: &[u8]) -> Result<Self, ()> {
1130 if bytes.len() < 4 {
1131 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#[derive(Debug, Clone, PartialEq)]
1211#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1212pub struct FormatTypeI {
1213 pub subslot_size: u8,
1215 pub bit_resolution: u8,
1217}
1218
1219#[derive(Debug, Clone, PartialEq)]
1221#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1222pub struct FormatTypeII {
1223 pub max_bit_rate: u16,
1225 pub slots_per_frame: u16,
1227}
1228
1229#[derive(Debug, Clone, PartialEq)]
1231#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1232pub struct FormatTypeIII {
1233 pub subslot_size: u8,
1235 pub bit_resolution: u8,
1237}
1238
1239#[derive(Debug, Clone, PartialEq)]
1241#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1242pub struct FormatTypeExtendedI {
1243 pub subslot_size: u8,
1245 pub bit_resolution: u8,
1247 pub header_length: u8,
1249 pub control_size: u8,
1251 pub sideband_protocol: u8,
1253}
1254
1255#[derive(Debug, Clone, PartialEq)]
1257#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1258pub struct FormatTypeExtendedII {
1259 pub max_bit_rate: u16,
1261 pub samples_per_frame: u16,
1263 pub header_length: u8,
1265 pub sideband_protocol: u8,
1267}
1268
1269#[derive(Debug, Clone, PartialEq)]
1271#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1272pub struct FormatTypeExtendedIII {
1273 pub subslot_size: u8,
1275 pub bit_resolution: u8,
1277 pub header_length: u8,
1279 pub sideband_protocol: u8,
1281}
1282
1283#[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 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, 9, 4, 0, 0, 0, 1, 1, 32, 7, 9, 36, 1, 0, 2, 8, 223, 0, 0, 8, 36, 10, 40, 1, 7, 0, 16, 17, 36, 2, 2, 1, 1, 0, 40, 16, 0, 0, 0, 0, 18, 0, 0, 2, 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, 12, 36, 3, 20, 1, 3, 0, 10, 40, 0, 0, 5, 17, 36, 2, 1, 1, 2, 0, 40, 16, 0, 0, 0, 0, 50, 0, 0, 3, 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, 12, 36, 3, 22, 1, 1, 0, 11, 40, 0, 0, 4, 9, 4, 1, 0, 0, 1, 2, 32, 8, 9, 4, 1, 1, 2, 1, 2, 32, 9, 16, 36, 1, 2, 0, 1, 1, 0, 0, 0, 16, 0, 0, 0, 0, 18, 6, 36, 2, 1, 4, 24, 7, 5, 1, 5, 0, 2, 1, 8, 37, 1, 0, 0, 2, 8, 0, 7, 5, 129, 17, 4, 0, 4, 9, 4, 2, 0, 0, 1, 2, 32, 10, 9, 4, 2, 1, 1, 1, 2, 32, 11, 16, 36, 1, 22, 0, 1, 1, 0, 0, 0, 16, 0, 0, 0, 0, 50, 6, 36, 2, 1, 4, 24, 7, 5, 130, 5, 0, 2, 1, 8, 37, 1, 0, 0, 2, 8, 0, 9, 4, 3, 0, 0, 1, 1, 0, 0, 9, 36, 1, 0, 1, 9, 0, 1, 1, 9, 4, 4, 0, 2, 1, 3, 0, 0, 7, 36, 1, 0, 1, 61, 0, 6, 36, 2, 1, 51, 0, 6, 36, 2, 2, 52, 82, 9, 36, 3, 1, 55, 1, 52, 1, 0, 9, 36, 3, 2, 56, 1, 51, 1, 83, 7, 5, 131, 2, 0, 2, 0, 5, 37, 1, 1, 55, 7, 5, 2, 2, 0, 2, 0, 5, 37, 1, 1, 51, 9, 4, 5, 0, 0, 254, 1, 1, 0, 7, 33, 7, 250, 0, 64, 0, ];
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 assert_eq!(audio_interface_collection, expected);
1592 }
1593}