use std::{
collections::BTreeMap,
fmt::{Debug, Display},
io::ErrorKind,
iter,
ops::Deref,
};
use log::warn;
use crate::{
transfer::{Direction, EndpointType},
Error,
};
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 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 Descriptors<'a>(&'a [u8]);
impl<'a> Descriptors<'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 Descriptors<'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<'a> $tname:ident<'a> {
$(
$(#[$attr:meta])*
$vis:vis fn $name:ident at $pos:literal -> $ty:ty;
)*
}) => {
impl<'a> $tname<'a> {
$(
$(#[$attr])*
#[inline]
$vis fn $name(&self) -> $ty { <$ty>::from_le_bytes(self.0[$pos..$pos + std::mem::size_of::<$ty>()].try_into().unwrap()) }
)*
}
}
}
pub(crate) fn validate_config_descriptor(buf: &[u8]) -> Option<usize> {
if buf.len() < DESCRIPTOR_LEN_CONFIGURATION as usize {
if buf.len() != 0 {
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(total_len)
}
#[derive(Clone)]
pub struct Configuration<'a>(&'a [u8]);
impl<'a> Configuration<'a> {
pub fn new(buf: &[u8]) -> Configuration {
assert!(buf.len() >= DESCRIPTOR_LEN_CONFIGURATION as usize);
assert!(buf[0] as usize >= DESCRIPTOR_LEN_CONFIGURATION as usize);
assert!(buf[1] == DESCRIPTOR_TYPE_CONFIGURATION);
assert!(buf.len() == u16::from_le_bytes(buf[2..4].try_into().unwrap()) as usize);
Configuration(buf)
}
pub fn descriptors(&self) -> Descriptors {
Descriptors(self.0)
}
pub fn interface_alt_settings(&self) -> impl Iterator<Item = InterfaceAltSetting> {
self.descriptors()
.split_by_type(DESCRIPTOR_TYPE_INTERFACE, DESCRIPTOR_LEN_INTERFACE)
.map(InterfaceAltSetting)
}
pub fn interfaces(&self) -> impl Iterator<Item = InterfaceGroup> {
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)| InterfaceGroup {
intf_number,
interfaces,
})
}
}
descriptor_fields! {
impl<'a> Configuration<'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> Configuration<'a> {
#[doc(alias = "iConfiguration")]
pub fn string_index(&self) -> Option<u8> {
Some(self.string_index_raw()).filter(|&i| i != 0)
}
}
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 Configuration<'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 InterfaceGroup<'a> {
intf_number: u8,
interfaces: Vec<InterfaceAltSetting<'a>>,
}
impl<'a> InterfaceGroup<'a> {
#[doc(alias = "bInterfaceNumber")]
pub fn interface_number(&self) -> u8 {
self.intf_number
}
pub fn alt_settings(&self) -> impl Iterator<Item = InterfaceAltSetting> {
self.interfaces.iter().cloned()
}
}
#[derive(Clone)]
pub struct InterfaceAltSetting<'a>(&'a [u8]);
impl<'a> InterfaceAltSetting<'a> {
pub fn descriptors(&self) -> Descriptors {
Descriptors(self.0)
}
pub fn endpoints(&self) -> impl Iterator<Item = Endpoint> {
self.descriptors()
.split_by_type(DESCRIPTOR_TYPE_ENDPOINT, DESCRIPTOR_LEN_ENDPOINT)
.map(Endpoint)
}
}
descriptor_fields! {
impl<'a> InterfaceAltSetting<'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> InterfaceAltSetting<'a> {
#[doc(alias = "iInterface")]
pub fn string_index(&self) -> Option<u8> {
Some(self.string_index_raw()).filter(|&i| i != 0)
}
}
impl<'a> Debug for InterfaceAltSetting<'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 Endpoint<'a>(&'a [u8]);
impl<'a> Endpoint<'a> {
pub fn descriptors(&self) -> impl Iterator<Item = Descriptor> {
Descriptors(self.0)
}
pub fn direction(&self) -> Direction {
match self.address() & 0x80 {
0 => Direction::Out,
_ => Direction::In,
}
}
pub fn transfer_type(&self) -> EndpointType {
match self.attributes() & 0x03 {
0 => EndpointType::Control,
1 => EndpointType::Isochronous,
2 => EndpointType::Bulk,
3 => EndpointType::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> Endpoint<'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 Endpoint<'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(Copy, Clone, Debug, PartialEq, Eq)]
pub struct ActiveConfigurationError {
pub(crate) configuration_value: u8,
}
impl Display for ActiveConfigurationError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self.configuration_value == 0 {
write!(f, "device is not configured")
} else {
write!(
f,
"no descriptor found for active configuration {}",
self.configuration_value
)
}
}
}
impl std::error::Error for ActiveConfigurationError {}
impl From<ActiveConfigurationError> for Error {
fn from(value: ActiveConfigurationError) -> Self {
Error::new(ErrorKind::Other, value)
}
}
pub(crate) fn parse_concatenated_config_descriptors(mut buf: &[u8]) -> impl Iterator<Item = &[u8]> {
iter::from_fn(move || {
let total_len = validate_config_descriptor(buf)?;
let descriptors = &buf[..total_len];
buf = &buf[total_len..];
Some(descriptors)
})
}
#[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<&[u8]>>(),
Vec::<&[u8]>::new()
);
}
#[test]
fn test_short() {
assert_eq!(
parse_concatenated_config_descriptors(&[0]).collect::<Vec<&[u8]>>(),
Vec::<&[u8]>::new()
);
}
#[test]
fn test_invalid_total_len() {
assert_eq!(
parse_concatenated_config_descriptors(&[9, 2, 0, 0, 0, 0, 0, 0, 0])
.collect::<Vec<&[u8]>>(),
Vec::<&[u8]>::new()
);
}
#[test]
fn test_one_config() {
assert_eq!(
parse_concatenated_config_descriptors(&[9, 2, 9, 0, 0, 0, 0, 0, 0])
.collect::<Vec<&[u8]>>(),
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])
.collect::<Vec<&[u8]>>(),
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
])
.collect::<Vec<&[u8]>>(),
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 = Configuration(&[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 = Configuration(&[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 c = Configuration(&[
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(), EndpointType::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 = Configuration(&[
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();
assert_eq!(descriptors.next().unwrap().descriptor_type(), DESCRIPTOR_TYPE_INTERFACE);
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(), EndpointType::Interrupt);
assert_eq!(endpoint.max_packet_size(), 16);
assert_eq!(endpoint.descriptors().nth(1).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(), EndpointType::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(), EndpointType::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(), EndpointType::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(), EndpointType::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(), EndpointType::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(), EndpointType::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());
}