use core::num::NonZero;
use alloc::{string::String, vec::Vec};
use crate::transfer::Direction;
mod class_code;
mod lang_id;
mod parser;
pub use class_code::*;
pub use lang_id::*;
pub use parser::decode_string_descriptor;
#[repr(C)]
#[derive(Debug, Clone)]
pub struct DescriptorType(pub u8);
impl DescriptorType {
pub const DEVICE: Self = Self(0x01);
pub const CONFIGURATION: Self = Self(0x02);
pub const STRING: Self = Self(0x03);
pub const INTERFACE: Self = Self(0x04);
pub const ENDPOINT: Self = Self(0x05);
pub const INTERFACE_POWER: Self = Self(0x08);
pub const OTG: Self = Self(0x09);
pub const DEBUG: Self = Self(0x0A);
pub const INTERFACE_ASSOCIATION: Self = Self(0x0B);
pub const BOS: Self = Self(0x0F);
pub const DEVICE_CAPABILITY: Self = Self(0x10);
pub const SUPERSPEED_USB_ENDPOINT_COMPANION: Self = Self(0x30);
pub const SUPERSPEEDPLUS_ISOCHRONOUS_ENDPOINT_COMPANION: Self = Self(0x31);
pub const HUB: Self = Self(0x29);
}
impl From<u8> for DescriptorType {
fn from(value: u8) -> Self {
Self(value)
}
}
impl From<DescriptorType> for u8 {
fn from(desc_type: DescriptorType) -> Self {
desc_type.0
}
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct DeviceDescriptorBase {
pub length: u8,
pub descriptor_type: u8,
pub usb_version: u16,
pub class: u8,
pub subclass: u8,
pub protocol: u8,
pub max_packet_size_0: u8,
}
impl DeviceDescriptorBase {
pub fn class(&self) -> Class {
Class::from_class_and_subclass(self.class, self.subclass, self.protocol)
}
}
#[derive(Debug, Clone)]
pub struct DeviceDescriptor {
pub usb_version: u16,
pub class: u8,
pub subclass: u8,
pub protocol: u8,
pub max_packet_size_0: u8,
pub vendor_id: u16,
pub product_id: u16,
pub device_version: u16,
pub manufacturer_string_index: Option<NonZero<u8>>,
pub product_string_index: Option<NonZero<u8>>,
pub serial_number_string_index: Option<NonZero<u8>>,
pub num_configurations: u8,
}
impl DeviceDescriptor {
pub fn parse(data: &[u8]) -> Option<Self> {
parser::DeviceDescriptor::new(data).map(Into::into)
}
pub const LEN: usize = 18;
pub fn class(&self) -> Class {
Class::from_class_and_subclass(self.class, self.subclass, self.protocol)
}
}
#[derive(Debug, Clone)]
pub struct InterfaceDescriptor {
pub interface_number: u8,
pub alternate_setting: u8,
pub class: u8,
pub subclass: u8,
pub protocol: u8,
pub string_index: Option<NonZero<u8>>,
pub string: Option<String>,
pub num_endpoints: u8,
pub endpoints: Vec<EndpointDescriptor>,
}
impl InterfaceDescriptor {
pub fn class(&self) -> Class {
Class::from_class_and_subclass(self.class, self.subclass, self.protocol)
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum EndpointType {
Control = 0,
Isochronous = 1,
Bulk = 2,
Interrupt = 3,
}
#[derive(Debug, Clone)]
pub struct EndpointDescriptor {
pub address: u8,
pub max_packet_size: u16,
pub transfer_type: EndpointType,
pub direction: Direction,
pub packets_per_microframe: usize,
pub interval: u8,
}
impl EndpointDescriptor {
pub fn dci(&self) -> u8 {
let endpoint_number = self.address & 0x0F; (endpoint_number * 2)
+ match self.transfer_type {
EndpointType::Control => 1, _ => {
if self.direction == Direction::In {
1
} else {
0
}
}
}
}
}
#[derive(Debug, Clone)]
pub struct InterfaceDescriptors {
pub interface_number: u8,
pub alt_settings: Vec<InterfaceDescriptor>,
}
impl InterfaceDescriptors {
pub fn first_alt_setting(&self) -> InterfaceDescriptor {
self.alt_settings.first().cloned().unwrap()
}
}
#[derive(Debug, Clone)]
pub struct ConfigurationDescriptor {
pub num_interfaces: u8,
pub configuration_value: u8,
pub attributes: u8,
pub max_power: u8,
pub string_index: Option<NonZero<u8>>,
pub string: Option<String>,
pub interfaces: Vec<InterfaceDescriptors>,
pub raw: Vec<u8>,
}
impl ConfigurationDescriptor {
pub fn parse(data: &[u8]) -> Option<Self> {
parser::ConfigurationDescriptor::new(data).map(Into::into)
}
pub const LEN: usize = 9;
}
impl From<parser::DeviceDescriptor> for DeviceDescriptor {
fn from(desc: parser::DeviceDescriptor) -> Self {
DeviceDescriptor {
usb_version: desc.usb_version(),
class: desc.class(),
subclass: desc.subclass(),
protocol: desc.protocol(),
max_packet_size_0: desc.max_packet_size_0(),
vendor_id: desc.vendor_id(),
product_id: desc.product_id(),
device_version: desc.device_version(),
manufacturer_string_index: desc.manufacturer_string_index(),
product_string_index: desc.product_string_index(),
serial_number_string_index: desc.serial_number_string_index(),
num_configurations: desc.num_configurations(),
}
}
}
impl From<parser::EndpointDescriptor<'_>> for EndpointDescriptor {
fn from(desc: parser::EndpointDescriptor) -> Self {
EndpointDescriptor {
address: desc.address(),
max_packet_size: desc.max_packet_size() as _,
direction: desc.direction(),
transfer_type: desc.transfer_type(),
packets_per_microframe: desc.packets_per_microframe() as usize,
interval: desc.interval(),
}
}
}
impl From<parser::ConfigurationDescriptor<'_>> for ConfigurationDescriptor {
fn from(desc: parser::ConfigurationDescriptor) -> Self {
ConfigurationDescriptor {
num_interfaces: desc.num_interfaces(),
configuration_value: desc.configuration_value(),
attributes: desc.attributes(),
max_power: desc.max_power(),
string_index: desc.string_index(),
interfaces: desc.interfaces().map(InterfaceDescriptors::from).collect(),
string: None,
raw: desc.as_bytes().to_vec(),
}
}
}
impl From<parser::InterfaceDescriptor<'_>> for InterfaceDescriptor {
fn from(desc: parser::InterfaceDescriptor) -> Self {
InterfaceDescriptor {
interface_number: desc.interface_number(),
alternate_setting: desc.alternate_setting(),
class: desc.class(),
subclass: desc.subclass(),
protocol: desc.protocol(),
string_index: desc.string_index(),
num_endpoints: desc.num_endpoints(),
endpoints: desc.endpoints().map(EndpointDescriptor::from).collect(),
string: None,
}
}
}
impl From<parser::InterfaceDescriptors<'_>> for InterfaceDescriptors {
fn from(desc: parser::InterfaceDescriptors) -> Self {
InterfaceDescriptors {
interface_number: desc.interface_number(),
alt_settings: desc.alt_settings().map(InterfaceDescriptor::from).collect(),
}
}
}