/// USB Protocol level types and functions. /// /// Everything in here is defined by the USB specification, and /// hardware independent. use core::convert::TryFrom; use core::convert::TryInto; // TODO: Put protocol section references in for types and // documentation. #[derive(Copy, Clone, Debug, Default, PartialEq)] #[repr(C, packed)] pub struct DeviceDescriptor { pub b_length: u8, pub b_descriptor_type: DescriptorType, 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 ConfigurationDescriptor { pub b_length: u8, pub b_descriptor_type: DescriptorType, 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 InterfaceDescriptor { pub b_length: u8, pub b_descriptor_type: DescriptorType, 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 EndpointDescriptor { pub b_length: u8, pub b_descriptor_type: DescriptorType, 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 SetupPacket { pub bm_request_type: RequestType, pub b_request: RequestCode, pub w_value: WValue, pub w_index: u16, pub w_length: u16, } #[derive(Clone, Copy, Debug, Default, PartialEq)] #[repr(C)] pub struct RequestType(u8); impl RequestType { // Get descriptor request type. pub fn get_descr() -> Self { Self::from(( RequestDirection::DeviceToHost, RequestKind::Standard, RequestRecipient::Device, )) } // Set request type for all but 'set feature' and 'set interface'. pub fn set() -> Self { Self::from(( RequestDirection::HostToDevice, RequestKind::Standard, RequestRecipient::Device, )) } // Get interface request type. pub fn cl_get_intf() -> Self { Self::from(( RequestDirection::DeviceToHost, RequestKind::Class, RequestRecipient::Interface, )) } pub fn recipient(&self) -> Result { const POS: u8 = 0; const MASK: u8 = 0x1f; (self.0 & (MASK << POS)).try_into() } pub fn set_recipient(&mut self, v: RequestRecipient) { const POS: u8 = 0; const MASK: u8 = 0x1f; self.0 &= !(MASK << POS); self.0 |= v as u8 & MASK; } pub fn kind(&self) -> Result { const POS: u8 = 5; const MASK: u8 = 0x3; (self.0 & (MASK << POS)).try_into() } pub fn set_kind(&mut self, v: RequestKind) { const POS: u8 = 5; const MASK: u8 = 0x3; self.0 &= !(MASK << POS); self.0 |= v as u8 & MASK; } pub fn direction(&self) -> Result { const POS: u8 = 7; const MASK: u8 = 0x1; (self.0 & (MASK << POS)).try_into() } pub fn set_direction(&mut self, v: RequestDirection) { const POS: u8 = 7; const MASK: u8 = 0x1; self.0 &= !(MASK << POS); self.0 |= v as u8 & MASK; } } impl From<(RequestDirection, RequestKind, RequestRecipient)> for RequestType { fn from(v: (RequestDirection, RequestKind, RequestRecipient)) -> Self { Self(v.0 as u8 | v.1 as u8 | v.2 as u8) } } #[derive(Copy, Clone, Debug, PartialEq)] pub enum RequestDirection { HostToDevice = 0x00, DeviceToHost = 0x80, } impl TryFrom for RequestDirection { type Error = &'static str; fn try_from(v: u8) -> Result { match v { 0x00 => Ok(Self::HostToDevice), 0x80 => Ok(Self::DeviceToHost), _ => Err("direction can only be 0x00 or 0x80"), } } } #[derive(Copy, Clone, Debug, PartialEq)] pub enum RequestKind { Standard = 0x00, Class = 0x20, Vendor = 0x40, } impl TryFrom for RequestKind { type Error = &'static str; fn try_from(v: u8) -> Result { match v { 0x00 => Ok(Self::Standard), 0x20 => Ok(Self::Class), 0x40 => Ok(Self::Vendor), _ => Err("type can only be 0x00, 0x20, or 0x40"), } } } #[derive(Copy, Clone, Debug, PartialEq)] pub enum RequestRecipient { Device = 0x00, Interface = 0x01, Endpoint = 0x02, Other = 0x03, } impl TryFrom for RequestRecipient { type Error = &'static str; fn try_from(v: u8) -> Result { match v { 0x00 => Ok(Self::Device), 0x01 => Ok(Self::Interface), 0x02 => Ok(Self::Endpoint), 0x03 => Ok(Self::Other), _ => Err("recipient can only be between 0 and 3"), } } } #[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 RequestCode { GetStatus = 0, ClearFeature = 1, SetFeature = 3, SetAddress = 5, GetDescriptor = 6, SetDescriptor = 7, GetConfiguration = 8, SetConfiguration = 9, GetInterface = 10, SetInterface = 11, SynchFrame = 12, } impl TryFrom for RequestCode { type Error = &'static str; fn try_from(v: u8) -> Result { match v { 0 => Ok(Self::GetStatus), 1 => Ok(Self::ClearFeature), 3 => Ok(Self::SetFeature), 5 => Ok(Self::SetAddress), 6 => Ok(Self::GetDescriptor), 7 => Ok(Self::SetDescriptor), 8 => Ok(Self::GetConfiguration), 9 => Ok(Self::SetConfiguration), 10 => Ok(Self::GetInterface), 11 => Ok(Self::SetInterface), 12 => Ok(Self::SynchFrame), _ => Err("invalid request value"), } } } impl Default for RequestCode { 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 DescriptorType { Device = 1, Configuration = 2, String = 3, Interface = 4, Endpoint = 5, DeviceQualifier = 6, OtherSpeed = 7, InterfacePower = 8, } impl Default for DescriptorType { fn default() -> Self { Self::Device } } #[cfg(test)] mod test { use super::super::pipe::DataBuf; use super::*; #[test] fn dev_desc_serialize() { let desc = DeviceDescriptor { b_length: 18, b_descriptor_type: DescriptorType::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 = ConfigurationDescriptor { b_length: 18, b_descriptor_type: DescriptorType::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 = InterfaceDescriptor { b_length: 18, b_descriptor_type: DescriptorType::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 = EndpointDescriptor { b_length: 18, b_descriptor_type: DescriptorType::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 = SetupPacket { bm_request_type: RequestType::get_descr(), b_request: RequestCode::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); } }