use std::{collections::BTreeMap, fmt::Debug, iter, num::NonZeroU8, ops::Deref};
use log::warn;
use crate::transfer::Direction;
pub(crate) const DESCRIPTOR_TYPE_DEVICE: u8 = 0x01;
pub(crate) const DESCRIPTOR_LEN_DEVICE: u8 = 18;
pub(crate) const DESCRIPTOR_TYPE_CONFIGURATION: u8 = 0x02;
pub(crate) const DESCRIPTOR_LEN_CONFIGURATION: u8 = 9;
pub(crate) const DESCRIPTOR_TYPE_INTERFACE: u8 = 0x04;
pub(crate) const DESCRIPTOR_LEN_INTERFACE: u8 = 9;
pub(crate) const DESCRIPTOR_TYPE_ENDPOINT: u8 = 0x05;
pub(crate) const DESCRIPTOR_LEN_ENDPOINT: u8 = 7;
pub(crate) const DESCRIPTOR_TYPE_STRING: u8 = 0x03;
pub mod language_id {
pub const US_ENGLISH: u16 = 0x0409;
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Descriptor<'a>(&'a [u8]);
impl<'a> Descriptor<'a> {
pub fn new(buf: &[u8]) -> Option<Descriptor<'_>> {
if buf.len() >= 2 && buf.len() >= buf[0] as usize {
Some(Descriptor(buf))
} else {
None
}
}
#[doc(alias = "bLength")]
pub fn descriptor_len(&self) -> usize {
self.0[0] as usize
}
#[doc(alias = "bDescriptorType")]
pub fn descriptor_type(&self) -> u8 {
self.0[1]
}
}
impl<'a> Deref for Descriptor<'a> {
type Target = [u8];
fn deref(&self) -> &[u8] {
self.0
}
}
#[derive(Clone)]
pub struct DescriptorIter<'a>(&'a [u8]);
impl<'a> DescriptorIter<'a> {
pub fn as_bytes(&self) -> &'a [u8] {
self.0
}
fn split_first(&self) -> Option<(&'a [u8], &'a [u8])> {
if self.0.len() < 2 {
return None;
}
if self.0[0] < 2 {
warn!(
"descriptor with bLength {} can't point to next descriptor",
self.0[0]
);
return None;
}
if self.0[0] as usize > self.0.len() {
warn!(
"descriptor with bLength {} exceeds remaining buffer length {}",
self.0[0],
self.0.len()
);
return None;
}
Some(self.0.split_at(self.0[0] as usize))
}
fn split_by_type(mut self, descriptor_type: u8, min_len: u8) -> impl Iterator<Item = &'a [u8]> {
iter::from_fn(move || {
loop {
let (_, next) = self.split_first()?;
if self.0[1] == descriptor_type {
if self.0[0] >= min_len {
break;
} else {
warn!("ignoring descriptor of type {} and length {} because the minimum length is {}", self.0[1], self.0[0], min_len);
}
}
self.0 = next;
}
let mut end = self.0[0] as usize;
while self.0.len() >= end + 2
&& self.0[end] > 2
&& self.0[end + 1] != descriptor_type
&& self.0.len() >= end + self.0[end] as usize
{
end += self.0[end] as usize;
}
let (r, next) = self.0.split_at(end);
self.0 = next;
Some(r)
})
}
}
impl<'a> Iterator for DescriptorIter<'a> {
type Item = Descriptor<'a>;
fn next(&mut self) -> Option<Self::Item> {
if let Some((cur, next)) = self.split_first() {
self.0 = next;
Some(Descriptor(cur))
} else {
None
}
}
}
macro_rules! descriptor_fields {
(impl $(<$( $i_lt:lifetime ),+>)? $tname:ident $(<$( $t_lt:lifetime ),+>)? {
$(
$(#[$attr:meta])*
$vis:vis fn $name:ident at $pos:literal -> $ty:ty;
)*
}) => {
impl $(<$( $i_lt ),+>)? $tname $(<$( $t_lt ),+>)? {
$(
$(#[$attr])*
#[inline]
$vis fn $name(&self) -> $ty { <$ty>::from_le_bytes(self.0[$pos..$pos + std::mem::size_of::<$ty>()].try_into().unwrap()) }
)*
}
}
}
#[derive(Clone)]
pub struct DeviceDescriptor([u8; DESCRIPTOR_LEN_DEVICE as usize]);
impl DeviceDescriptor {
pub fn new(buf: &[u8]) -> Option<Self> {
let Some(buf) = buf.get(0..DESCRIPTOR_LEN_DEVICE as usize) else {
if !buf.is_empty() {
warn!(
"device descriptor buffer is {} bytes, need {}",
buf.len(),
DESCRIPTOR_LEN_DEVICE
);
}
return None;
};
let buf: [u8; DESCRIPTOR_LEN_DEVICE as usize] = buf.try_into().ok()?;
if buf[0] < DESCRIPTOR_LEN_DEVICE {
warn!("invalid device descriptor bLength");
None
} else if buf[1] != DESCRIPTOR_TYPE_DEVICE {
warn!(
"device bDescriptorType is {}, not a device descriptor",
buf[1]
);
None
} else {
Some(Self(buf))
}
}
pub fn as_bytes(&self) -> &[u8] {
&self.0
}
#[allow(unused)]
#[allow(clippy::too_many_arguments)]
pub(crate) fn from_fields(
usb_version: u16,
class: u8,
subclass: u8,
protocol: u8,
max_packet_size_0: u8,
vendor_id: u16,
product_id: u16,
device_version: u16,
manufacturer_string_index: u8,
product_string_index: u8,
serial_number_string_index: u8,
num_configurations: u8,
) -> DeviceDescriptor {
DeviceDescriptor([
DESCRIPTOR_LEN_DEVICE,
DESCRIPTOR_TYPE_DEVICE,
usb_version.to_le_bytes()[0],
usb_version.to_le_bytes()[1],
class,
subclass,
protocol,
max_packet_size_0,
vendor_id.to_le_bytes()[0],
vendor_id.to_le_bytes()[1],
product_id.to_le_bytes()[0],
product_id.to_le_bytes()[1],
device_version.to_le_bytes()[0],
device_version.to_le_bytes()[1],
manufacturer_string_index,
product_string_index,
serial_number_string_index,
num_configurations,
])
}
}
descriptor_fields! {
impl DeviceDescriptor {
#[doc(alias = "bcdUSB")]
pub fn usb_version at 2 -> u16;
#[doc(alias = "bDeviceClass")]
pub fn class at 4 -> u8;
#[doc(alias = "bDeviceSubClass")]
pub fn subclass at 5 -> u8;
#[doc(alias = "bDeviceProtocol")]
pub fn protocol at 6 -> u8;
#[doc(alias = "bMaxPacketSize0")]
pub fn max_packet_size_0 at 7 -> u8;
#[doc(alias = "idVendor")]
pub fn vendor_id at 8 -> u16;
#[doc(alias = "idProduct")]
pub fn product_id at 10 -> u16;
#[doc(alias = "bcdDevice")]
pub fn device_version at 12 -> u16;
fn manufacturer_string_index_raw at 14 -> u8;
fn product_string_index_raw at 15 -> u8;
fn serial_number_string_index_raw at 16 -> u8;
#[doc(alias = "bNumConfigurations")]
pub fn num_configurations at 17 -> u8;
}
}
impl DeviceDescriptor {
pub fn manufacturer_string_index(&self) -> Option<NonZeroU8> {
NonZeroU8::new(self.manufacturer_string_index_raw())
}
pub fn product_string_index(&self) -> Option<NonZeroU8> {
NonZeroU8::new(self.product_string_index_raw())
}
pub fn serial_number_string_index(&self) -> Option<NonZeroU8> {
NonZeroU8::new(self.serial_number_string_index_raw())
}
}
impl Debug for DeviceDescriptor {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("DeviceDescriptor")
.field("usb_version", &format_args!("0x{:04X}", self.usb_version()))
.field("class", &format_args!("0x{:02X}", self.class()))
.field("subclass", &format_args!("0x{:02X}", self.subclass()))
.field("protocol", &format_args!("0x{:02X}", self.protocol()))
.field("max_packet_size_0", &self.max_packet_size_0())
.field("vendor_id", &format_args!("0x{:04X}", self.vendor_id()))
.field("product_id", &format_args!("0x{:04X}", self.product_id()))
.field(
"device_version",
&format_args!("0x{:04X}", self.device_version()),
)
.field(
"manufacturer_string_index",
&self.manufacturer_string_index(),
)
.field("product_string_index", &self.product_string_index())
.field(
"serial_number_string_index",
&self.serial_number_string_index(),
)
.field("num_configurations", &self.num_configurations())
.finish()
}
}
#[derive(Clone)]
pub struct ConfigurationDescriptor<'a>(&'a [u8]);
impl<'a> ConfigurationDescriptor<'a> {
pub fn new(buf: &[u8]) -> Option<ConfigurationDescriptor<'_>> {
if buf.len() < DESCRIPTOR_LEN_CONFIGURATION as usize {
if !buf.is_empty() {
warn!(
"config descriptor buffer is {} bytes, need {}",
buf.len(),
DESCRIPTOR_LEN_CONFIGURATION
);
}
return None;
}
if buf[0] < DESCRIPTOR_LEN_CONFIGURATION {
warn!("invalid config descriptor bLength");
return None;
}
if buf[1] != DESCRIPTOR_TYPE_CONFIGURATION {
warn!(
"config bDescriptorType is {}, not a configuration descriptor",
buf[0]
);
return None;
}
let total_len = u16::from_le_bytes(buf[2..4].try_into().unwrap()) as usize;
if total_len < buf[0] as usize || total_len > buf.len() {
warn!(
"invalid config descriptor wTotalLen of {total_len} (buffer size is {bufsize})",
bufsize = buf.len()
);
return None;
}
Some(ConfigurationDescriptor(&buf[..total_len]))
}
#[allow(unused)]
pub(crate) fn new_unchecked(d: &'a [u8]) -> Self {
Self(d)
}
pub fn as_bytes(&self) -> &'a [u8] {
self.0
}
pub fn descriptors(&self) -> DescriptorIter<'a> {
DescriptorIter(&self.0[self.0[0] as usize..])
}
pub fn interface_alt_settings(&self) -> impl Iterator<Item = InterfaceDescriptor<'a>> {
self.descriptors()
.split_by_type(DESCRIPTOR_TYPE_INTERFACE, DESCRIPTOR_LEN_INTERFACE)
.map(InterfaceDescriptor)
}
pub fn interfaces(&self) -> impl Iterator<Item = InterfaceDescriptors<'a>> {
let mut interfaces = BTreeMap::new();
for intf in self.interface_alt_settings() {
interfaces
.entry(intf.interface_number())
.or_insert_with(Vec::new)
.push(intf);
}
interfaces
.into_iter()
.map(|(intf_number, interfaces)| InterfaceDescriptors {
intf_number,
interfaces,
})
}
}
descriptor_fields! {
impl<'a> ConfigurationDescriptor<'a> {
#[doc(alias = "bNumInterfaces")]
pub fn num_interfaces at 4 -> u8;
#[doc(alias = "bConfigurationValue")]
pub fn configuration_value at 5 -> u8;
fn string_index_raw at 6 -> u8;
#[doc(alias = "bmAttributes")]
pub fn attributes at 7 -> u8;
#[doc(alias = "bMaxPower")]
pub fn max_power at 8 -> u8;
}
}
impl<'a> ConfigurationDescriptor<'a> {
#[doc(alias = "iConfiguration")]
pub fn string_index(&self) -> Option<NonZeroU8> {
NonZeroU8::new(self.string_index_raw())
}
}
struct DebugEntries<F>(F);
impl<F, I> Debug for DebugEntries<F>
where
F: Fn() -> I,
I: Iterator,
I::Item: Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_list().entries(self.0()).finish()
}
}
impl<'a> Debug for ConfigurationDescriptor<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Configuration")
.field("configuration_value", &self.configuration_value())
.field("num_interfaces", &self.num_interfaces())
.field("attributes", &self.attributes())
.field("max_power", &self.max_power())
.field("string_index", &self.string_index())
.field(
"interface_alt_settings",
&DebugEntries(|| self.interface_alt_settings()),
)
.finish()
}
}
#[derive(Clone)]
pub struct InterfaceDescriptors<'a> {
intf_number: u8,
interfaces: Vec<InterfaceDescriptor<'a>>,
}
impl<'a> InterfaceDescriptors<'a> {
#[doc(alias = "bInterfaceNumber")]
pub fn interface_number(&self) -> u8 {
self.intf_number
}
pub fn alt_settings(&self) -> impl Iterator<Item = InterfaceDescriptor<'a>> + '_ {
self.interfaces.iter().cloned()
}
pub fn first_alt_setting(&self) -> InterfaceDescriptor<'a> {
self.interfaces[0].clone()
}
}
#[derive(Clone)]
pub struct InterfaceDescriptor<'a>(&'a [u8]);
impl<'a> InterfaceDescriptor<'a> {
pub fn as_bytes(&self) -> &[u8] {
self.0
}
pub fn descriptors(&self) -> DescriptorIter<'a> {
DescriptorIter(&self.0[self.0[0] as usize..])
}
pub fn endpoints(&self) -> impl Iterator<Item = EndpointDescriptor<'a>> {
self.descriptors()
.split_by_type(DESCRIPTOR_TYPE_ENDPOINT, DESCRIPTOR_LEN_ENDPOINT)
.map(EndpointDescriptor)
}
}
descriptor_fields! {
impl<'a> InterfaceDescriptor<'a> {
#[doc(alias="bInterfaceNumber")]
pub fn interface_number at 2 -> u8;
#[doc(alias="bAlternateSetting")]
pub fn alternate_setting at 3 -> u8;
#[doc(alias="bNumEndpoints")]
pub fn num_endpoints at 4 -> u8;
#[doc(alias="bInterfaceClass")]
pub fn class at 5 -> u8;
#[doc(alias="bInterfaceSubClass")]
pub fn subclass at 6 -> u8;
#[doc(alias="bInterfaceProtocol")]
pub fn protocol at 7 -> u8;
fn string_index_raw at 8 -> u8;
}
}
impl<'a> InterfaceDescriptor<'a> {
#[doc(alias = "iInterface")]
pub fn string_index(&self) -> Option<NonZeroU8> {
NonZeroU8::new(self.string_index_raw())
}
}
impl<'a> Debug for InterfaceDescriptor<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("InterfaceAltSetting")
.field("interface_number", &self.interface_number())
.field("alternate_setting", &self.alternate_setting())
.field("num_endpoints", &self.num_endpoints())
.field("class", &self.class())
.field("subclass", &self.subclass())
.field("protocol", &self.protocol())
.field("string_index", &self.string_index())
.field("endpoints", &DebugEntries(|| self.endpoints()))
.finish()
}
}
pub struct EndpointDescriptor<'a>(&'a [u8]);
impl<'a> EndpointDescriptor<'a> {
pub fn as_bytes(&self) -> &'a [u8] {
self.0
}
pub fn descriptors(&self) -> DescriptorIter<'a> {
DescriptorIter(&self.0[self.0[0] as usize..])
}
pub fn direction(&self) -> Direction {
Direction::from_address(self.address())
}
pub fn transfer_type(&self) -> TransferType {
match self.attributes() & 0x03 {
0 => TransferType::Control,
1 => TransferType::Isochronous,
2 => TransferType::Bulk,
3 => TransferType::Interrupt,
_ => unreachable!(),
}
}
pub fn max_packet_size(&self) -> usize {
(self.max_packet_size_raw() & ((1 << 11) - 1)) as usize
}
pub fn packets_per_microframe(&self) -> u8 {
((self.max_packet_size_raw() >> 11) & 0b11) as u8 + 1
}
}
descriptor_fields! {
impl<'a> EndpointDescriptor<'a> {
#[doc(alias = "bEndpointAddress")]
pub fn address at 2 -> u8;
#[doc(alias = "bmAttributes")]
pub fn attributes at 3 -> u8;
#[doc(alias = "wMaxPacketSize")]
pub fn max_packet_size_raw at 4 -> u16;
#[doc(alias = "bInterval")]
pub fn interval at 6 -> u8;
}
}
impl<'a> Debug for EndpointDescriptor<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Endpoint")
.field("address", &format_args!("0x{:02X}", self.address()))
.field("direction", &self.direction())
.field("transfer_type", &self.transfer_type())
.field("max_packet_size", &self.max_packet_size())
.field("packets_per_microframe", &self.packets_per_microframe())
.field("interval", &self.interval())
.finish()
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[allow(dead_code)]
pub enum TransferType {
Control = 0,
Isochronous = 1,
Bulk = 2,
Interrupt = 3,
}
#[allow(unused)]
pub(crate) fn parse_concatenated_config_descriptors(
mut buf: &[u8],
) -> impl Iterator<Item = ConfigurationDescriptor<'_>> {
iter::from_fn(move || {
let desc = ConfigurationDescriptor::new(buf)?;
buf = &buf[desc.0.len()..];
Some(desc)
})
}
pub(crate) fn validate_string_descriptor(data: &[u8]) -> bool {
data.len() >= 2 && data[0] as usize == data.len() && data[1] == DESCRIPTOR_TYPE_STRING
}
pub(crate) fn decode_string_descriptor(data: &[u8]) -> Result<String, ()> {
if !validate_string_descriptor(data) {
return Err(());
}
Ok(char::decode_utf16(
data[2..]
.chunks_exact(2)
.map(|c| u16::from_le_bytes(c.try_into().unwrap())),
)
.map(|r| r.unwrap_or(char::REPLACEMENT_CHARACTER))
.collect::<String>())
}
#[cfg(fuzzing)]
pub fn fuzz_parse_concatenated_config_descriptors(buf: &[u8]) -> impl Iterator<Item = &[u8]> {
parse_concatenated_config_descriptors(buf)
}
#[cfg(test)]
mod test_concatenated {
use super::parse_concatenated_config_descriptors;
#[test]
fn test_empty() {
assert_eq!(
parse_concatenated_config_descriptors(&[])
.collect::<Vec<_>>()
.len(),
0
);
}
#[test]
fn test_short() {
assert_eq!(
parse_concatenated_config_descriptors(&[0])
.map(|d| d.descriptors().as_bytes())
.collect::<Vec<_>>(),
Vec::<&[u8]>::new()
);
}
#[test]
fn test_invalid_total_len() {
assert_eq!(
parse_concatenated_config_descriptors(&[9, 2, 0, 0, 0, 0, 0, 0, 0])
.map(|d| d.descriptors().as_bytes())
.collect::<Vec<_>>(),
Vec::<&[u8]>::new()
);
}
#[test]
fn test_one_config() {
assert_eq!(
parse_concatenated_config_descriptors(&[9, 2, 9, 0, 0, 0, 0, 0, 0])
.map(|d| d.as_bytes())
.collect::<Vec<_>>(),
vec![&[9, 2, 9, 0, 0, 0, 0, 0, 0]]
);
assert_eq!(
parse_concatenated_config_descriptors(&[9, 2, 13, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0])
.map(|d| d.as_bytes())
.collect::<Vec<_>>(),
vec![&[9, 2, 13, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0]]
);
}
#[test]
fn test_two_configs() {
assert_eq!(
parse_concatenated_config_descriptors(&[
9, 2, 13, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 9, 2, 9, 0, 0, 0, 0, 0, 0
])
.map(|d| d.as_bytes())
.collect::<Vec<_>>(),
vec![
[9, 2, 13, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0].as_slice(),
[9, 2, 9, 0, 0, 0, 0, 0, 0].as_slice()
]
);
}
}
#[test]
fn test_empty_config() {
let c = ConfigurationDescriptor(&[9, 2, 9, 0, 0, 1, 0, 0, 250]);
assert_eq!(c.num_interfaces(), 0);
assert_eq!(c.configuration_value(), 1);
assert_eq!(c.string_index(), None);
assert_eq!(c.interfaces().count(), 0);
}
#[test]
fn test_malformed() {
let c = ConfigurationDescriptor(&[9, 2, 0, 0, 0, 1, 0, 0, 2, 5, 250, 0, 0, 0]);
assert!(c.interfaces().next().is_none());
}
#[test]
#[rustfmt::skip]
fn test_linux_root_hub() {
let dev = DeviceDescriptor::new(&[
0x12, 0x01, 0x00, 0x02, 0x09, 0x00, 0x01, 0x40, 0x6b,
0x1d, 0x02, 0x00, 0x10, 0x05, 0x03, 0x02, 0x01, 0x01
]).unwrap();
assert_eq!(dev.usb_version(), 0x0200);
assert_eq!(dev.class(), 0x09);
assert_eq!(dev.subclass(), 0x00);
assert_eq!(dev.protocol(), 0x01);
assert_eq!(dev.max_packet_size_0(), 64);
assert_eq!(dev.vendor_id(), 0x1d6b);
assert_eq!(dev.product_id(), 0x0002);
assert_eq!(dev.device_version(), 0x0510);
assert_eq!(dev.manufacturer_string_index(), NonZeroU8::new(3));
assert_eq!(dev.product_string_index(), NonZeroU8::new(2));
assert_eq!(dev.serial_number_string_index(), NonZeroU8::new(1));
assert_eq!(dev.num_configurations(), 1);
let c = ConfigurationDescriptor(&[
0x09, 0x02, 0x19, 0x00, 0x01, 0x01, 0x00, 0xe0, 0x00,
0x09, 0x04, 0x00, 0x00, 0x01, 0x09, 0x00, 0x00, 0x00,
0x07, 0x05, 0x81, 0x03, 0x04, 0x00, 0x0c
]);
assert_eq!(c.num_interfaces(), 1);
assert_eq!(c.configuration_value(), 1);
assert_eq!(c.max_power(), 0);
assert_eq!(c.interfaces().count(), 1);
let interface = c.interfaces().next().unwrap();
assert_eq!(interface.interface_number(), 0);
let mut alts = interface.alt_settings();
let alt = alts.next().unwrap();
assert_eq!(alt.interface_number(), 0);
assert_eq!(alt.alternate_setting(), 0);
assert_eq!(alt.num_endpoints(), 1);
assert_eq!(alt.class(), 9);
assert_eq!(alt.subclass(), 0);
assert_eq!(alt.protocol(), 0);
assert_eq!(alt.endpoints().count(), 1);
let endpoint = alt.endpoints().next().unwrap();
assert_eq!(endpoint.address(), 0x81);
assert_eq!(endpoint.transfer_type(), TransferType::Interrupt);
assert_eq!(endpoint.max_packet_size(), 4);
assert_eq!(endpoint.interval(), 12);
assert!(alts.next().is_none());
}
#[test]
#[rustfmt::skip]
fn test_dell_webcam() {
let c = ConfigurationDescriptor(&[
0x09, 0x02, 0xa3, 0x02, 0x02, 0x01, 0x00, 0x80, 0xfa,
0x28, 0xff, 0x42, 0x49, 0x53, 0x54, 0x00, 0x01, 0x06, 0x01, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0xd1, 0x10, 0xd0, 0x07, 0xd2, 0x11, 0xf4, 0x01,
0xd3, 0x12, 0xf4, 0x01, 0xd4, 0x13, 0xf4, 0x01, 0xd5, 0x14, 0xd0, 0x07,
0xd6, 0x15, 0xf4, 0x01,
0x08, 0x0b, 0x00, 0x02, 0x0e, 0x03, 0x00, 0x05,
0x09, 0x04, 0x00, 0x00, 0x01, 0x0e, 0x01, 0x00, 0x05,
0x0d, 0x24, 0x01, 0x00, 0x01, 0x67, 0x00, 0xc0, 0xe1, 0xe4, 0x00, 0x01, 0x01,
0x09, 0x24, 0x03, 0x05, 0x01, 0x01, 0x00, 0x04, 0x00,
0x1a, 0x24, 0x06, 0x03, 0x70, 0x33, 0xf0, 0x28, 0x11, 0x63, 0x2e, 0x4a,
0xba, 0x2c, 0x68, 0x90, 0xeb, 0x33, 0x40, 0x16, 0x08, 0x01, 0x02, 0x01,
0x9f, 0x00,
0x1a, 0x24, 0x06, 0x04, 0xc3, 0x85, 0xb8, 0x0f, 0xc2, 0x68, 0x47, 0x45,
0x90, 0xf7, 0x8f, 0x47, 0x57, 0x9d, 0x95, 0xfc, 0x08, 0x01, 0x03, 0x01,
0x0f, 0x00,
0x12, 0x24, 0x02, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x03, 0x0e, 0x00, 0x20,
0x0b, 0x24, 0x05, 0x02, 0x01, 0x00, 0x00, 0x02, 0x7f, 0x17, 0x00,
0x07, 0x05, 0x83, 0x03, 0x10, 0x00, 0x06,
0x05, 0x25, 0x03, 0x80, 0x00,
0x09, 0x04, 0x01, 0x00, 0x00, 0x0e, 0x02, 0x00, 0x00,
0x0f, 0x24, 0x01, 0x02, 0x85, 0x01, 0x81, 0x00, 0x05, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00,
0x0b, 0x24, 0x06, 0x01, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x06, 0x24, 0x0d, 0x01, 0x01, 0x04,
0x09, 0x04, 0x01, 0x01, 0x01, 0x0e, 0x02, 0x00, 0x00,
0x07, 0x05, 0x81, 0x05, 0x80, 0x00, 0x01,
0x09, 0x04, 0x01, 0x02, 0x01, 0x0e, 0x02, 0x00, 0x00,
0x07, 0x05, 0x81, 0x05, 0x00, 0x01, 0x01,
0x09, 0x04, 0x01, 0x03, 0x01, 0x0e, 0x02, 0x00, 0x00,
0x07, 0x05, 0x81, 0x05, 0x20, 0x03, 0x01,
0x09, 0x04, 0x01, 0x04, 0x01, 0x0e, 0x02, 0x00, 0x00,
0x07, 0x05, 0x81, 0x05, 0x20, 0x0b, 0x01,
0x09, 0x04, 0x01, 0x05, 0x01, 0x0e, 0x02, 0x00, 0x00,
0x07, 0x05, 0x81, 0x05, 0x20, 0x13, 0x01,
0x09, 0x04, 0x01, 0x06, 0x01, 0x0e, 0x02, 0x00, 0x00,
0x07, 0x05, 0x81, 0x05, 0x00, 0x14, 0x01
]);
assert_eq!(c.configuration_value(), 1);
assert_eq!(c.num_interfaces(), 2);
assert_eq!(c.max_power(), 250);
let mut interfaces = c.interfaces();
let interface = interfaces.next().unwrap();
assert_eq!(interface.interface_number(), 0);
let mut alts = interface.alt_settings();
let alt = alts.next().unwrap();
assert_eq!(alt.interface_number(), 0);
assert_eq!(alt.alternate_setting(), 0);
assert_eq!(alt.num_endpoints(), 1);
assert_eq!(alt.class(), 14);
assert_eq!(alt.subclass(), 1);
assert_eq!(alt.protocol(), 0);
let mut descriptors = alt.descriptors();
for _ in 0..6 {
assert_eq!(descriptors.next().unwrap().descriptor_type(), 0x24);
}
assert_eq!(descriptors.next().unwrap().descriptor_type(), DESCRIPTOR_TYPE_ENDPOINT);
assert_eq!(descriptors.next().unwrap().descriptor_type(), 0x25);
assert!(descriptors.next().is_none());
let mut endpoints = alt.endpoints();
let endpoint = endpoints.next().unwrap();
assert_eq!(endpoint.address(), 0x83);
assert_eq!(endpoint.transfer_type(), TransferType::Interrupt);
assert_eq!(endpoint.max_packet_size(), 16);
assert_eq!(endpoint.descriptors().next().unwrap().descriptor_type(), 0x25);
assert!(endpoints.next().is_none());
assert!(alts.next().is_none());
let interface = interfaces.next().unwrap();
assert_eq!(interface.interface_number(), 1);
let mut alts = interface.alt_settings();
let alt = alts.next().unwrap();
assert_eq!(alt.interface_number(), 1);
assert_eq!(alt.alternate_setting(), 0);
assert_eq!(alt.num_endpoints(), 0);
assert_eq!(alt.class(), 14);
assert_eq!(alt.subclass(), 2);
assert_eq!(alt.protocol(), 0);
let mut endpoints = alt.endpoints();
assert!(endpoints.next().is_none());
let alt = alts.next().unwrap();
assert_eq!(alt.interface_number(), 1);
assert_eq!(alt.alternate_setting(), 1);
assert_eq!(alt.num_endpoints(), 1);
assert_eq!(alt.class(), 14);
assert_eq!(alt.subclass(), 2);
assert_eq!(alt.protocol(), 0);
let mut endpoints = alt.endpoints();
let endpoint = endpoints.next().unwrap();
assert_eq!(endpoint.address(), 0x81);
assert_eq!(endpoint.transfer_type(), TransferType::Isochronous);
assert_eq!(endpoint.max_packet_size(), 128);
assert!(endpoints.next().is_none());
let alt = alts.next().unwrap();
assert_eq!(alt.interface_number(), 1);
assert_eq!(alt.alternate_setting(), 2);
assert_eq!(alt.num_endpoints(), 1);
assert_eq!(alt.class(), 14);
assert_eq!(alt.subclass(), 2);
assert_eq!(alt.protocol(), 0);
let mut endpoints = alt.endpoints();
let endpoint = endpoints.next().unwrap();
assert_eq!(endpoint.address(), 0x81);
assert_eq!(endpoint.transfer_type(), TransferType::Isochronous);
assert_eq!(endpoint.max_packet_size(), 256);
assert_eq!(endpoint.packets_per_microframe(), 1);
assert!(endpoints.next().is_none());
let alt = alts.next().unwrap();
assert_eq!(alt.interface_number(), 1);
assert_eq!(alt.alternate_setting(), 3);
assert_eq!(alt.num_endpoints(), 1);
assert_eq!(alt.class(), 14);
assert_eq!(alt.subclass(), 2);
assert_eq!(alt.protocol(), 0);
let mut endpoints = alt.endpoints();
let endpoint = endpoints.next().unwrap();
assert_eq!(endpoint.address(), 0x81);
assert_eq!(endpoint.transfer_type(), TransferType::Isochronous);
assert_eq!(endpoint.max_packet_size(), 800);
assert_eq!(endpoint.packets_per_microframe(), 1);
assert!(endpoints.next().is_none());
let alt = alts.next().unwrap();
assert_eq!(alt.interface_number(), 1);
assert_eq!(alt.alternate_setting(), 4);
assert_eq!(alt.num_endpoints(), 1);
assert_eq!(alt.class(), 14);
assert_eq!(alt.subclass(), 2);
assert_eq!(alt.protocol(), 0);
let mut endpoints = alt.endpoints();
let endpoint = endpoints.next().unwrap();
assert_eq!(endpoint.address(), 0x81);
assert_eq!(endpoint.transfer_type(), TransferType::Isochronous);
assert_eq!(endpoint.max_packet_size(), 800);
assert_eq!(endpoint.packets_per_microframe(), 2);
let alt = alts.next().unwrap();
assert_eq!(alt.interface_number(), 1);
assert_eq!(alt.alternate_setting(), 5);
assert_eq!(alt.num_endpoints(), 1);
assert_eq!(alt.class(), 14);
assert_eq!(alt.subclass(), 2);
assert_eq!(alt.protocol(), 0);
let mut endpoints = alt.endpoints();
let endpoint = endpoints.next().unwrap();
assert_eq!(endpoint.address(), 0x81);
assert_eq!(endpoint.transfer_type(), TransferType::Isochronous);
assert_eq!(endpoint.max_packet_size(), 800);
assert_eq!(endpoint.packets_per_microframe(), 3);
let alt = alts.next().unwrap();
assert_eq!(alt.interface_number(), 1);
assert_eq!(alt.alternate_setting(), 6);
assert_eq!(alt.num_endpoints(), 1);
assert_eq!(alt.class(), 14);
assert_eq!(alt.subclass(), 2);
assert_eq!(alt.protocol(), 0);
let mut endpoints = alt.endpoints();
let endpoint = endpoints.next().unwrap();
assert_eq!(endpoint.address(), 0x81);
assert_eq!(endpoint.transfer_type(), TransferType::Isochronous);
assert_eq!(endpoint.max_packet_size(), 1024);
assert_eq!(endpoint.packets_per_microframe(), 3);
assert!(endpoints.next().is_none());
assert!(alts.next().is_none());
assert!(interfaces.next().is_none());
}