1use core::convert::{TryFrom, TryInto};
11
12#[derive(Clone, Copy, Debug, PartialEq)]
13#[repr(C)]
14pub struct RequestType(u8);
15impl RequestType {
16 pub fn recipient(self) -> Result<RequestRecipient, &'static str> {
17 const POS: u8 = 0;
18 const MASK: u8 = 0x1f;
19 (self.0 & (MASK << POS)).try_into()
20 }
21
22 pub fn set_recipient(&mut self, v: RequestRecipient) {
23 const POS: u8 = 0;
24 const MASK: u8 = 0x1f;
25 self.0 &= !(MASK << POS);
26 self.0 |= v as u8 & MASK;
27 }
28
29 pub fn kind(self) -> Result<RequestKind, &'static str> {
30 const POS: u8 = 5;
31 const MASK: u8 = 0x3;
32 (self.0 & (MASK << POS)).try_into()
33 }
34
35 pub fn set_kind(&mut self, v: RequestKind) {
36 const POS: u8 = 5;
37 const MASK: u8 = 0x3;
38 self.0 &= !(MASK << POS);
39 self.0 |= v as u8 & MASK;
40 }
41
42 pub fn direction(self) -> Result<RequestDirection, &'static str> {
43 const POS: u8 = 7;
44 const MASK: u8 = 0x1;
45 (self.0 & (MASK << POS)).try_into()
46 }
47
48 pub fn set_direction(&mut self, v: RequestDirection) {
49 const POS: u8 = 7;
50 const MASK: u8 = 0x1;
51 self.0 &= !(MASK << POS);
52 self.0 |= v as u8 & MASK;
53 }
54}
55impl From<(RequestDirection, RequestKind, RequestRecipient)> for RequestType {
56 fn from(v: (RequestDirection, RequestKind, RequestRecipient)) -> Self {
57 Self(v.0 as u8 | v.1 as u8 | v.2 as u8)
58 }
59}
60
61#[derive(Copy, Clone, Debug, PartialEq)]
62pub enum RequestDirection {
63 HostToDevice = 0x00,
64 DeviceToHost = 0x80,
65}
66impl TryFrom<u8> for RequestDirection {
67 type Error = &'static str;
68
69 fn try_from(v: u8) -> Result<Self, Self::Error> {
70 match v {
71 0x00 => Ok(Self::HostToDevice),
72 0x80 => Ok(Self::DeviceToHost),
73 _ => Err("direction can only be 0x00 or 0x80"),
74 }
75 }
76}
77
78#[derive(Copy, Clone, Debug, PartialEq)]
79pub enum RequestKind {
80 Standard = 0x00,
81 Class = 0x20,
82 Vendor = 0x40,
83}
84impl TryFrom<u8> for RequestKind {
85 type Error = &'static str;
86
87 fn try_from(v: u8) -> Result<Self, Self::Error> {
88 match v {
89 0x00 => Ok(Self::Standard),
90 0x20 => Ok(Self::Class),
91 0x40 => Ok(Self::Vendor),
92 _ => Err("type can only be 0x00, 0x20, or 0x40"),
93 }
94 }
95}
96
97#[derive(Copy, Clone, Debug, PartialEq)]
98pub enum RequestRecipient {
99 Device = 0x00,
100 Interface = 0x01,
101 Endpoint = 0x02,
102 Other = 0x03,
103}
104impl TryFrom<u8> for RequestRecipient {
105 type Error = &'static str;
106
107 fn try_from(v: u8) -> Result<Self, Self::Error> {
108 match v {
109 0x00 => Ok(Self::Device),
110 0x01 => Ok(Self::Interface),
111 0x02 => Ok(Self::Endpoint),
112 0x03 => Ok(Self::Other),
113 _ => Err("recipient can only be between 0 and 3"),
114 }
115 }
116}
117
118#[derive(Clone, Copy, Debug, Default, PartialEq)]
119#[repr(C)]
120pub struct WValue(u16);
121impl WValue {
122 pub fn w_value_lo(self) -> u8 {
123 const POS: u8 = 0;
124 const MASK: u16 = 0xff;
125 ((self.0 >> POS) & MASK) as u8
126 }
127
128 pub fn set_w_value_lo(&mut self, v: u8) {
129 const POS: u8 = 0;
130 const MASK: u8 = 0xff;
131 self.0 &= !(u16::from(MASK) << POS);
132 self.0 |= u16::from(v & MASK) << POS;
133 }
134
135 pub fn w_value_hi(self) -> u8 {
136 const POS: u8 = 8;
137 const MASK: u16 = 0xff;
138 ((self.0 >> POS) & MASK) as u8
139 }
140
141 pub fn set_w_value_hi(&mut self, v: u8) {
142 const POS: u8 = 8;
143 const MASK: u8 = 0xff;
144 self.0 &= !(u16::from(MASK) << POS);
145 self.0 |= u16::from(v & MASK) << POS;
146 }
147}
148impl From<(u8, u8)> for WValue {
149 fn from(v: (u8, u8)) -> Self {
150 let mut rc = Self(0);
151 rc.set_w_value_lo(v.0);
152 rc.set_w_value_hi(v.1);
153 rc
154 }
155}
156
157#[derive(Clone, Copy, Debug, PartialEq)]
158pub enum RequestCode {
159 GetStatus = 0,
160 ClearFeature = 1,
161 SetFeature = 3,
162 SetAddress = 5,
163 GetDescriptor = 6,
164 SetDescriptor = 7,
165 GetConfiguration = 8,
166 SetConfiguration = 9,
167 GetInterface = 10,
168 SetInterface = 11,
169 SynchFrame = 12,
170}
171impl TryFrom<u8> for RequestCode {
172 type Error = &'static str;
173
174 fn try_from(v: u8) -> Result<Self, Self::Error> {
175 match v {
176 0 => Ok(Self::GetStatus),
177 1 => Ok(Self::ClearFeature),
178 3 => Ok(Self::SetFeature),
179 5 => Ok(Self::SetAddress),
180 6 => Ok(Self::GetDescriptor),
181 7 => Ok(Self::SetDescriptor),
182 8 => Ok(Self::GetConfiguration),
183 9 => Ok(Self::SetConfiguration),
184 10 => Ok(Self::GetInterface),
185 11 => Ok(Self::SetInterface),
186 12 => Ok(Self::SynchFrame),
187 _ => Err("invalid request value"),
188 }
189 }
190}
191impl Default for RequestCode {
192 fn default() -> Self {
193 Self::GetStatus
194 }
195}
196
197#[derive(Copy, Clone, Debug)]
198#[repr(C, packed)]
199pub struct SetupPacket {
200 pub bm_request_type: RequestType,
201 pub b_request: RequestCode,
202 pub w_value: WValue,
203 pub w_index: u16,
204 pub w_length: u16,
205}
206
207#[cfg(test)]
208mod test {
209 use super::*;
210
211 use core::mem;
212 use core::slice;
213
214 #[test]
215 fn setup_packet_layout() {
216 let len = mem::size_of::<SetupPacket>();
217 assert_eq!(len, 8);
218 let sp = SetupPacket {
219 bm_request_type: RequestType::from((
220 RequestDirection::HostToDevice,
221 RequestKind::Class,
222 RequestRecipient::Endpoint,
223 )),
224 b_request: RequestCode::GetInterface,
225 w_value: WValue::from((0xf0, 0x0d)),
226 w_index: 0xadde,
227 w_length: 0xefbe,
228 };
229 let base = &sp as *const _ as usize;
230 assert_offset("bm_request_type", &sp.bm_request_type, base, 0x00);
231 assert_offset("b_request", &sp.b_request, base, 0x01);
232 assert_offset("w_value", &sp.w_value, base, 0x02);
233 assert_offset("w_index", &sp.w_index, base, 0x04);
234 assert_offset("w_length", &sp.w_length, base, 0x06);
235
236 let got = unsafe { slice::from_raw_parts(&sp as *const _ as *const u8, len) };
237 let want = &[0x22, 0x0a, 0xf0, 0x0d, 0xde, 0xad, 0xbe, 0xef];
238 assert_eq!(got, want);
239 }
240
241 fn assert_offset<T>(name: &str, field: &T, base: usize, offset: usize) {
242 let ptr = field as *const _ as usize;
243 assert_eq!(ptr - base, offset, "{} register offset.", name);
244 }
245}