yggdrasil/kernel/driver/bus/usb/src/descriptor.rs
Mark Poliakov 18fa8b954a Add 'kernel/' from commit '7f1f6b73377367db17f98a740316b904c37ce3b1'
git-subtree-dir: kernel
git-subtree-mainline: 817f71f90f97270dd569fd44246bf74e57636552
git-subtree-split: 7f1f6b73377367db17f98a740316b904c37ce3b1
2024-03-12 15:52:48 +02:00

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),
}
}
}