blob: 0bfbc203272f5d3a78ea5ca1d82d03ea9194ca67 [file] [log] [blame]
Patrick Georgid21f68b2008-09-02 16:06:22 +00001/*
2 * This file is part of the libpayload project.
3 *
4 * Copyright (C) 2008 coresystems GmbH
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#ifndef __USB_H
31#define __USB_H
32#include <libpayload.h>
Stefan Reinauer8992e532013-05-02 16:16:41 -070033#include <pci/pci.h>
Patrick Georgid21f68b2008-09-02 16:06:22 +000034
35typedef enum { host_to_device = 0, device_to_host = 1 } dev_req_dir;
36typedef enum { standard_type = 0, class_type = 1, vendor_type =
37 2, reserved_type = 3
38} dev_req_type;
39typedef enum { dev_recp = 0, iface_recp = 1, endp_recp = 2, other_recp = 3
40} dev_req_recp;
41
42typedef enum {
43 GET_STATUS = 0,
44 CLEAR_FEATURE = 1,
45 SET_FEATURE = 3,
46 SET_ADDRESS = 5,
47 GET_DESCRIPTOR = 6,
48 SET_DESCRIPTOR = 7,
49 GET_CONFIGURATION = 8,
50 SET_CONFIGURATION = 9,
51 GET_INTERFACE = 10,
52 SET_INTERFACE = 11,
53 SYNCH_FRAME = 12
54} bRequest_Codes;
55
56typedef enum {
57 ENDPOINT_HALT = 0,
58 DEVICE_REMOTE_WAKEUP = 1,
59 TEST_MODE = 2
60} feature_selectors;
61
62typedef struct {
63 union {
64 struct {
65 dev_req_recp req_recp:5;
66 dev_req_type req_type:2;
67 dev_req_dir data_dir:1;
68 } __attribute__ ((packed));
69 unsigned char bmRequestType;
70 } __attribute__ ((packed));
71 unsigned char bRequest;
72 unsigned short wValue;
73 unsigned short wIndex;
74 unsigned short wLength;
75} __attribute__ ((packed)) dev_req_t;
76
77struct usbdev_hc;
78typedef struct usbdev_hc hci_t;
79
80struct usbdev;
81typedef struct usbdev usbdev_t;
82
Patrick Georgid78691d2010-06-07 13:58:17 +000083typedef enum { SETUP, IN, OUT } direction_t;
Patrick Georgid21f68b2008-09-02 16:06:22 +000084typedef enum { CONTROL = 0, ISOCHRONOUS = 1, BULK = 2, INTERRUPT = 3
85} endpoint_type;
86
87typedef struct {
88 usbdev_t *dev;
89 int endpoint;
Patrick Georgid78691d2010-06-07 13:58:17 +000090 direction_t direction;
Patrick Georgid21f68b2008-09-02 16:06:22 +000091 int toggle;
92 int maxpacketsize;
93 endpoint_type type;
Nico Huberaee44fa2013-06-06 10:20:35 +020094 int interval; /* expressed as binary logarithm of the number
95 of microframes (i.e. t = 125us * 2^interval) */
Patrick Georgid21f68b2008-09-02 16:06:22 +000096} endpoint_t;
97
Nico Huber4fc7b6c2013-06-04 10:03:45 +020098enum { FULL_SPEED = 0, LOW_SPEED = 1, HIGH_SPEED = 2, SUPER_SPEED = 3 };
Patrick Georgid21f68b2008-09-02 16:06:22 +000099
100struct usbdev {
101 hci_t *controller;
102 endpoint_t endpoints[32];
103 int num_endp;
104 int address; // usb address
105 int hub; // hub, device is attached to
106 int port; // port where device is attached
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000107 int speed; // 1: lowspeed, 0: fullspeed, 2: highspeed
108 u32 quirks; // quirks field. got to love usb
Patrick Georgid21f68b2008-09-02 16:06:22 +0000109 void *data;
110 u8 *descriptor;
111 u8 *configuration;
112 void (*init) (usbdev_t *dev);
113 void (*destroy) (usbdev_t *dev);
114 void (*poll) (usbdev_t *dev);
115};
116
Anton Kochkov1c36ead2012-06-28 08:30:15 +0400117typedef enum { OHCI = 0, UHCI = 1, EHCI = 2, XHCI = 3} hc_type;
118
Patrick Georgid21f68b2008-09-02 16:06:22 +0000119struct usbdev_hc {
Patrick Georgi482af6d2013-05-24 15:48:56 +0200120 hci_t *next;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000121 u32 reg_base;
Patrick Georgifdb348a2013-12-21 11:41:22 +0100122 pcidev_t pcidev; // 0 if not used (eg on ARM)
Anton Kochkov1c36ead2012-06-28 08:30:15 +0400123 hc_type type;
Patrick Georgi4727c072008-10-16 19:20:51 +0000124 usbdev_t *devices[128]; // dev 0 is root hub, 127 is last addressable
Nico Hubera4827012012-11-12 15:12:35 +0100125
126 /* start(): Resume operation. */
Patrick Georgid21f68b2008-09-02 16:06:22 +0000127 void (*start) (hci_t *controller);
Nico Hubera4827012012-11-12 15:12:35 +0100128 /* stop(): Stop operation but keep controller initialized. */
Patrick Georgid21f68b2008-09-02 16:06:22 +0000129 void (*stop) (hci_t *controller);
Nico Hubera4827012012-11-12 15:12:35 +0100130 /* reset(): Perform a controller reset. The controller needs to
131 be (re)initialized afterwards to work (again). */
Patrick Georgid21f68b2008-09-02 16:06:22 +0000132 void (*reset) (hci_t *controller);
Nico Huber6e711c62012-11-12 16:20:32 +0100133 /* init(): Initialize a (previously reset) controller
134 to a working state. */
135 void (*init) (hci_t *controller);
Nico Hubera4827012012-11-12 15:12:35 +0100136 /* shutdown(): Stop operation, detach host controller and shutdown
137 this driver instance. After calling shutdown() any
138 other usage of this hci_t* is invalid. */
Patrick Georgid21f68b2008-09-02 16:06:22 +0000139 void (*shutdown) (hci_t *controller);
Nico Hubera4827012012-11-12 15:12:35 +0100140
Patrick Georgid21f68b2008-09-02 16:06:22 +0000141 int (*bulk) (endpoint_t *ep, int size, u8 *data, int finalize);
Patrick Georgid78691d2010-06-07 13:58:17 +0000142 int (*control) (usbdev_t *dev, direction_t pid, int dr_length,
Patrick Georgid21f68b2008-09-02 16:06:22 +0000143 void *devreq, int data_length, u8 *data);
Patrick Georgi4727c072008-10-16 19:20:51 +0000144 void* (*create_intr_queue) (endpoint_t *ep, int reqsize, int reqcount, int reqtiming);
145 void (*destroy_intr_queue) (endpoint_t *ep, void *queue);
146 u8* (*poll_intr_queue) (void *queue);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000147 void *instance;
Patrick Georgi482af6d2013-05-24 15:48:56 +0200148
149 /* set_address(): Tell the usb device its address and
150 return it. xHCI controllers want to
151 do this by themself. Also, the usbdev
152 structure has to be allocated and
153 initialized. */
154 int (*set_address) (hci_t *controller, int speed, int hubport, int hubaddr);
155 /* finish_device_config(): Another hook for xHCI,
156 returns 0 on success. */
157 int (*finish_device_config) (usbdev_t *dev);
158 /* destroy_device(): Finally, destroy all structures that
159 were allocated during set_address()
160 and finish_device_config(). */
161 void (*destroy_device) (hci_t *controller, int devaddr);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000162};
163
164typedef struct {
165 unsigned char bDescLength;
166 unsigned char bDescriptorType;
167 unsigned char bNbrPorts;
168 union {
169 struct {
170 unsigned long logicalPowerSwitchingMode:2;
171 unsigned long isCompoundDevice:1;
172 unsigned long overcurrentProtectionMode:2;
173 unsigned long ttThinkTime:2;
174 unsigned long arePortIndicatorsSupported:1;
175 unsigned long:8;
176 } __attribute__ ((packed));
177 unsigned short wHubCharacteristics;
178 } __attribute__ ((packed));
179 unsigned char bPowerOn2PwrGood;
180 unsigned char bHubContrCurrent;
181 char DeviceRemovable[];
182} __attribute__ ((packed)) hub_descriptor_t;
183
184typedef struct {
185 unsigned char bLength;
186 unsigned char bDescriptorType;
187 unsigned short bcdUSB;
188 unsigned char bDeviceClass;
189 unsigned char bDeviceSubClass;
190 unsigned char bDeviceProtocol;
191 unsigned char bMaxPacketSize0;
192 unsigned short idVendor;
193 unsigned short idProduct;
194 unsigned short bcdDevice;
195 unsigned char iManufacturer;
196 unsigned char iProduct;
197 unsigned char iSerialNumber;
198 unsigned char bNumConfigurations;
199} __attribute__ ((packed)) device_descriptor_t;
200
201typedef struct {
202 unsigned char bLength;
203 unsigned char bDescriptorType;
204 unsigned short wTotalLength;
205 unsigned char bNumInterfaces;
206 unsigned char bConfigurationValue;
207 unsigned char iConfiguration;
208 unsigned char bmAttributes;
209 unsigned char bMaxPower;
210} __attribute__ ((packed)) configuration_descriptor_t;
211
212typedef struct {
213 unsigned char bLength;
214 unsigned char bDescriptorType;
215 unsigned char bInterfaceNumber;
216 unsigned char bAlternateSetting;
217 unsigned char bNumEndpoints;
218 unsigned char bInterfaceClass;
219 unsigned char bInterfaceSubClass;
220 unsigned char bInterfaceProtocol;
221 unsigned char iInterface;
222} __attribute__ ((packed)) interface_descriptor_t;
223
224typedef struct {
225 unsigned char bLength;
226 unsigned char bDescriptorType;
227 unsigned char bEndpointAddress;
228 unsigned char bmAttributes;
229 unsigned short wMaxPacketSize;
230 unsigned char bInterval;
231} __attribute__ ((packed)) endpoint_descriptor_t;
232
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000233typedef struct {
234 unsigned char bLength;
235 unsigned char bDescriptorType;
236 unsigned short bcdHID;
237 unsigned char bCountryCode;
238 unsigned char bNumDescriptors;
239 unsigned char bReportDescriptorType;
240 unsigned short wReportDescriptorLength;
241} __attribute__ ((packed)) hid_descriptor_t;
242
Patrick Georgid21f68b2008-09-02 16:06:22 +0000243hci_t *new_controller (void);
244void detach_controller (hci_t *controller);
245void usb_poll (void);
246void init_device_entry (hci_t *controller, int num);
247
248void set_feature (usbdev_t *dev, int endp, int feature, int rtype);
249void get_status (usbdev_t *dev, int endp, int rtype, int len, void *data);
Nico Huberba22e4c2012-11-23 11:34:20 +0100250void set_configuration (usbdev_t *dev);
Nico Huber79e1f2f2012-06-01 09:50:11 +0200251int clear_feature (usbdev_t *dev, int endp, int feature, int rtype);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000252int clear_stall (endpoint_t *ep);
253
254void usb_nop_init (usbdev_t *dev);
255void usb_hub_init (usbdev_t *dev);
256void usb_hid_init (usbdev_t *dev);
257void usb_msc_init (usbdev_t *dev);
Gabe Blackdc9e77f2013-02-01 20:19:27 -0800258void usb_generic_init (usbdev_t *dev);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000259
Patrick Georgid21f68b2008-09-02 16:06:22 +0000260u8 *get_descriptor (usbdev_t *dev, unsigned char bmRequestType,
261 int descType, int descIdx, int langID);
262
263static inline unsigned char
264gen_bmRequestType (dev_req_dir dir, dev_req_type type, dev_req_recp recp)
265{
266 return (dir << 7) | (type << 5) | recp;
267}
268
Patrick Georgi482af6d2013-05-24 15:48:56 +0200269/* default "set address" handler */
270int generic_set_address (hci_t *controller, int speed, int hubport, int hubaddr);
271
Patrick Georgi4727c072008-10-16 19:20:51 +0000272void usb_detach_device(hci_t *controller, int devno);
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000273int usb_attach_device(hci_t *controller, int hubaddress, int port, int speed);
274
275u32 usb_quirk_check(u16 vendor, u16 device);
276int usb_interface_check(u16 vendor, u16 device);
277
278#define USB_QUIRK_MSC_FORCE_PROTO_SCSI (1 << 0)
279#define USB_QUIRK_MSC_FORCE_PROTO_ATAPI (1 << 1)
280#define USB_QUIRK_MSC_FORCE_PROTO_UFI (1 << 2)
281#define USB_QUIRK_MSC_FORCE_PROTO_RBC (1 << 3)
282#define USB_QUIRK_MSC_FORCE_TRANS_BBB (1 << 4)
283#define USB_QUIRK_MSC_FORCE_TRANS_CBI (1 << 5)
284#define USB_QUIRK_MSC_FORCE_TRANS_CBI_I (1 << 6)
285#define USB_QUIRK_MSC_NO_TEST_UNIT_READY (1 << 7)
286#define USB_QUIRK_MSC_SHORT_INQUIRY (1 << 8)
287#define USB_QUIRK_TEST (1 << 31)
288#define USB_QUIRK_NONE 0
289
Gabe Black93ded592012-11-01 15:44:10 -0700290static inline void usb_debug(const char *fmt, ...)
291{
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000292#ifdef USB_DEBUG
Gabe Black93ded592012-11-01 15:44:10 -0700293 va_list ap;
294 va_start(ap, fmt);
295 vprintf(fmt, ap);
296 va_end(ap);
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000297#endif
Gabe Black93ded592012-11-01 15:44:10 -0700298}
Stefan Reinauer5fe6e232009-07-31 11:39:55 +0000299
Gabe Blackdc9e77f2013-02-01 20:19:27 -0800300/**
301 * To be implemented by libpayload-client. It's called by the USB stack
302 * when a new USB device is found which isn't claimed by a built in driver,
303 * so the client has the chance to know about it.
304 *
305 * @param dev descriptor for the USB device
306 */
307void __attribute__((weak)) usb_generic_create (usbdev_t *dev);
308
309/**
310 * To be implemented by libpayload-client. It's called by the USB stack
311 * when it finds out that a USB device is removed which wasn't claimed by a
312 * built in driver.
313 *
314 * @param dev descriptor for the USB device
315 */
316void __attribute__((weak)) usb_generic_remove (usbdev_t *dev);
317
Patrick Georgid21f68b2008-09-02 16:06:22 +0000318#endif