/// 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, PartialEq)] #[repr(C, packed)] pub struct USBDeviceDescriptor { pub b_length: u8, pub b_descriptor_type: USBDescriptor, 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, PartialEq)] #[repr(C, packed)] pub struct USBConfigurationDescriptor { pub b_length: u8, pub b_descriptor_type: USBDescriptor, 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, PartialEq)] #[repr(C, packed)] pub struct USBInterfaceDescriptor { pub b_length: u8, pub b_descriptor_type: USBDescriptor, 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, PartialEq)] #[repr(C, packed)] pub struct USBEndpointDescriptor { pub b_length: u8, pub b_descriptor_type: USBDescriptor, pub b_endpoint_address: u8, pub bm_attributes: u8, pub w_max_packet_size: u16, pub b_interval: u8, } #[derive(Copy, Clone, Debug, Default, PartialEq)] #[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"), } } } impl Default for USBRequest { fn default() -> Self { Self::GetStatus } } #[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, } impl Default for USBDescriptor { fn default() -> Self { Self::Device } } #[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, } #[cfg(test)] mod test { use super::super::pipe::DataBuf; use super::*; #[test] fn dev_desc_serialize() { let desc = USBDeviceDescriptor { b_length: 18, b_descriptor_type: USBDescriptor::Device, bcd_usb: 0x0110, b_device_class: 0x02, b_device_sub_class: 0x03, b_device_protocol: 0x04, b_max_packet_size: 64, id_vendor: 0xdead, id_product: 0xbeef, bcd_device: 0x5432, i_manufacturer: 0xa0, i_product: 0xa1, i_serial_number: 0xa2, b_num_configurations: 1, }; let want = [ 0x12, 0x01, 0x10, 0x01, 0x02, 0x03, 0x04, 64, 0xad, 0xde, 0xef, 0xbe, 0x32, 0x54, 0xa0, 0xa1, 0xa2, 1, ]; serde_test(desc, &want); } #[test] fn config_desc_serialize() { let desc = USBConfigurationDescriptor { b_length: 18, b_descriptor_type: USBDescriptor::Configuration, w_total_length: 0x20, b_num_interfaces: 5, b_configuration_value: 10, i_configuration: 1, bm_attributes: 0x40, b_max_power: 0xfa, }; let want = [0x12, 0x02, 0x20, 0x00, 0x05, 0x0a, 0x01, 0x40, 0xfa]; serde_test(desc, &want); } #[test] fn interface_desc_serialize() { let desc = USBInterfaceDescriptor { b_length: 18, b_descriptor_type: USBDescriptor::Interface, b_interface_number: 2, b_alternate_setting: 0xaa, b_num_endpoints: 5, b_interface_class: 0x11, b_interface_sub_class: 0x22, b_interface_protocol: 0x33, i_interface: 10, }; let want = [0x12, 0x04, 0x02, 0xaa, 0x05, 0x11, 0x22, 0x33, 0x0a]; serde_test(desc, &want); } #[test] fn endpoint_desc_serialize() { let desc = USBEndpointDescriptor { b_length: 18, b_descriptor_type: USBDescriptor::Endpoint, b_endpoint_address: 1, bm_attributes: 0x22, w_max_packet_size: 0xdead, b_interval: 0x33, }; let want = [0x12, 0x05, 0x01, 0x22, 0xad, 0xde, 0x33]; serde_test(desc, &want); } #[test] fn setup_packet_serialize() { let setup_packet = USBSetupPacket { bm_request_type: BMRequestType::get_descr(), b_request: USBRequest::GetDescriptor, w_value: WValue::from((0x00, 0x01)), w_index: 0xbeef, w_length: 18, }; let want = [0x80, 0x06, 0x00, 0x01, 0xef, 0xbe, 0x012, 0x00]; serde_test(setup_packet, &want); } fn serde_test(mut native: T, raw: &[u8]) where T: Default + PartialEq + core::fmt::Debug, { let db = DataBuf::from(&mut native); assert_eq!(db.len, raw.len()); // Serialization. let got_raw = unsafe { core::slice::from_raw_parts(db.ptr, db.len) }; assert_eq!(got_raw, raw); // Deserialization. let mut got_native: T = Default::default(); let db = DataBuf::from(&mut got_native); let dbslice = unsafe { core::slice::from_raw_parts_mut(db.ptr, db.len) }; for i in 0..db.len { dbslice[i] = raw[i]; } assert_eq!(got_native, native); } }