/// USB Protocol level types and functions. /// /// Everything in here is defined by the USB specification, and /// hardware independent. // TODO: Put protocol section references in for types and // documentation. #[derive(Copy, Clone, Debug, Default)] #[repr(C, packed)] pub struct USBDeviceDescriptor { pub b_length: u8, pub b_descriptor_type: u8, pub bcd_usb: u16, pub b_device_class: u8, pub b_device_sub_class: u8, pub b_device_protocol: u8, pub b_max_packet_size: u8, pub id_vendor: u16, pub id_product: u16, pub bcd_device: u16, pub i_manufacturer: u8, pub i_product: u8, pub i_serial_number: u8, pub b_num_configurations: u8, } #[derive(Copy, Clone, Debug, Default)] #[repr(C, packed)] pub struct USBConfigurationDescriptor { pub b_length: u8, pub b_descriptor_type: u8, pub w_total_length: u16, pub b_num_interfaces: u8, pub b_configuration_value: u8, pub i_configuration: u8, pub bm_attributes: u8, pub b_max_power: u8, } #[derive(Copy, Clone, Debug, Default)] #[repr(C, packed)] pub struct USBInterfaceDescriptor { pub b_length: u8, pub b_descriptor_type: u8, pub b_interface_number: u8, pub b_alternate_setting: u8, pub b_num_endpoints: u8, pub b_interface_class: u8, pub b_interface_sub_class: u8, pub b_interface_protocol: u8, pub i_interface: u8, } #[derive(Copy, Clone, Debug, Default)] #[repr(C, packed)] pub struct USBEndpointDescriptor { pub b_length: u8, pub b_descriptor_type: u8, pub b_endpoint_address: u8, pub bm_attributes: u8, pub w_max_packet_size: u16, pub b_interval: u8, } #[derive(Copy, Clone, Debug)] #[repr(C, packed)] pub struct USBSetupPacket { pub bm_request_type: BMRequestType, pub b_request: USBRequest, pub w_value: WValue, pub w_index: u16, pub w_length: u16, } // TODO: shortcuts for standard device requests ยง9.4 of USB standard. #[derive(Copy, Clone, Debug, PartialEq)] pub enum USBSetupDirection { HostToDevice = 0x00, DeviceToHost = 0x80, } impl From for USBSetupDirection where T: Into, { fn from(v: T) -> Self { match v.into() { 0x00 => Self::HostToDevice, 0x80 => Self::DeviceToHost, _ => panic!("direction can only be 0x00 or 0x80"), } } } #[derive(Copy, Clone, Debug, PartialEq)] pub enum USBSetupType { Standard = 0x00, Class = 0x20, Vendor = 0x40, } impl From for USBSetupType where T: Into, { fn from(v: T) -> Self { match v.into() { 0x00 => Self::Standard, 0x20 => Self::Class, 0x40 => Self::Vendor, _ => panic!("type can only be 0x00, 0x20, or 0x40"), } } } #[derive(Copy, Clone, Debug, PartialEq)] pub enum USBSetupRecipient { Device = 0x00, Interface = 0x01, Endpoint = 0x02, Other = 0x03, } impl From for USBSetupRecipient where T: Into, { fn from(v: T) -> Self { match v.into() { 0x00 => Self::Device, 0x01 => Self::Interface, 0x02 => Self::Endpoint, 0x03 => Self::Other, _ => panic!("recipient can only be between 0 and 3"), } } } #[derive(Clone, Copy, Debug, Default, PartialEq)] #[repr(C)] pub struct BMRequestType(u8); impl BMRequestType { // Get descriptor request type. pub fn get_descr() -> Self { Self::from(( USBSetupDirection::DeviceToHost, USBSetupType::Standard, USBSetupRecipient::Device, )) } // Set request type for all but 'set feature' and 'set interface'. pub fn set() -> Self { Self::from(( USBSetupDirection::HostToDevice, USBSetupType::Standard, USBSetupRecipient::Device, )) } // Get interface request type. pub fn cl_get_intf() -> Self { Self::from(( USBSetupDirection::DeviceToHost, USBSetupType::Class, USBSetupRecipient::Interface, )) } pub fn recipient(&self) -> USBSetupRecipient { const POS: u8 = 0; const MASK: u8 = 0x1f; (self.0 & (MASK << POS)).into() } pub fn set_recipient(&mut self, v: USBSetupRecipient) { const POS: u8 = 0; const MASK: u8 = 0x1f; self.0 &= !(MASK << POS); self.0 |= v as u8 & MASK; } pub fn typ(&self) -> USBSetupType { const POS: u8 = 5; const MASK: u8 = 0x3; (self.0 & (MASK << POS)).into() } pub fn set_typ(&mut self, v: USBSetupType) { const POS: u8 = 5; const MASK: u8 = 0x3; self.0 &= !(MASK << POS); self.0 |= v as u8 & MASK; } pub fn direction(&self) -> USBSetupDirection { const POS: u8 = 7; const MASK: u8 = 0x1; (self.0 & (MASK << POS)).into() } pub fn set_direction(&mut self, v: USBSetupDirection) { const POS: u8 = 7; const MASK: u8 = 0x1; self.0 &= !(MASK << POS); self.0 |= v as u8 & MASK; } } impl From for BMRequestType { fn from(v: u8) -> Self { Self(v) } } impl From<(USBSetupDirection, USBSetupType, USBSetupRecipient)> for BMRequestType { fn from(v: (USBSetupDirection, USBSetupType, USBSetupRecipient)) -> Self { Self(v.0 as u8 | v.1 as u8 | v.2 as u8) } } #[derive(Clone, Copy, Debug, Default, PartialEq)] #[repr(C)] pub struct WValue(u16); impl WValue { pub fn w_value_lo(&self) -> u8 { const POS: u8 = 0; const MASK: u16 = 0xff; ((self.0 >> POS) & MASK) as u8 } pub fn set_w_value_lo(&mut self, v: u8) { const POS: u8 = 0; const MASK: u8 = 0xff; self.0 &= !((MASK as u16) << POS); self.0 |= ((v & MASK) as u16) << POS; } pub fn w_value_hi(&self) -> u8 { const POS: u8 = 8; const MASK: u16 = 0xff; ((self.0 >> POS) & MASK) as u8 } pub fn set_w_value_hi(&mut self, v: u8) { const POS: u8 = 8; const MASK: u8 = 0xff; self.0 &= !((MASK as u16) << POS); self.0 |= ((v & MASK) as u16) << POS; } } impl From<(u8, u8)> for WValue { fn from(v: (u8, u8)) -> Self { let mut rc = Self(0); rc.set_w_value_lo(v.0); rc.set_w_value_hi(v.1); rc } } #[derive(Clone, Copy, Debug, PartialEq)] pub enum USBRequest { GetStatus = 0, ClearFeature = 1, SetFeature = 3, SetAddress = 5, GetDescriptor = 6, SetDescriptor = 7, GetConfiguration = 8, SetConfiguration = 9, GetInterface = 10, SetInterface = 11, SynchFrame = 12, } impl From for USBRequest where T: Into, { fn from(v: T) -> Self { match v.into() { 0 => Self::GetStatus, 1 => Self::ClearFeature, 3 => Self::SetFeature, 5 => Self::SetAddress, 6 => Self::GetDescriptor, 7 => Self::SetDescriptor, 8 => Self::GetConfiguration, 9 => Self::SetConfiguration, 10 => Self::GetInterface, 11 => Self::SetInterface, 12 => Self::SynchFrame, _ => panic!("invalid request value"), } } } #[derive(Clone, Copy, Debug, PartialEq)] pub enum USBFeature { EndpointHalt = 0, DeviceRemoteWakeup = 1, TestMode = 2, } #[derive(Clone, Copy, Debug, PartialEq)] pub enum USBDescriptor { Device = 0x01, Configuration = 0x02, String = 0x03, Interface = 0x04, Endpoint = 0x05, DeviceQualifier = 0x06, OtherSpeed = 0x07, InterfacePower = 0x08, OTG = 0x09, } #[derive(Clone, Copy, Debug, PartialEq)] pub enum HIDDescriptor { HID = 0x21, } #[derive(Clone, Copy, Debug, PartialEq)] pub enum OTGFeature { BHNPEnable = 3, AHNPSupport = 4, AAltHNPSupport = 5, } #[derive(Clone, Copy, Debug, PartialEq)] pub enum USBTransferType { Control = 0x00, Isochronous = 0x01, Bulk = 0x02, Interrupt = 0x03, }