blob: fc3ce5a50fbad9f9497211ab07ae877a309fc134 [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>
33#include <pci.h>
34
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;
94} endpoint_t;
95
Nico Huber4fc7b6c2013-06-04 10:03:45 +020096enum { FULL_SPEED = 0, LOW_SPEED = 1, HIGH_SPEED = 2, SUPER_SPEED = 3 };
Patrick Georgid21f68b2008-09-02 16:06:22 +000097
98struct usbdev {
99 hci_t *controller;
100 endpoint_t endpoints[32];
101 int num_endp;
102 int address; // usb address
103 int hub; // hub, device is attached to
104 int port; // port where device is attached
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000105 int speed; // 1: lowspeed, 0: fullspeed, 2: highspeed
106 u32 quirks; // quirks field. got to love usb
Patrick Georgid21f68b2008-09-02 16:06:22 +0000107 void *data;
108 u8 *descriptor;
109 u8 *configuration;
110 void (*init) (usbdev_t *dev);
111 void (*destroy) (usbdev_t *dev);
112 void (*poll) (usbdev_t *dev);
113};
114
Anton Kochkov1c36ead2012-06-28 08:30:15 +0400115typedef enum { OHCI = 0, UHCI = 1, EHCI = 2, XHCI = 3} hc_type;
116
Patrick Georgid21f68b2008-09-02 16:06:22 +0000117struct usbdev_hc {
118 struct usbdev_hc *next;
119 pcidev_t bus_address;
120 u32 reg_base;
Anton Kochkov1c36ead2012-06-28 08:30:15 +0400121 hc_type type;
Patrick Georgi4727c072008-10-16 19:20:51 +0000122 usbdev_t *devices[128]; // dev 0 is root hub, 127 is last addressable
Nico Hubera4827012012-11-12 15:12:35 +0100123
124 /* start(): Resume operation. */
Patrick Georgid21f68b2008-09-02 16:06:22 +0000125 void (*start) (hci_t *controller);
Nico Hubera4827012012-11-12 15:12:35 +0100126 /* stop(): Stop operation but keep controller initialized. */
Patrick Georgid21f68b2008-09-02 16:06:22 +0000127 void (*stop) (hci_t *controller);
Nico Hubera4827012012-11-12 15:12:35 +0100128 /* reset(): Perform a controller reset. The controller needs to
129 be (re)initialized afterwards to work (again). */
Patrick Georgid21f68b2008-09-02 16:06:22 +0000130 void (*reset) (hci_t *controller);
Nico Huber6e711c62012-11-12 16:20:32 +0100131 /* init(): Initialize a (previously reset) controller
132 to a working state. */
133 void (*init) (hci_t *controller);
Nico Hubera4827012012-11-12 15:12:35 +0100134 /* shutdown(): Stop operation, detach host controller and shutdown
135 this driver instance. After calling shutdown() any
136 other usage of this hci_t* is invalid. */
Patrick Georgid21f68b2008-09-02 16:06:22 +0000137 void (*shutdown) (hci_t *controller);
Nico Hubera4827012012-11-12 15:12:35 +0100138
Patrick Georgid21f68b2008-09-02 16:06:22 +0000139 int (*bulk) (endpoint_t *ep, int size, u8 *data, int finalize);
Patrick Georgid78691d2010-06-07 13:58:17 +0000140 int (*control) (usbdev_t *dev, direction_t pid, int dr_length,
Patrick Georgid21f68b2008-09-02 16:06:22 +0000141 void *devreq, int data_length, u8 *data);
Patrick Georgi4727c072008-10-16 19:20:51 +0000142 void* (*create_intr_queue) (endpoint_t *ep, int reqsize, int reqcount, int reqtiming);
143 void (*destroy_intr_queue) (endpoint_t *ep, void *queue);
144 u8* (*poll_intr_queue) (void *queue);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000145 void *instance;
146};
147
148typedef struct {
149 unsigned char bDescLength;
150 unsigned char bDescriptorType;
151 unsigned char bNbrPorts;
152 union {
153 struct {
154 unsigned long logicalPowerSwitchingMode:2;
155 unsigned long isCompoundDevice:1;
156 unsigned long overcurrentProtectionMode:2;
157 unsigned long ttThinkTime:2;
158 unsigned long arePortIndicatorsSupported:1;
159 unsigned long:8;
160 } __attribute__ ((packed));
161 unsigned short wHubCharacteristics;
162 } __attribute__ ((packed));
163 unsigned char bPowerOn2PwrGood;
164 unsigned char bHubContrCurrent;
165 char DeviceRemovable[];
166} __attribute__ ((packed)) hub_descriptor_t;
167
168typedef struct {
169 unsigned char bLength;
170 unsigned char bDescriptorType;
171 unsigned short bcdUSB;
172 unsigned char bDeviceClass;
173 unsigned char bDeviceSubClass;
174 unsigned char bDeviceProtocol;
175 unsigned char bMaxPacketSize0;
176 unsigned short idVendor;
177 unsigned short idProduct;
178 unsigned short bcdDevice;
179 unsigned char iManufacturer;
180 unsigned char iProduct;
181 unsigned char iSerialNumber;
182 unsigned char bNumConfigurations;
183} __attribute__ ((packed)) device_descriptor_t;
184
185typedef struct {
186 unsigned char bLength;
187 unsigned char bDescriptorType;
188 unsigned short wTotalLength;
189 unsigned char bNumInterfaces;
190 unsigned char bConfigurationValue;
191 unsigned char iConfiguration;
192 unsigned char bmAttributes;
193 unsigned char bMaxPower;
194} __attribute__ ((packed)) configuration_descriptor_t;
195
196typedef struct {
197 unsigned char bLength;
198 unsigned char bDescriptorType;
199 unsigned char bInterfaceNumber;
200 unsigned char bAlternateSetting;
201 unsigned char bNumEndpoints;
202 unsigned char bInterfaceClass;
203 unsigned char bInterfaceSubClass;
204 unsigned char bInterfaceProtocol;
205 unsigned char iInterface;
206} __attribute__ ((packed)) interface_descriptor_t;
207
208typedef struct {
209 unsigned char bLength;
210 unsigned char bDescriptorType;
211 unsigned char bEndpointAddress;
212 unsigned char bmAttributes;
213 unsigned short wMaxPacketSize;
214 unsigned char bInterval;
215} __attribute__ ((packed)) endpoint_descriptor_t;
216
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000217typedef struct {
218 unsigned char bLength;
219 unsigned char bDescriptorType;
220 unsigned short bcdHID;
221 unsigned char bCountryCode;
222 unsigned char bNumDescriptors;
223 unsigned char bReportDescriptorType;
224 unsigned short wReportDescriptorLength;
225} __attribute__ ((packed)) hid_descriptor_t;
226
Patrick Georgid21f68b2008-09-02 16:06:22 +0000227hci_t *new_controller (void);
228void detach_controller (hci_t *controller);
229void usb_poll (void);
230void init_device_entry (hci_t *controller, int num);
231
232void set_feature (usbdev_t *dev, int endp, int feature, int rtype);
233void get_status (usbdev_t *dev, int endp, int rtype, int len, void *data);
Nico Huberba22e4c2012-11-23 11:34:20 +0100234void set_configuration (usbdev_t *dev);
Nico Huber79e1f2f2012-06-01 09:50:11 +0200235int clear_feature (usbdev_t *dev, int endp, int feature, int rtype);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000236int clear_stall (endpoint_t *ep);
237
238void usb_nop_init (usbdev_t *dev);
239void usb_hub_init (usbdev_t *dev);
240void usb_hid_init (usbdev_t *dev);
241void usb_msc_init (usbdev_t *dev);
Gabe Blackdc9e77f2013-02-01 20:19:27 -0800242void usb_generic_init (usbdev_t *dev);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000243
Patrick Georgid21f68b2008-09-02 16:06:22 +0000244u8 *get_descriptor (usbdev_t *dev, unsigned char bmRequestType,
245 int descType, int descIdx, int langID);
246
247static inline unsigned char
248gen_bmRequestType (dev_req_dir dir, dev_req_type type, dev_req_recp recp)
249{
250 return (dir << 7) | (type << 5) | recp;
251}
252
Patrick Georgi4727c072008-10-16 19:20:51 +0000253void usb_detach_device(hci_t *controller, int devno);
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000254int usb_attach_device(hci_t *controller, int hubaddress, int port, int speed);
255
256u32 usb_quirk_check(u16 vendor, u16 device);
257int usb_interface_check(u16 vendor, u16 device);
258
259#define USB_QUIRK_MSC_FORCE_PROTO_SCSI (1 << 0)
260#define USB_QUIRK_MSC_FORCE_PROTO_ATAPI (1 << 1)
261#define USB_QUIRK_MSC_FORCE_PROTO_UFI (1 << 2)
262#define USB_QUIRK_MSC_FORCE_PROTO_RBC (1 << 3)
263#define USB_QUIRK_MSC_FORCE_TRANS_BBB (1 << 4)
264#define USB_QUIRK_MSC_FORCE_TRANS_CBI (1 << 5)
265#define USB_QUIRK_MSC_FORCE_TRANS_CBI_I (1 << 6)
266#define USB_QUIRK_MSC_NO_TEST_UNIT_READY (1 << 7)
267#define USB_QUIRK_MSC_SHORT_INQUIRY (1 << 8)
268#define USB_QUIRK_TEST (1 << 31)
269#define USB_QUIRK_NONE 0
270
Gabe Black93ded592012-11-01 15:44:10 -0700271static inline void usb_debug(const char *fmt, ...)
272{
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000273#ifdef USB_DEBUG
Gabe Black93ded592012-11-01 15:44:10 -0700274 va_list ap;
275 va_start(ap, fmt);
276 vprintf(fmt, ap);
277 va_end(ap);
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000278#endif
Gabe Black93ded592012-11-01 15:44:10 -0700279}
Stefan Reinauer5fe6e232009-07-31 11:39:55 +0000280
Gabe Blackdc9e77f2013-02-01 20:19:27 -0800281/**
282 * To be implemented by libpayload-client. It's called by the USB stack
283 * when a new USB device is found which isn't claimed by a built in driver,
284 * so the client has the chance to know about it.
285 *
286 * @param dev descriptor for the USB device
287 */
288void __attribute__((weak)) usb_generic_create (usbdev_t *dev);
289
290/**
291 * To be implemented by libpayload-client. It's called by the USB stack
292 * when it finds out that a USB device is removed which wasn't claimed by a
293 * built in driver.
294 *
295 * @param dev descriptor for the USB device
296 */
297void __attribute__((weak)) usb_generic_remove (usbdev_t *dev);
298
Patrick Georgid21f68b2008-09-02 16:06:22 +0000299#endif