1 // Copyright 2018 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 use std::mem::size_of;
6
7 use static_assertions::const_assert;
8 use zerocopy::AsBytes;
9 use zerocopy::FromBytes;
10
11 /// Standard USB descriptor types.
12 pub enum DescriptorType {
13 Device = 0x01,
14 Configuration = 0x02,
15 Interface = 0x04,
16 Endpoint = 0x05,
17 }
18
19 /// Trait describing USB descriptors.
20 pub trait Descriptor {
21 /// Get the expected bDescriptorType value for this type of descriptor.
descriptor_type() -> DescriptorType22 fn descriptor_type() -> DescriptorType;
23 }
24
25 /// Standard USB descriptor header common to all descriptor types.
26 #[allow(non_snake_case)]
27 #[derive(Copy, Clone, Debug, Default, FromBytes, AsBytes)]
28 #[repr(C, packed)]
29 pub struct DescriptorHeader {
30 pub bLength: u8,
31 pub bDescriptorType: u8,
32 }
33
_assert_descriptor_header()34 fn _assert_descriptor_header() {
35 const_assert!(size_of::<DescriptorHeader>() == 2);
36 }
37
38 /// Standard USB device descriptor as defined in USB 2.0 chapter 9,
39 /// not including the standard header.
40 #[allow(non_snake_case)]
41 #[derive(Copy, Clone, Debug, Default, FromBytes, AsBytes)]
42 #[repr(C, packed)]
43 pub struct DeviceDescriptor {
44 pub bcdUSB: u16,
45 pub bDeviceClass: u8,
46 pub bDeviceSubClass: u8,
47 pub bDeviceProtocol: u8,
48 pub bMaxPacketSize0: u8,
49 pub idVendor: u16,
50 pub idProduct: u16,
51 pub bcdDevice: u16,
52 pub iManufacturer: u8,
53 pub iProduct: u8,
54 pub iSerialNumber: u8,
55 pub bNumConfigurations: u8,
56 }
57
58 impl Descriptor for DeviceDescriptor {
descriptor_type() -> DescriptorType59 fn descriptor_type() -> DescriptorType {
60 DescriptorType::Device
61 }
62 }
63
_assert_device_descriptor()64 fn _assert_device_descriptor() {
65 const_assert!(size_of::<DeviceDescriptor>() == 18 - 2);
66 }
67
68 /// Standard USB configuration descriptor as defined in USB 2.0 chapter 9,
69 /// not including the standard header.
70 #[allow(non_snake_case)]
71 #[derive(Copy, Clone, Debug, Default, FromBytes, AsBytes)]
72 #[repr(C, packed)]
73 pub struct ConfigDescriptor {
74 pub wTotalLength: u16,
75 pub bNumInterfaces: u8,
76 pub bConfigurationValue: u8,
77 pub iConfiguration: u8,
78 pub bmAttributes: u8,
79 pub bMaxPower: u8,
80 }
81
82 impl Descriptor for ConfigDescriptor {
descriptor_type() -> DescriptorType83 fn descriptor_type() -> DescriptorType {
84 DescriptorType::Configuration
85 }
86 }
87
_assert_config_descriptor()88 fn _assert_config_descriptor() {
89 const_assert!(size_of::<ConfigDescriptor>() == 9 - 2);
90 }
91
92 impl ConfigDescriptor {
num_interfaces(&self) -> u893 pub fn num_interfaces(&self) -> u8 {
94 self.bNumInterfaces
95 }
96 }
97
98 /// Standard USB interface descriptor as defined in USB 2.0 chapter 9,
99 /// not including the standard header.
100 #[allow(non_snake_case)]
101 #[derive(Copy, Clone, Debug, Default, FromBytes, AsBytes)]
102 #[repr(C, packed)]
103 pub struct InterfaceDescriptor {
104 pub bInterfaceNumber: u8,
105 pub bAlternateSetting: u8,
106 pub bNumEndpoints: u8,
107 pub bInterfaceClass: u8,
108 pub bInterfaceSubClass: u8,
109 pub bInterfaceProtocol: u8,
110 pub iInterface: u8,
111 }
112
113 impl Descriptor for InterfaceDescriptor {
descriptor_type() -> DescriptorType114 fn descriptor_type() -> DescriptorType {
115 DescriptorType::Interface
116 }
117 }
118
_assert_interface_descriptor()119 fn _assert_interface_descriptor() {
120 const_assert!(size_of::<InterfaceDescriptor>() == 9 - 2);
121 }
122
123 /// Standard USB endpoint descriptor as defined in USB 2.0 chapter 9,
124 /// not including the standard header.
125 #[allow(non_snake_case)]
126 #[derive(Copy, Clone, Debug, Default, FromBytes, AsBytes)]
127 #[repr(C, packed)]
128 pub struct EndpointDescriptor {
129 pub bEndpointAddress: u8,
130 pub bmAttributes: u8,
131 pub wMaxPacketSize: u16,
132 pub bInterval: u8,
133 }
134
135 impl Descriptor for EndpointDescriptor {
descriptor_type() -> DescriptorType136 fn descriptor_type() -> DescriptorType {
137 DescriptorType::Endpoint
138 }
139 }
140
_assert_endpoint_descriptor()141 fn _assert_endpoint_descriptor() {
142 const_assert!(size_of::<EndpointDescriptor>() == 7 - 2);
143 }
144
145 const ENDPOINT_DESCRIPTOR_DIRECTION_MASK: u8 = 1 << 7;
146 const ENDPOINT_DESCRIPTOR_NUMBER_MASK: u8 = 0xf;
147 const ENDPOINT_DESCRIPTOR_ATTRIBUTES_TYPE_MASK: u8 = 0x3;
148
149 /// Endpoint types.
150 #[derive(PartialEq, Eq)]
151 pub enum EndpointType {
152 Control,
153 Isochronous,
154 Bulk,
155 Interrupt,
156 }
157
158 /// Endpoint Directions.
159 #[derive(PartialEq, Eq, Clone, Copy)]
160 pub enum EndpointDirection {
161 HostToDevice = 0,
162 DeviceToHost = 1,
163 }
164 /// Endpoint direction offset.
165 pub const ENDPOINT_DIRECTION_OFFSET: u8 = 7;
166
167 impl EndpointDescriptor {
168 // Get direction of this endpoint.
get_direction(&self) -> EndpointDirection169 pub fn get_direction(&self) -> EndpointDirection {
170 let direction = self.bEndpointAddress & ENDPOINT_DESCRIPTOR_DIRECTION_MASK;
171 if direction != 0 {
172 EndpointDirection::DeviceToHost
173 } else {
174 EndpointDirection::HostToDevice
175 }
176 }
177
178 // Get endpoint number.
get_endpoint_number(&self) -> u8179 pub fn get_endpoint_number(&self) -> u8 {
180 self.bEndpointAddress & ENDPOINT_DESCRIPTOR_NUMBER_MASK
181 }
182
183 // Get endpoint type.
get_endpoint_type(&self) -> Option<EndpointType>184 pub fn get_endpoint_type(&self) -> Option<EndpointType> {
185 let ep_type = self.bmAttributes & ENDPOINT_DESCRIPTOR_ATTRIBUTES_TYPE_MASK;
186 match ep_type {
187 0 => Some(EndpointType::Control),
188 1 => Some(EndpointType::Isochronous),
189 2 => Some(EndpointType::Bulk),
190 3 => Some(EndpointType::Interrupt),
191 _ => None,
192 }
193 }
194 }
195
196 /// Offset of data phase transfer direction.
197 pub const DATA_PHASE_DIRECTION_OFFSET: u8 = 7;
198 /// Bit mask of data phase transfer direction.
199 pub const DATA_PHASE_DIRECTION: u8 = 1u8 << DATA_PHASE_DIRECTION_OFFSET;
200 // Types of data phase transfer directions.
201 #[derive(Copy, Clone, PartialEq, Eq)]
202 pub enum ControlRequestDataPhaseTransferDirection {
203 HostToDevice = 0,
204 DeviceToHost = 1,
205 }
206
207 /// Offset of control request type.
208 pub const CONTROL_REQUEST_TYPE_OFFSET: u8 = 5;
209 /// Bit mask of control request type.
210 pub const CONTROL_REQUEST_TYPE: u8 = 0b11 << CONTROL_REQUEST_TYPE_OFFSET;
211 /// Request types.
212 #[derive(PartialEq, Eq)]
213 pub enum ControlRequestType {
214 Standard = 0,
215 Class = 1,
216 Vendor = 2,
217 Reserved = 3,
218 }
219
220 /// Recipient type bits.
221 pub const REQUEST_RECIPIENT_TYPE: u8 = 0b1111;
222 /// Recipient type of control request.
223 #[derive(PartialEq, Eq)]
224 pub enum ControlRequestRecipient {
225 Device = 0,
226 Interface = 1,
227 Endpoint = 2,
228 Other = 3,
229 Reserved,
230 }
231
232 /// Standard request defined in usb spec.
233 #[derive(PartialEq, Eq)]
234 pub enum StandardControlRequest {
235 GetStatus = 0x00,
236 ClearFeature = 0x01,
237 SetFeature = 0x03,
238 SetAddress = 0x05,
239 GetDescriptor = 0x06,
240 SetDescriptor = 0x07,
241 GetConfiguration = 0x08,
242 SetConfiguration = 0x09,
243 GetInterface = 0x0a,
244 SetInterface = 0x11,
245 SynchFrame = 0x12,
246 }
247
248 /// RequestSetup is first part of control transfer buffer.
249 #[repr(C, packed)]
250 #[derive(Copy, Clone, Debug, FromBytes, AsBytes)]
251 pub struct UsbRequestSetup {
252 // USB Device Request. USB spec. rev. 2.0 9.3
253 pub request_type: u8, // bmRequestType
254 pub request: u8, // bRequest
255 pub value: u16, // wValue
256 pub index: u16, // wIndex
257 pub length: u16, // wLength
258 }
259
_assert_usb_request_setup()260 fn _assert_usb_request_setup() {
261 const_assert!(size_of::<UsbRequestSetup>() == 8);
262 }
263
264 impl UsbRequestSetup {
new( request_type: u8, request: u8, value: u16, index: u16, length: u16, ) -> UsbRequestSetup265 pub fn new(
266 request_type: u8,
267 request: u8,
268 value: u16,
269 index: u16,
270 length: u16,
271 ) -> UsbRequestSetup {
272 UsbRequestSetup {
273 request_type,
274 request,
275 value,
276 index,
277 length,
278 }
279 }
280
281 /// Get type of request.
get_type(&self) -> ControlRequestType282 pub fn get_type(&self) -> ControlRequestType {
283 let ty = (self.request_type & CONTROL_REQUEST_TYPE) >> CONTROL_REQUEST_TYPE_OFFSET;
284 match ty {
285 0 => ControlRequestType::Standard,
286 1 => ControlRequestType::Class,
287 2 => ControlRequestType::Vendor,
288 _ => ControlRequestType::Reserved,
289 }
290 }
291
292 /// Get request direction.
get_direction(&self) -> ControlRequestDataPhaseTransferDirection293 pub fn get_direction(&self) -> ControlRequestDataPhaseTransferDirection {
294 let dir = (self.request_type & DATA_PHASE_DIRECTION) >> DATA_PHASE_DIRECTION_OFFSET;
295 match dir {
296 0 => ControlRequestDataPhaseTransferDirection::HostToDevice,
297 _ => ControlRequestDataPhaseTransferDirection::DeviceToHost,
298 }
299 }
300
301 /// Get recipient of this control transfer.
get_recipient(&self) -> ControlRequestRecipient302 pub fn get_recipient(&self) -> ControlRequestRecipient {
303 let recipient = self.request_type & REQUEST_RECIPIENT_TYPE;
304 match recipient {
305 0 => ControlRequestRecipient::Device,
306 1 => ControlRequestRecipient::Interface,
307 2 => ControlRequestRecipient::Endpoint,
308 3 => ControlRequestRecipient::Other,
309 _ => ControlRequestRecipient::Reserved,
310 }
311 }
312
313 /// Return the type of standard control request.
get_standard_request(&self) -> Option<StandardControlRequest>314 pub fn get_standard_request(&self) -> Option<StandardControlRequest> {
315 if self.get_type() != ControlRequestType::Standard {
316 return None;
317 }
318 match self.request {
319 0x00 => Some(StandardControlRequest::GetStatus),
320 0x01 => Some(StandardControlRequest::ClearFeature),
321 0x03 => Some(StandardControlRequest::SetFeature),
322 0x05 => Some(StandardControlRequest::SetAddress),
323 0x06 => Some(StandardControlRequest::GetDescriptor),
324 0x07 => Some(StandardControlRequest::SetDescriptor),
325 0x08 => Some(StandardControlRequest::GetConfiguration),
326 0x09 => Some(StandardControlRequest::SetConfiguration),
327 0x0a => Some(StandardControlRequest::GetInterface),
328 0x11 => Some(StandardControlRequest::SetInterface),
329 0x12 => Some(StandardControlRequest::SynchFrame),
330 _ => None,
331 }
332 }
333 }
334
335 /// Construct a bmRequestType value for a control request.
control_request_type( type_: ControlRequestType, dir: ControlRequestDataPhaseTransferDirection, recipient: ControlRequestRecipient, ) -> u8336 pub fn control_request_type(
337 type_: ControlRequestType,
338 dir: ControlRequestDataPhaseTransferDirection,
339 recipient: ControlRequestRecipient,
340 ) -> u8 {
341 ((type_ as u8) << CONTROL_REQUEST_TYPE_OFFSET)
342 | ((dir as u8) << DATA_PHASE_DIRECTION_OFFSET)
343 | (recipient as u8)
344 }
345
346 /// USB device speed
347 pub enum DeviceSpeed {
348 Full,
349 Low,
350 High,
351 Super,
352 SuperPlus,
353 }
354
355 #[cfg(test)]
356 #[allow(clippy::unusual_byte_groupings)]
357 mod tests {
358 use super::*;
359
360 #[test]
control_request_types()361 fn control_request_types() {
362 assert_eq!(
363 control_request_type(
364 ControlRequestType::Standard,
365 ControlRequestDataPhaseTransferDirection::HostToDevice,
366 ControlRequestRecipient::Device
367 ),
368 0b0_00_00000
369 );
370 assert_eq!(
371 control_request_type(
372 ControlRequestType::Standard,
373 ControlRequestDataPhaseTransferDirection::DeviceToHost,
374 ControlRequestRecipient::Device
375 ),
376 0b1_00_00000
377 );
378 assert_eq!(
379 control_request_type(
380 ControlRequestType::Standard,
381 ControlRequestDataPhaseTransferDirection::HostToDevice,
382 ControlRequestRecipient::Interface
383 ),
384 0b0_00_00001
385 );
386 assert_eq!(
387 control_request_type(
388 ControlRequestType::Class,
389 ControlRequestDataPhaseTransferDirection::HostToDevice,
390 ControlRequestRecipient::Device
391 ),
392 0b0_01_00000
393 );
394 }
395 }
396