3 * Copyright (C) 2008 coresystems GmbH
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 #include <libpayload.h>
35 typedef enum { host_to_device
= 0, device_to_host
= 1 } dev_req_dir
;
36 typedef enum { standard_type
= 0, class_type
= 1, vendor_type
=
39 typedef enum { dev_recp
= 0, iface_recp
= 1, endp_recp
= 2, other_recp
= 3
57 GET_CONFIGURATION
= 8,
58 SET_CONFIGURATION
= 9,
66 DEVICE_REMOTE_WAKEUP
= 1,
70 /* SetAddress() recovery interval (USB 2.0 specification 9.2.6.3 */
71 #define SET_ADDRESS_MDELAY 2
74 * USB sets an upper limit of 5 seconds for any transfer to be completed.
76 * Data originally from EHCI driver:
77 * Tested with some USB2.0 flash sticks:
78 * TUR turn around took about 2.2s for the slowest (13fe:3800), maximum
79 * of 250ms for the others.
81 * SET ADDRESS on xHCI controllers.
82 * The USB specification indicates that devices must complete processing
83 * of a SET ADDRESS request within 50 ms. However, some hubs were found
84 * to take more than 100 ms to complete a SET ADDRESS request on a
87 #define USB_MAX_PROCESSING_TIME_US (5 * 1000 * 1000)
89 #define USB_FULL_LOW_SPEED_FRAME_US 1000
92 unsigned char bDescLength
;
93 unsigned char bDescriptorType
;
94 unsigned char bNbrPorts
;
97 unsigned long logicalPowerSwitchingMode
:2;
98 unsigned long isCompoundDevice
:1;
99 unsigned long overcurrentProtectionMode
:2;
100 unsigned long ttThinkTime
:2;
101 unsigned long arePortIndicatorsSupported
:1;
104 unsigned short wHubCharacteristics
;
106 unsigned char bPowerOn2PwrGood
;
107 unsigned char bHubContrCurrent
;
108 char DeviceRemovable
[];
109 } __packed hub_descriptor_t
;
112 unsigned char bLength
;
113 unsigned char bDescriptorType
;
114 unsigned short bcdUSB
;
115 unsigned char bDeviceClass
;
116 unsigned char bDeviceSubClass
;
117 unsigned char bDeviceProtocol
;
118 unsigned char bMaxPacketSize0
;
119 unsigned short idVendor
;
120 unsigned short idProduct
;
121 unsigned short bcdDevice
;
122 unsigned char iManufacturer
;
123 unsigned char iProduct
;
124 unsigned char iSerialNumber
;
125 unsigned char bNumConfigurations
;
126 } __packed device_descriptor_t
;
129 unsigned char bLength
;
130 unsigned char bDescriptorType
;
131 unsigned short wTotalLength
;
132 unsigned char bNumInterfaces
;
133 unsigned char bConfigurationValue
;
134 unsigned char iConfiguration
;
135 unsigned char bmAttributes
;
136 unsigned char bMaxPower
;
137 } __packed configuration_descriptor_t
;
140 unsigned char bLength
;
141 unsigned char bDescriptorType
;
142 unsigned char bInterfaceNumber
;
143 unsigned char bAlternateSetting
;
144 unsigned char bNumEndpoints
;
145 unsigned char bInterfaceClass
;
146 unsigned char bInterfaceSubClass
;
147 unsigned char bInterfaceProtocol
;
148 unsigned char iInterface
;
149 } __packed interface_descriptor_t
;
152 unsigned char bLength
;
153 unsigned char bDescriptorType
;
154 unsigned char bEndpointAddress
;
155 unsigned char bmAttributes
;
156 unsigned short wMaxPacketSize
;
157 unsigned char bInterval
;
158 } __packed endpoint_descriptor_t
;
161 unsigned char bLength
;
162 unsigned char bDescriptorType
;
163 unsigned short bcdHID
;
164 unsigned char bCountryCode
;
165 unsigned char bNumDescriptors
;
166 unsigned char bReportDescriptorType
;
167 unsigned short wReportDescriptorLength
;
168 } __packed hid_descriptor_t
;
173 dev_req_recp req_recp
:5;
174 dev_req_type req_type
:2;
175 dev_req_dir data_dir
:1;
177 unsigned char bmRequestType
;
179 unsigned char bRequest
;
180 unsigned short wValue
;
181 unsigned short wIndex
;
182 unsigned short wLength
;
183 } __packed dev_req_t
;
186 typedef struct usbdev_hc hci_t
;
189 typedef struct usbdev usbdev_t
;
191 typedef enum { SETUP
, IN
, OUT
} direction_t
;
192 typedef enum { CONTROL
= 0, ISOCHRONOUS
= 1, BULK
= 2, INTERRUPT
= 3
198 direction_t direction
;
202 int interval
; /* expressed as binary logarithm of the number
203 of microframes (i.e. t = 125us * 2^interval) */
212 SUPER_SPEED_PLUS
= 4,
217 endpoint_t endpoints
[32];
219 int address
; // USB address
220 int hub
; // hub, device is attached to
221 int port
; // port where device is attached
223 u32 quirks
; // quirks field. got to love usb
225 device_descriptor_t
*descriptor
;
226 configuration_descriptor_t
*configuration
;
227 void (*init
) (usbdev_t
*dev
);
228 void (*destroy
) (usbdev_t
*dev
);
229 void (*poll
) (usbdev_t
*dev
);
232 typedef enum { OHCI
= 0, UHCI
= 1, EHCI
= 2, XHCI
= 3, DWC2
= 4} hc_type
;
237 pcidev_t pcidev
; // 0 if not used (eg on ARM)
240 usbdev_t
*devices
[128]; // dev 0 is root hub, 127 is last addressable
242 /* start(): Resume operation. */
243 void (*start
) (hci_t
*controller
);
244 /* stop(): Stop operation but keep controller initialized. */
245 void (*stop
) (hci_t
*controller
);
246 /* reset(): Perform a controller reset. The controller needs to
247 be (re)initialized afterwards to work (again). */
248 void (*reset
) (hci_t
*controller
);
249 /* init(): Initialize a (previously reset) controller
250 to a working state. */
251 void (*init
) (hci_t
*controller
);
252 /* shutdown(): Stop operation, detach host controller and shutdown
253 this driver instance. After calling shutdown() any
254 other usage of this hci_t* is invalid. */
255 void (*shutdown
) (hci_t
*controller
);
257 int (*bulk
) (endpoint_t
*ep
, int size
, u8
*data
, int finalize
);
258 int (*control
) (usbdev_t
*dev
, direction_t pid
, int dr_length
,
259 void *devreq
, int data_length
, u8
*data
);
260 void* (*create_intr_queue
) (endpoint_t
*ep
, int reqsize
, int reqcount
, int reqtiming
);
261 void (*destroy_intr_queue
) (endpoint_t
*ep
, void *queue
);
262 u8
* (*poll_intr_queue
) (void *queue
);
265 /* set_address(): Tell the USB device its address (xHCI
266 controllers want to do this by
267 themselves). Also, allocate the usbdev
268 structure, initialize enpoint 0
269 (including MPS) and return it. */
270 usbdev_t
*(*set_address
) (hci_t
*controller
, usb_speed speed
,
271 int hubport
, int hubaddr
);
272 /* finish_device_config(): Another hook for xHCI,
273 returns 0 on success. */
274 int (*finish_device_config
) (usbdev_t
*dev
);
275 /* destroy_device(): Finally, destroy all structures that
276 were allocated during set_address()
277 and finish_device_config(). */
278 void (*destroy_device
) (hci_t
*controller
, int devaddr
);
281 hci_t
*usb_add_mmio_hc(hc_type type
, void *bar
);
282 hci_t
*new_controller (void);
283 void detach_controller (hci_t
*controller
);
284 void usb_poll (void);
285 usbdev_t
*init_device_entry (hci_t
*controller
, int num
);
287 int usb_decode_mps0 (usb_speed speed
, u8 bMaxPacketSize0
);
288 int speed_to_default_mps(usb_speed speed
);
289 int set_feature (usbdev_t
*dev
, int endp
, int feature
, int rtype
);
290 int get_status (usbdev_t
*dev
, int endp
, int rtype
, int len
, void *data
);
291 int get_descriptor (usbdev_t
*dev
, int rtype
, int descType
, int descIdx
,
292 void *data
, size_t len
);
293 int set_configuration (usbdev_t
*dev
);
294 int clear_feature (usbdev_t
*dev
, int endp
, int feature
, int rtype
);
295 int clear_stall (endpoint_t
*ep
);
296 _Bool
is_usb_speed_ss(usb_speed speed
);
298 void usb_nop_init (usbdev_t
*dev
);
299 void usb_hub_init (usbdev_t
*dev
);
300 void usb_hid_init (usbdev_t
*dev
);
301 void usb_msc_init (usbdev_t
*dev
);
302 void usb_generic_init (usbdev_t
*dev
);
304 int closest_usb2_hub(const usbdev_t
*dev
, int *const addr
, int *const port
);
306 static inline unsigned char
307 gen_bmRequestType (dev_req_dir dir
, dev_req_type type
, dev_req_recp recp
)
309 return (dir
<< 7) | (type
<< 5) | recp
;
312 /* default "set address" handler */
313 usbdev_t
*generic_set_address (hci_t
*controller
, usb_speed speed
,
314 int hubport
, int hubaddr
);
316 void usb_detach_device(hci_t
*controller
, int devno
);
317 int usb_attach_device(hci_t
*controller
, int hubaddress
, int port
,
320 u32
pci_quirk_check(pcidev_t controller
);
321 u32
usb_quirk_check(u16 vendor
, u16 device
);
322 int usb_interface_check(u16 vendor
, u16 device
);
324 #define USB_QUIRK_MSC_FORCE_PROTO_SCSI (1 << 0)
325 #define USB_QUIRK_MSC_FORCE_PROTO_ATAPI (1 << 1)
326 #define USB_QUIRK_MSC_FORCE_PROTO_UFI (1 << 2)
327 #define USB_QUIRK_MSC_FORCE_PROTO_RBC (1 << 3)
328 #define USB_QUIRK_MSC_FORCE_TRANS_BBB (1 << 4)
329 #define USB_QUIRK_MSC_FORCE_TRANS_CBI (1 << 5)
330 #define USB_QUIRK_MSC_FORCE_TRANS_CBI_I (1 << 6)
331 #define USB_QUIRK_MSC_NO_TEST_UNIT_READY (1 << 7)
332 #define USB_QUIRK_MSC_SHORT_INQUIRY (1 << 8)
333 #define USB_QUIRK_HUB_NO_USBSTS_PCD (1 << 9)
334 #define USB_QUIRK_TEST (1 << 31)
335 #define USB_QUIRK_NONE 0
337 static inline void __attribute__((format(printf
, 1, 2))) usb_debug(const char *fmt
, ...)
348 * To be implemented by libpayload-client. It's called by the USB
349 * stack just before iterating over known devices to poll them for
352 void __attribute__((weak
)) usb_poll_prepare (void);
355 * To be implemented by libpayload-client. It's called by the USB stack
356 * when a new USB device is found which isn't claimed by a built in driver,
357 * so the client has the chance to know about it.
359 * @param dev descriptor for the USB device
361 void __attribute__((weak
)) usb_generic_create (usbdev_t
*dev
);
364 * To be implemented by libpayload-client. It's called by the USB stack
365 * when it finds out that a USB device is removed which wasn't claimed by a
368 * @param dev descriptor for the USB device
370 void __attribute__((weak
)) usb_generic_remove (usbdev_t
*dev
);