git-subtree-dir: kernel git-subtree-mainline: 817f71f90f97270dd569fd44246bf74e57636552 git-subtree-split: 7f1f6b73377367db17f98a740316b904c37ce3b1
147 lines
3.7 KiB
Rust
147 lines
3.7 KiB
Rust
use bytemuck::{Pod, Zeroable};
|
|
|
|
use crate::{
|
|
error::UsbError,
|
|
info::{UsbDeviceClass, UsbDeviceProtocol, UsbEndpointType},
|
|
UsbDirection,
|
|
};
|
|
|
|
#[derive(Clone, Copy, Debug, Default, Pod, Zeroable)]
|
|
#[repr(C, packed)]
|
|
pub struct UsbDeviceDescriptor {
|
|
pub length: u8,
|
|
pub ty: u8,
|
|
pub bcd_usb: u16,
|
|
pub device_class: u8,
|
|
pub device_subclass: u8,
|
|
pub device_protocol: u8,
|
|
pub max_packet_size_0: u8,
|
|
pub id_vendor: u16,
|
|
pub id_product: u16,
|
|
pub bcd_device: u16,
|
|
pub manufacturer_str: u8,
|
|
pub product_str: u8,
|
|
pub serial_number_str: u8,
|
|
pub num_configurations: u8,
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, Default, Pod, Zeroable)]
|
|
#[repr(C, packed)]
|
|
pub struct UsbConfigurationDescriptor {
|
|
pub length: u8,
|
|
pub ty: u8,
|
|
pub total_length: u16,
|
|
pub num_interfaces: u8,
|
|
pub config_val: u8,
|
|
pub config_str: u8,
|
|
pub attributes: u8,
|
|
pub max_power: u8,
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, Default, Pod, Zeroable)]
|
|
#[repr(C, packed)]
|
|
pub struct UsbInterfaceDescriptor {
|
|
pub length: u8,
|
|
pub ty: u8,
|
|
pub interface_number: u8,
|
|
pub alternate_setting: u8,
|
|
pub num_endpoints: u8,
|
|
pub interface_class: u8,
|
|
pub interface_subclass: u8,
|
|
pub interface_protocol: u8,
|
|
pub interface_str: u8,
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, Default, Pod, Zeroable)]
|
|
#[repr(C, packed)]
|
|
pub struct UsbEndpointDescriptor {
|
|
pub length: u8,
|
|
pub ty: u8,
|
|
pub endpoint_address: u8,
|
|
pub attributes: u8,
|
|
pub max_packet_size: u16,
|
|
pub interval: u8,
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, Default, Pod, Zeroable)]
|
|
#[repr(C, packed)]
|
|
pub struct UsbDeviceQualifier {
|
|
pub length: u8,
|
|
pub ty: u8,
|
|
pub bcd_usb: u16,
|
|
pub device_class: u8,
|
|
pub device_subclass: u8,
|
|
pub device_protocol: u8,
|
|
pub max_packet_size_0: u8,
|
|
pub num_configurations: u8,
|
|
pub _reserved: u8,
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, Default, Pod, Zeroable)]
|
|
#[repr(C, packed)]
|
|
pub struct UsbOtherSpeedConfiguration {
|
|
pub length: u8,
|
|
pub ty: u8,
|
|
pub total_length: u16,
|
|
pub num_interfaces: u8,
|
|
pub config_val: u8,
|
|
pub config_str: u8,
|
|
pub attributes: u8,
|
|
pub max_power: u8,
|
|
}
|
|
|
|
impl UsbInterfaceDescriptor {
|
|
pub fn class(&self) -> UsbDeviceClass {
|
|
UsbDeviceClass::try_from(self.interface_class).unwrap_or(UsbDeviceClass::Unknown)
|
|
}
|
|
|
|
pub fn protocol(&self) -> UsbDeviceProtocol {
|
|
UsbDeviceProtocol::try_from(self.interface_protocol).unwrap_or(UsbDeviceProtocol::Unknown)
|
|
}
|
|
}
|
|
|
|
impl UsbEndpointDescriptor {
|
|
pub fn direction(&self) -> UsbDirection {
|
|
match self.endpoint_address >> 7 {
|
|
1 => UsbDirection::In,
|
|
0 => UsbDirection::Out,
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
|
|
pub fn number(&self) -> u8 {
|
|
assert_ne!(self.endpoint_address & 0xF, 0);
|
|
self.endpoint_address & 0xF
|
|
}
|
|
|
|
pub fn transfer_type(&self) -> UsbEndpointType {
|
|
match self.attributes & 0x3 {
|
|
0 => UsbEndpointType::Control,
|
|
1 => UsbEndpointType::Isochronous,
|
|
2 => UsbEndpointType::Bulk,
|
|
3 => UsbEndpointType::Interrupt,
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl UsbDeviceDescriptor {
|
|
pub fn class(&self) -> UsbDeviceClass {
|
|
UsbDeviceClass::try_from(self.device_class).unwrap_or(UsbDeviceClass::Unknown)
|
|
}
|
|
|
|
pub fn protocol(&self) -> UsbDeviceProtocol {
|
|
UsbDeviceProtocol::try_from(self.device_protocol).unwrap_or(UsbDeviceProtocol::Unknown)
|
|
}
|
|
|
|
pub fn max_packet_size(&self) -> Result<usize, UsbError> {
|
|
match self.max_packet_size_0 {
|
|
8 => Ok(8),
|
|
16 => Ok(16),
|
|
32 => Ok(32),
|
|
64 => Ok(64),
|
|
_ => Err(UsbError::InvalidDescriptorField),
|
|
}
|
|
}
|
|
}
|