const DESCRIPTOR_TYPE_CONFIGURATION: u8 = 2;
const DESCRIPTOR_TYPE_INTERFACE: u8 = 4;
const DESCRIPTOR_TYPE_ENDPOINT: u8 = 5;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct DeviceDescriptor {
pub device_class: u8,
pub max_packet_size0: u8,
pub vendor_id: u16,
pub product_id: u16,
}
impl DeviceDescriptor {
pub fn from_bytes(bytes: &[u8; 18]) -> Self {
Self {
device_class: bytes[4],
max_packet_size0: bytes[7],
vendor_id: u16::from_le_bytes([bytes[8], bytes[9]]),
product_id: u16::from_le_bytes([bytes[10], bytes[11]]),
}
}
}
pub struct Descriptors<'a> {
buf: &'a [u8],
pos: usize,
}
impl<'a> Descriptors<'a> {
pub fn new(buf: &'a [u8]) -> Self {
Self { buf, pos: 0 }
}
}
impl<'a> Iterator for Descriptors<'a> {
type Item = &'a [u8];
fn next(&mut self) -> Option<&'a [u8]> {
if self.pos + 2 > self.buf.len() {
return None;
}
let len = self.buf[self.pos] as usize;
if len < 2 || self.pos + len > self.buf.len() {
return None;
}
let descriptor = &self.buf[self.pos..self.pos + len];
self.pos += len;
Some(descriptor)
}
}
pub struct ConfigurationDescriptor<'a>(&'a [u8]);
impl<'a> ConfigurationDescriptor<'a> {
pub fn parse(descriptor: &'a [u8]) -> Option<Self> {
if descriptor.len() >= 9 && descriptor[1] == DESCRIPTOR_TYPE_CONFIGURATION {
Some(Self(descriptor))
} else {
None
}
}
pub fn value(&self) -> u8 {
self.0[5]
}
}
pub struct InterfaceDescriptor<'a>(&'a [u8]);
impl<'a> InterfaceDescriptor<'a> {
pub fn parse(descriptor: &'a [u8]) -> Option<Self> {
if descriptor.len() >= 9 && descriptor[1] == DESCRIPTOR_TYPE_INTERFACE {
Some(Self(descriptor))
} else {
None
}
}
pub fn number(&self) -> u8 {
self.0[2]
}
pub fn class(&self) -> u8 {
self.0[5]
}
pub fn subclass(&self) -> u8 {
self.0[6]
}
pub fn protocol(&self) -> u8 {
self.0[7]
}
}
pub struct EndpointDescriptor<'a>(&'a [u8]);
impl<'a> EndpointDescriptor<'a> {
pub fn parse(descriptor: &'a [u8]) -> Option<Self> {
if descriptor.len() >= 7 && descriptor[1] == DESCRIPTOR_TYPE_ENDPOINT {
Some(Self(descriptor))
} else {
None
}
}
pub fn number(&self) -> u8 {
self.0[2] & 0x0f
}
pub fn is_in(&self) -> bool {
self.0[2] & 0x80 != 0
}
pub fn is_interrupt(&self) -> bool {
self.0[3] & 0x03 == 3
}
pub fn is_bulk(&self) -> bool {
self.0[3] & 0x03 == 2
}
pub fn max_packet_size(&self) -> u16 {
u16::from_le_bytes([self.0[4], self.0[5]])
}
pub fn interval(&self) -> u8 {
self.0[6]
}
}