1 // Copyright 2018 The Chromium OS Authors. All rights reserved.
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 assertions::const_assert;
6 use data_model::DataInit;
7
8 use std::mem::size_of;
9
10 use crate::bindings;
11
12 /// Speed of usb device. See usb spec for more details.
13 #[derive(Debug)]
14 pub enum Speed {
15 /// The OS doesn't report or know the device speed.
16 Unknown,
17 /// The device is operating at low speed (1.5MBit/s).
18 Low,
19 /// The device is operating at full speed (12MBit/s).
20 Full,
21 /// The device is operating at high speed (480MBit/s).
22 High,
23 /// The device is operating at super speed (5000MBit/s).
24 Super,
25 }
26
27 impl From<bindings::libusb_speed> for Speed {
from(speed: bindings::libusb_speed) -> Speed28 fn from(speed: bindings::libusb_speed) -> Speed {
29 match speed {
30 bindings::LIBUSB_SPEED_LOW => Speed::Low,
31 bindings::LIBUSB_SPEED_FULL => Speed::Full,
32 bindings::LIBUSB_SPEED_HIGH => Speed::High,
33 bindings::LIBUSB_SPEED_SUPER => Speed::Super,
34 _ => Speed::Unknown,
35 }
36 }
37 }
38
39 /// Endpoint types.
40 #[derive(PartialEq)]
41 pub enum EndpointType {
42 Control,
43 Isochronous,
44 Bulk,
45 Interrupt,
46 }
47
48 /// Endpoint Directions.
49 #[derive(PartialEq, Clone, Copy)]
50 pub enum EndpointDirection {
51 HostToDevice = 0,
52 DeviceToHost = 1,
53 }
54 /// Endpoint direction offset.
55 pub const ENDPOINT_DIRECTION_OFFSET: u8 = 7;
56
57 /// Offset of data phase transfer direction.
58 pub const DATA_PHASE_DIRECTION_OFFSET: u8 = 7;
59 /// Bit mask of data phase transfer direction.
60 pub const DATA_PHASE_DIRECTION: u8 = 1u8 << DATA_PHASE_DIRECTION_OFFSET;
61 // Types of data phase transfer directions.
62 #[derive(Copy, Clone, PartialEq)]
63 pub enum ControlRequestDataPhaseTransferDirection {
64 HostToDevice = 0,
65 DeviceToHost = 1,
66 }
67
68 /// Offset of control request type.
69 pub const CONTROL_REQUEST_TYPE_OFFSET: u8 = 5;
70 /// Bit mask of control request type.
71 pub const CONTROL_REQUEST_TYPE: u8 = 0b11 << CONTROL_REQUEST_TYPE_OFFSET;
72 /// Request types.
73 #[derive(PartialEq)]
74 pub enum ControlRequestType {
75 Standard = 0,
76 Class = 1,
77 Vendor = 2,
78 Reserved = 3,
79 }
80
81 /// Recipient type bits.
82 pub const REQUEST_RECIPIENT_TYPE: u8 = 0b1111;
83 /// Recipient type of control request.
84 #[derive(PartialEq)]
85 pub enum ControlRequestRecipient {
86 Device = 0,
87 Interface = 1,
88 Endpoint = 2,
89 Other = 3,
90 Reserved,
91 }
92
93 /// Standard request defined in usb spec.
94 #[derive(PartialEq)]
95 pub enum StandardControlRequest {
96 GetStatus = 0x00,
97 ClearFeature = 0x01,
98 SetFeature = 0x03,
99 SetAddress = 0x05,
100 GetDescriptor = 0x06,
101 SetDescriptor = 0x07,
102 GetConfiguration = 0x08,
103 SetConfiguration = 0x09,
104 GetInterface = 0x0a,
105 SetInterface = 0x11,
106 SynchFrame = 0x12,
107 }
108
109 /// RequestSetup is first part of control transfer buffer.
110 #[repr(C, packed)]
111 #[derive(Copy, Clone, Debug)]
112 pub struct UsbRequestSetup {
113 // USB Device Request. USB spec. rev. 2.0 9.3
114 pub request_type: u8, // bmRequestType
115 pub request: u8, // bRequest
116 pub value: u16, // wValue
117 pub index: u16, // wIndex
118 pub length: u16, // wLength
119 }
120
_assert()121 fn _assert() {
122 const_assert!(size_of::<UsbRequestSetup>() == 8);
123 }
124
125 unsafe impl DataInit for UsbRequestSetup {}
126
127 impl UsbRequestSetup {
new( request_type: u8, request: u8, value: u16, index: u16, length: u16, ) -> UsbRequestSetup128 pub fn new(
129 request_type: u8,
130 request: u8,
131 value: u16,
132 index: u16,
133 length: u16,
134 ) -> UsbRequestSetup {
135 UsbRequestSetup {
136 request_type,
137 request,
138 value,
139 index,
140 length,
141 }
142 }
143
144 /// Get type of request.
get_type(&self) -> ControlRequestType145 pub fn get_type(&self) -> ControlRequestType {
146 let ty = (self.request_type & CONTROL_REQUEST_TYPE) >> CONTROL_REQUEST_TYPE_OFFSET;
147 match ty {
148 0 => ControlRequestType::Standard,
149 1 => ControlRequestType::Class,
150 2 => ControlRequestType::Vendor,
151 _ => ControlRequestType::Reserved,
152 }
153 }
154
155 /// Get request direction.
get_direction(&self) -> ControlRequestDataPhaseTransferDirection156 pub fn get_direction(&self) -> ControlRequestDataPhaseTransferDirection {
157 let dir = (self.request_type & DATA_PHASE_DIRECTION) >> DATA_PHASE_DIRECTION_OFFSET;
158 match dir {
159 0 => ControlRequestDataPhaseTransferDirection::HostToDevice,
160 _ => ControlRequestDataPhaseTransferDirection::DeviceToHost,
161 }
162 }
163
164 /// Get recipient of this control transfer.
get_recipient(&self) -> ControlRequestRecipient165 pub fn get_recipient(&self) -> ControlRequestRecipient {
166 let recipient = self.request_type & REQUEST_RECIPIENT_TYPE;
167 match recipient {
168 0 => ControlRequestRecipient::Device,
169 1 => ControlRequestRecipient::Interface,
170 2 => ControlRequestRecipient::Endpoint,
171 3 => ControlRequestRecipient::Other,
172 _ => ControlRequestRecipient::Reserved,
173 }
174 }
175
176 /// Return the type of standard control request.
get_standard_request(&self) -> Option<StandardControlRequest>177 pub fn get_standard_request(&self) -> Option<StandardControlRequest> {
178 if self.get_type() != ControlRequestType::Standard {
179 return None;
180 }
181 match self.request {
182 0x00 => Some(StandardControlRequest::GetStatus),
183 0x01 => Some(StandardControlRequest::ClearFeature),
184 0x03 => Some(StandardControlRequest::SetFeature),
185 0x05 => Some(StandardControlRequest::SetAddress),
186 0x06 => Some(StandardControlRequest::GetDescriptor),
187 0x07 => Some(StandardControlRequest::SetDescriptor),
188 0x08 => Some(StandardControlRequest::GetConfiguration),
189 0x09 => Some(StandardControlRequest::SetConfiguration),
190 0x0a => Some(StandardControlRequest::GetInterface),
191 0x11 => Some(StandardControlRequest::SetInterface),
192 0x12 => Some(StandardControlRequest::SynchFrame),
193 _ => None,
194 }
195 }
196 }
197