Skip to main content

embassy_usb_host/
descriptor.rs

1//! USB descriptor parsers.
2#![allow(missing_docs)]
3
4use embassy_usb_driver::host::HostError;
5use embassy_usb_driver::{Direction, EndpointInfo, EndpointType};
6
7/// Standard descriptor type constants.
8pub mod descriptor_type {
9    pub const DEVICE: u8 = 0x01;
10    pub const CONFIGURATION: u8 = 0x02;
11    pub const INTERFACE: u8 = 0x04;
12    pub const ENDPOINT: u8 = 0x05;
13
14    pub const INTERFACE_ASSOCIATION: u8 = 0x0B;
15    pub const CS_INTERFACE: u8 = 0x24;
16    pub const CS_ENDPOINT: u8 = 0x25;
17}
18
19pub type StringIndex = u8;
20
21/// Maximum descriptor buffer size used during enumeration.
22pub(crate) const DEFAULT_MAX_DESCRIPTOR_SIZE: usize = 512;
23
24#[derive(Debug)]
25#[cfg_attr(feature = "defmt", derive(defmt::Format))]
26pub enum DescriptorError {
27    BadDescriptorType,
28    UnexpectedEndOfBuffer,
29}
30
31/// Error returned by [`ConfigurationDescriptor::visit_descriptors`].
32#[derive(Debug)]
33#[cfg_attr(feature = "defmt", derive(defmt::Format))]
34pub enum VisitError<E> {
35    /// An interface or endpoint descriptor in the configuration buffer was malformed.
36    BadDescriptor,
37    /// The visitor itself returned an error.
38    Visitor(E),
39}
40
41/// Trait for fixed-size USB descriptors that can be parsed from a byte slice.
42pub trait USBDescriptor {
43    const SIZE: usize;
44    const DESC_TYPE: u8;
45    type Error;
46    fn try_from_bytes(bytes: &[u8]) -> Result<Self, Self::Error>
47    where
48        Self: Sized;
49}
50
51/// First 8 bytes of the DeviceDescriptor, used to read `max_packet_size0` before SET_ADDRESS.
52#[derive(Debug)]
53pub struct DeviceDescriptorPartial {
54    _padding: [u8; 7],
55    pub max_packet_size0: u8,
56}
57
58impl USBDescriptor for DeviceDescriptorPartial {
59    const SIZE: usize = 8;
60    const DESC_TYPE: u8 = descriptor_type::DEVICE;
61    type Error = ();
62
63    fn try_from_bytes(bytes: &[u8]) -> Result<Self, Self::Error> {
64        if bytes.len() < Self::SIZE || bytes[1] != Self::DESC_TYPE {
65            return Err(());
66        }
67        Ok(Self {
68            _padding: [0; 7],
69            max_packet_size0: bytes[7],
70        })
71    }
72}
73
74/// USB Device Descriptor (18 bytes).
75#[derive(Copy, Clone, Debug)]
76#[cfg_attr(feature = "defmt", derive(defmt::Format))]
77pub struct DeviceDescriptor {
78    pub len: u8,
79    pub descriptor_type: u8,
80    pub bcd_usb: u16,
81    pub device_class: u8,
82    pub device_subclass: u8,
83    pub device_protocol: u8,
84    pub max_packet_size0: u8,
85    pub vendor_id: u16,
86    pub product_id: u16,
87    pub bcd_device: u16,
88    pub manufacturer: StringIndex,
89    pub product: StringIndex,
90    pub serial_number: StringIndex,
91    pub num_configurations: u8,
92}
93
94impl USBDescriptor for DeviceDescriptor {
95    const SIZE: usize = 18;
96    const DESC_TYPE: u8 = descriptor_type::DEVICE;
97    type Error = ();
98
99    fn try_from_bytes(bytes: &[u8]) -> Result<Self, Self::Error> {
100        if bytes.len() < Self::SIZE || bytes[1] != Self::DESC_TYPE {
101            return Err(());
102        }
103        Ok(Self {
104            len: bytes[0],
105            descriptor_type: bytes[1],
106            bcd_usb: u16::from_le_bytes([bytes[2], bytes[3]]),
107            device_class: bytes[4],
108            device_subclass: bytes[5],
109            device_protocol: bytes[6],
110            max_packet_size0: bytes[7],
111            vendor_id: u16::from_le_bytes([bytes[8], bytes[9]]),
112            product_id: u16::from_le_bytes([bytes[10], bytes[11]]),
113            bcd_device: u16::from_le_bytes([bytes[12], bytes[13]]),
114            manufacturer: bytes[14],
115            product: bytes[15],
116            serial_number: bytes[16],
117            num_configurations: bytes[17],
118        })
119    }
120}
121
122/// USB Configuration Descriptor header with a reference to the sub-descriptor buffer.
123#[derive(Copy, Clone, Debug)]
124#[cfg_attr(feature = "defmt", derive(defmt::Format))]
125pub struct ConfigurationDescriptor<'a> {
126    pub len: u8,
127    pub descriptor_type: u8,
128    pub total_len: u16,
129    pub num_interfaces: u8,
130    pub configuration_value: u8,
131    pub configuration_name: StringIndex,
132    pub attributes: u8,
133    pub max_power: u8,
134    /// The raw bytes following the 9-byte header (interface + endpoint descriptors).
135    pub buffer: &'a [u8],
136}
137
138impl USBDescriptor for ConfigurationDescriptor<'_> {
139    const SIZE: usize = 9;
140    const DESC_TYPE: u8 = descriptor_type::CONFIGURATION;
141    type Error = ();
142
143    fn try_from_bytes(bytes: &[u8]) -> Result<Self, Self::Error> {
144        if bytes.len() < Self::SIZE || bytes[1] != Self::DESC_TYPE {
145            return Err(());
146        }
147        Ok(Self {
148            len: bytes[0],
149            descriptor_type: bytes[1],
150            total_len: u16::from_le_bytes([bytes[2], bytes[3]]),
151            num_interfaces: bytes[4],
152            configuration_value: bytes[5],
153            configuration_name: bytes[6],
154            attributes: bytes[7],
155            max_power: bytes[8],
156            buffer: &[],
157        })
158    }
159}
160
161impl<'a> ConfigurationDescriptor<'a> {
162    /// Parse a full Configuration Descriptor blob, giving access to sub-descriptors via iterators.
163    pub fn try_from_slice(buf: &'a [u8]) -> Result<Self, HostError> {
164        if buf.len() < Self::SIZE || buf[1] != Self::DESC_TYPE {
165            return Err(HostError::InvalidDescriptor);
166        }
167        let total_length = u16::from_le_bytes([buf[2], buf[3]]);
168        Ok(Self {
169            len: buf[0],
170            descriptor_type: buf[1],
171            total_len: total_length,
172            num_interfaces: buf[4],
173            configuration_value: buf[5],
174            configuration_name: buf[6],
175            attributes: buf[7],
176            max_power: buf[8],
177            buffer: &buf[buf[0] as usize..total_length as usize],
178        })
179    }
180
181    /// Iterate over all raw descriptors in this Configuration.
182    pub fn iter_descriptors(&self) -> RawDescriptorIterator<'a> {
183        RawDescriptorIterator {
184            buf: self.buffer,
185            offset: 0,
186        }
187    }
188
189    /// Iterate over all interface descriptors of this Configuration.
190    pub fn iter_interface(&self) -> InterfaceIterator<'_> {
191        let first_interface_offset = self
192            .iter_descriptors()
193            .find_map(|(offset, bytes)| {
194                if bytes[1] == descriptor_type::INTERFACE {
195                    Some(offset)
196                } else {
197                    None
198                }
199            })
200            .unwrap_or(0);
201        InterfaceIterator {
202            offset: first_interface_offset,
203            cfg_desc: self,
204        }
205    }
206
207    /// Iterate over all descriptors of this Configuration, passing to Visitor callbacks.
208    /// Returns `Ok(())` on completion (including early stop), or `Err(e)` on error.
209    pub fn visit_descriptors<V: DescriptorVisitor<'a>>(&self, visitor: &mut V) -> Result<(), VisitError<V::Error>> {
210        if !visitor.on_configuration(self) {
211            return Ok(());
212        }
213        let mut current_iface: Option<InterfaceDescriptor<'a>> = None;
214        for (_, bytes) in self.iter_descriptors() {
215            if bytes.len() < 2 {
216                continue;
217            }
218            match bytes[1] {
219                descriptor_type::INTERFACE => {
220                    let iface = InterfaceDescriptor::try_from_bytes(bytes).map_err(|_| VisitError::BadDescriptor)?;
221                    current_iface = Some(iface);
222                    if !visitor.on_interface(&iface) {
223                        return Ok(());
224                    }
225                }
226                descriptor_type::ENDPOINT => {
227                    let ep = EndpointDescriptor::try_from_bytes(bytes).map_err(|_| VisitError::BadDescriptor)?;
228                    if let Some(iface) = current_iface.as_ref() {
229                        if !visitor.on_endpoint(iface, &ep) {
230                            return Ok(());
231                        }
232                    }
233                }
234                _ => {
235                    if !visitor
236                        .on_other(current_iface.as_ref(), bytes)
237                        .map_err(VisitError::Visitor)?
238                    {
239                        return Ok(());
240                    }
241                }
242            }
243        }
244        Ok(())
245    }
246}
247
248/// Callback-based visitor for a configuration's descriptor tree.
249///
250/// Implement only the methods you care about.
251pub trait DescriptorVisitor<'a> {
252    type Error;
253
254    /// Return `false` to stop iteration early
255    fn on_configuration(&mut self, _c: &ConfigurationDescriptor<'a>) -> bool {
256        true
257    }
258
259    /// Return `false` to stop iteration early
260    fn on_interface(&mut self, _i: &InterfaceDescriptor<'a>) -> bool {
261        true
262    }
263
264    /// Return `false` to stop iteration early
265    fn on_endpoint(&mut self, _iface: &InterfaceDescriptor<'a>, _e: &EndpointDescriptor) -> bool {
266        true
267    }
268
269    /// Catches every sub-descriptor that isn't an interface or endpoint:
270    /// CS_INTERFACE, CS_ENDPOINT, HID, vendor-specific, etc.
271    /// Return `Ok(false)` to stop iteration early without an error, or `Err(e)` to stop with one.
272    fn on_other(&mut self, _iface: Option<&InterfaceDescriptor<'a>>, _raw: &[u8]) -> Result<bool, Self::Error> {
273        Ok(true)
274    }
275}
276
277/// [`A DescriptorVisitor`] that just logs the descriptors to the debug stream
278pub struct ShowDescriptors;
279
280impl<'a> DescriptorVisitor<'a> for ShowDescriptors {
281    type Error = core::convert::Infallible;
282
283    fn on_configuration(&mut self, c: &ConfigurationDescriptor) -> bool {
284        debug!("{:?}", c);
285        true
286    }
287    fn on_interface(&mut self, i: &InterfaceDescriptor) -> bool {
288        debug!("  {:?}", i);
289        true
290    }
291    fn on_endpoint(&mut self, _i: &InterfaceDescriptor, e: &EndpointDescriptor) -> bool {
292        debug!("    {:?}", e);
293        true
294    }
295    fn on_other(&mut self, _i: Option<&InterfaceDescriptor>, d: &[u8]) -> Result<bool, Self::Error> {
296        let dlen = d[0];
297        let dtype = d[1];
298        let domain = match dtype & 0x60 {
299            0x00 => "standard",
300            0x20 => "class",
301            0x40 => "vendor",
302            _ => "reserved",
303        };
304        debug!("  {} type 0x{:02X} len {}", domain, dtype, dlen);
305        Ok(true)
306    }
307}
308
309/// USB Interface Descriptor with a reference to the trailing sub-descriptor buffer.
310#[derive(Copy, Clone, Debug)]
311#[cfg_attr(feature = "defmt", derive(defmt::Format))]
312pub struct InterfaceDescriptor<'a> {
313    pub len: u8,
314    pub descriptor_type: u8,
315    pub interface_number: u8,
316    pub alternate_setting: u8,
317    pub num_endpoints: u8,
318    pub interface_class: u8,
319    pub interface_subclass: u8,
320    pub interface_protocol: u8,
321    pub interface_name: StringIndex,
322    /// All bytes following this descriptor up to (but not including) the next interface descriptor.
323    pub buffer: &'a [u8],
324}
325
326impl<'a> InterfaceDescriptor<'a> {
327    const SIZE: usize = 9;
328    const DESC_TYPE: u8 = descriptor_type::INTERFACE;
329
330    pub(crate) fn try_from_bytes(bytes: &'a [u8]) -> Result<Self, ()> {
331        if bytes.len() < Self::SIZE || bytes[1] != Self::DESC_TYPE {
332            return Err(());
333        }
334        let endpoints = &bytes[bytes[0] as usize..];
335        let mut raw = RawDescriptorIterator {
336            buf: endpoints,
337            offset: 0,
338        };
339        let next_iface_index = raw
340            .find_map(|(index, v)| v.get(1).is_some_and(|v| *v == Self::DESC_TYPE).then_some(index))
341            .unwrap_or(endpoints.len());
342        Ok(Self {
343            len: bytes[0],
344            descriptor_type: bytes[1],
345            interface_number: bytes[2],
346            alternate_setting: bytes[3],
347            num_endpoints: bytes[4],
348            interface_class: bytes[5],
349            interface_subclass: bytes[6],
350            interface_protocol: bytes[7],
351            interface_name: bytes[8],
352            buffer: &endpoints[..next_iface_index],
353        })
354    }
355
356    /// Iterate over raw descriptors inside this interface.
357    pub fn iter_descriptors(&self) -> RawDescriptorIterator<'_> {
358        RawDescriptorIterator {
359            buf: self.buffer,
360            offset: 0,
361        }
362    }
363
364    /// Iterate over endpoint descriptors inside this interface.
365    pub fn iter_endpoints(&'a self) -> EndpointIterator<'a> {
366        EndpointIterator {
367            index: 0,
368            buffer_idx: 0,
369            iface_desc: self,
370        }
371    }
372}
373
374/// Iterates over the InterfaceDescriptors of a configuration.
375pub struct InterfaceIterator<'a> {
376    offset: usize,
377    cfg_desc: &'a ConfigurationDescriptor<'a>,
378}
379
380impl<'a> Iterator for InterfaceIterator<'a> {
381    type Item = InterfaceDescriptor<'a>;
382
383    fn next(&mut self) -> Option<Self::Item> {
384        if self.offset >= self.cfg_desc.buffer.len() {
385            return None;
386        }
387        let remaining = &self.cfg_desc.buffer[self.offset..];
388        let iface = InterfaceDescriptor::try_from_bytes(remaining).ok()?;
389        self.offset += iface.len as usize + iface.buffer.len();
390        Some(iface)
391    }
392}
393
394/// Iterates over raw descriptors, yielding `(byte_offset, &[u8])`.
395pub struct RawDescriptorIterator<'a> {
396    buf: &'a [u8],
397    offset: usize,
398}
399
400impl<'a> Iterator for RawDescriptorIterator<'a> {
401    type Item = (usize, &'a [u8]);
402
403    fn next(&mut self) -> Option<Self::Item> {
404        if self.offset >= self.buf.len() {
405            return None;
406        }
407        let pre = self.offset;
408        let len = self.buf[pre] as usize;
409        if len == 0 {
410            return None;
411        }
412        self.offset += len;
413        if self.offset > self.buf.len() {
414            return None;
415        }
416        Some((pre, &self.buf[pre..self.offset]))
417    }
418}
419
420/// Iterates over the endpoint descriptors of an interface.
421pub struct EndpointIterator<'a> {
422    buffer_idx: usize,
423    index: usize,
424    iface_desc: &'a InterfaceDescriptor<'a>,
425}
426
427impl Iterator for EndpointIterator<'_> {
428    type Item = EndpointDescriptor;
429
430    fn next(&mut self) -> Option<Self::Item> {
431        if self.index >= self.iface_desc.num_endpoints as usize {
432            return None;
433        }
434        while self.buffer_idx + 7 <= self.iface_desc.buffer.len() {
435            let working = &self.iface_desc.buffer[self.buffer_idx..];
436            self.buffer_idx += working[0] as usize;
437            if let Ok(d) = EndpointDescriptor::try_from_bytes(working) {
438                self.index += 1;
439                return Some(d);
440            }
441        }
442        None
443    }
444}
445
446/// USB Endpoint Descriptor (7 bytes).
447#[derive(Copy, Clone, Debug, PartialEq)]
448#[cfg_attr(feature = "defmt", derive(defmt::Format))]
449pub struct EndpointDescriptor {
450    pub len: u8,
451    pub descriptor_type: u8,
452    pub endpoint_address: u8,
453    pub attributes: u8,
454    pub max_packet_size: u16,
455    pub interval: u8,
456}
457
458impl EndpointDescriptor {
459    /// Returns the endpoint direction.
460    pub fn ep_dir(&self) -> Direction {
461        match self.endpoint_address & 0x80 {
462            0x00 => Direction::Out,
463            _ => Direction::In,
464        }
465    }
466
467    /// Returns the endpoint transfer type.
468    pub fn ep_type(&self) -> EndpointType {
469        match self.attributes & 0x03 {
470            0 => EndpointType::Control,
471            1 => EndpointType::Isochronous,
472            2 => EndpointType::Bulk,
473            _ => EndpointType::Interrupt,
474        }
475    }
476
477    /// Endpoint number (0-15).
478    pub fn ep_number(&self) -> u8 {
479        self.endpoint_address & 0x0F
480    }
481
482    /// True if this is an IN endpoint.
483    pub fn is_in(&self) -> bool {
484        (self.endpoint_address & 0x80) != 0
485    }
486
487    /// Transfer type (0=Control, 1=Isochronous, 2=Bulk, 3=Interrupt).
488    pub fn transfer_type(&self) -> u8 {
489        self.attributes & 0x03
490    }
491}
492
493impl USBDescriptor for EndpointDescriptor {
494    const SIZE: usize = 7;
495    const DESC_TYPE: u8 = descriptor_type::ENDPOINT;
496    type Error = DescriptorError;
497
498    fn try_from_bytes(bytes: &[u8]) -> Result<Self, Self::Error> {
499        if bytes.len() < Self::SIZE || bytes.len() < bytes[0] as usize {
500            return Err(DescriptorError::UnexpectedEndOfBuffer);
501        }
502        if bytes[1] != Self::DESC_TYPE {
503            return Err(DescriptorError::BadDescriptorType);
504        }
505        Ok(Self {
506            len: bytes[0],
507            descriptor_type: bytes[1],
508            endpoint_address: bytes[2],
509            attributes: bytes[3],
510            max_packet_size: u16::from_le_bytes([bytes[4], bytes[5]]),
511            interval: bytes[6],
512        })
513    }
514}
515
516impl From<EndpointDescriptor> for EndpointInfo {
517    fn from(value: EndpointDescriptor) -> Self {
518        EndpointInfo {
519            addr: value.endpoint_address.into(),
520            ep_type: value.ep_type(),
521            max_packet_size: value.max_packet_size,
522            interval_ms: value.interval,
523        }
524    }
525}
526
527#[cfg(test)]
528mod test {
529    use heapless::Vec;
530
531    use super::{ConfigurationDescriptor, DescriptorVisitor, EndpointDescriptor, InterfaceDescriptor};
532    use crate::descriptor::ShowDescriptors;
533
534    struct TestInterface<'a> {
535        interface: InterfaceDescriptor<'a>,
536        endpoints: Vec<EndpointDescriptor, 4>,
537    }
538
539    const MAX_INTERFACES: usize = 4;
540    const MAX_DESCRIPTOR_SIZE: usize = 256;
541    const MAX_OTHERS: usize = 8;
542
543    struct TestVisitor<'a> {
544        configuration: Option<ConfigurationDescriptor<'a>>,
545        interfaces: Vec<TestInterface<'a>, MAX_INTERFACES>,
546        others: Vec<Vec<u8, MAX_DESCRIPTOR_SIZE>, MAX_OTHERS>,
547    }
548
549    impl<'a> Default for TestVisitor<'a> {
550        fn default() -> Self {
551            Self {
552                configuration: None,
553                interfaces: Vec::new(),
554                others: Vec::new(),
555            }
556        }
557    }
558
559    impl<'a> DescriptorVisitor<'a> for TestVisitor<'a> {
560        type Error = core::convert::Infallible;
561
562        fn on_configuration(&mut self, c: &ConfigurationDescriptor<'a>) -> bool {
563            assert!(self.configuration.is_none());
564            self.configuration = Some(*c);
565            true
566        }
567
568        fn on_interface(&mut self, i: &InterfaceDescriptor<'a>) -> bool {
569            assert!(self.configuration.is_some());
570            let _ = self.interfaces.push(TestInterface {
571                interface: *i,
572                endpoints: Vec::new(),
573            });
574            true
575        }
576
577        fn on_endpoint(&mut self, _iface: &InterfaceDescriptor<'a>, e: &EndpointDescriptor) -> bool {
578            assert!(!self.interfaces.is_empty());
579            let _ = self.interfaces.last_mut().unwrap().endpoints.push(*e);
580            true
581        }
582
583        fn on_other(&mut self, _iface: Option<&InterfaceDescriptor<'a>>, d: &[u8]) -> Result<bool, Self::Error> {
584            assert!(self.configuration.is_some());
585            let _ = self.others.push(Vec::from_slice(d).unwrap_or_default());
586            Ok(true)
587        }
588    }
589
590    #[test]
591    fn test_parse_extended_endpoint_descriptor() {
592        let desc_bytes = [
593            9, 2, 76, 0, 2, 1, 0, 160, 101, 8, 11, 0, 1, 3, 0, 0, 0, 9, 4, 0, 0, 1, 3, 1, 1, 0, 9, 33, 16, 1, 0, 1, 34,
594            63, 0, 9, 5, 129, 3, 8, 0, 1, 99, 99, 9, 4, 1, 0, 2, 3, 1, 0, 0, 9, 33, 16, 1, 0, 1, 34, 39, 0, 7, 5, 131,
595            3, 64, 0, 1, 7, 5, 3, 3, 64, 0, 1,
596        ];
597
598        let cfg = ConfigurationDescriptor::try_from_slice(desc_bytes.as_slice()).unwrap();
599        assert_eq!(cfg.num_interfaces, 2);
600
601        let interface0 = cfg.iter_interface().next().unwrap();
602        assert_eq!(interface0.interface_number, 0);
603        assert_eq!(interface0.num_endpoints, 1);
604
605        let endpoints: Vec<EndpointDescriptor, 2> = interface0.iter_endpoints().collect();
606        assert_eq!(endpoints.len(), 1);
607        assert_eq!(endpoints[0].endpoint_address, 0x81);
608        assert_eq!(endpoints[0].max_packet_size, 8);
609
610        let interface1 = cfg.iter_interface().nth(1).unwrap();
611        assert_eq!(interface1.interface_number, 1);
612        assert_eq!(interface1.num_endpoints, 2);
613
614        let endpoints: Vec<EndpointDescriptor, 2> = interface1.iter_endpoints().collect();
615        assert_eq!(endpoints.len(), 2);
616    }
617
618    #[test]
619    fn test_parse_interface_descriptor() {
620        let desc_bytes = [
621            9, 2, 66, 0, 2, 1, 0, 160, 101, 9, 4, 0, 0, 1, 3, 1, 1, 0, 9, 33, 16, 1, 0, 1, 34, 63, 0, 7, 5, 129, 3, 8,
622            0, 1, 9, 4, 1, 0, 2, 3, 1, 0, 0, 9, 33, 16, 1, 0, 1, 34, 39, 0, 7, 5, 131, 3, 64, 0, 1, 7, 5, 3, 3, 64, 0,
623            1,
624        ];
625
626        let cfg = ConfigurationDescriptor::try_from_slice(desc_bytes.as_slice()).unwrap();
627        assert_eq!(cfg.num_interfaces, 2);
628
629        let interface0 = cfg.iter_interface().next().unwrap();
630        assert_eq!(interface0.interface_number, 0);
631
632        let interface0_buffer_ref = [9u8, 33, 16, 1, 0, 1, 34, 63, 0, 7, 5, 129, 3, 8, 0, 1];
633        assert_eq!(interface0.buffer.len(), interface0_buffer_ref.len());
634
635        let interface1 = cfg.iter_interface().nth(1).unwrap();
636        assert_eq!(interface1.interface_number, 1);
637
638        let interface1_buffer_ref = [
639            9u8, 33, 16, 1, 0, 1, 34, 39, 0, 7, 5, 131, 3, 64, 0, 1, 7, 5, 3, 3, 64, 0, 1,
640        ];
641        assert_eq!(interface1.buffer.len(), interface1_buffer_ref.len());
642    }
643
644    #[test]
645    fn test_parse_visit_midi_descriptor() {
646        let _ = env_logger::builder().is_test(true).try_init();
647
648        let desc_bytes = [
649            9, 2, 101, 0, 2, 1, 0, 128, 50, 9, 4, 0, 0, 0, 1, 1, 0, 0, 9, 36, 1, 0, 1, 9, 0, 1, 1, 9, 4, 1, 0, 2, 1, 3,
650            0, 0, 7, 36, 1, 0, 1, 65, 0, 6, 36, 2, 1, 1, 0, 6, 36, 2, 2, 2, 0, 9, 36, 3, 1, 3, 1, 2, 1, 0, 9, 36, 3, 2,
651            4, 1, 1, 1, 0, 9, 5, 2, 2, 32, 0, 0, 0, 0, 5, 37, 1, 1, 1, 9, 5, 129, 2, 32, 0, 0, 0, 0, 5, 37, 1, 1, 3,
652        ];
653
654        let cfg = ConfigurationDescriptor::try_from_slice(desc_bytes.as_slice()).unwrap();
655        assert_eq!(cfg.num_interfaces, 2);
656
657        let mut v = TestVisitor::default();
658        cfg.visit_descriptors(&mut v).unwrap();
659
660        assert!(v.configuration.is_some());
661        assert_eq!(cfg.num_interfaces, 2);
662        assert_eq!(v.interfaces.len(), 2);
663        assert_eq!(v.interfaces[0].interface.interface_class, 1);
664        assert_eq!(v.interfaces[0].endpoints.len(), 0);
665        assert_eq!(v.interfaces[1].endpoints.len(), 2);
666        assert_eq!(v.interfaces[1].endpoints[0].attributes, 2);
667        assert_eq!(v.interfaces[1].endpoints[0].endpoint_address, 0x02);
668        assert_eq!(v.interfaces[1].endpoints[1].endpoint_address, 0x81);
669        assert_eq!(v.others.len(), 8);
670
671        let mut sv = ShowDescriptors {};
672        cfg.visit_descriptors(&mut sv).unwrap();
673    }
674}