2 * Driver for USB ported from CoreBoot
4 * Copyright (C) 2014 BALATON Zoltan
6 * This file was part of the libpayload project.
8 * Copyright (C) 2008 coresystems GmbH
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 #include <drivers/pci.h>
38 typedef enum { host_to_device = 0, device_to_host = 1 } dev_req_dir;
39 typedef enum { standard_type = 0, class_type = 1, vendor_type =
42 typedef enum { dev_recp = 0, iface_recp = 1, endp_recp = 2, other_recp = 3
52 GET_CONFIGURATION = 8,
53 SET_CONFIGURATION = 9,
61 DEVICE_REMOTE_WAKEUP = 1,
69 physical_device = 0x05,
70 imaging_device = 0x06,
71 printer_device = 0x07,
76 security_device = 0x0d,
78 healthcare_device = 0x0f,
79 diagnostic_device = 0xdc,
80 wireless_device = 0xe0,
84 enum { hid_subclass_none = 0, hid_subclass_boot = 1 };
87 hid_boot_proto_none = 0,
88 hid_boot_proto_keyboard = 1,
89 hid_boot_proto_mouse = 2
95 #ifdef CONFIG_BIG_ENDIAN
96 dev_req_dir data_dir:1;
97 dev_req_type req_type:2;
98 dev_req_recp req_recp:5;
100 dev_req_recp req_recp:5;
101 dev_req_type req_type:2;
102 dev_req_dir data_dir:1;
104 } __attribute__ ((packed));
105 unsigned char bmRequestType;
106 } __attribute__ ((packed));
107 unsigned char bRequest;
108 unsigned short wValue;
109 unsigned short wIndex;
110 unsigned short wLength;
111 } __attribute__ ((packed)) dev_req_t;
114 typedef struct usbdev_hc hci_t;
117 typedef struct usbdev usbdev_t;
119 typedef enum { SETUP, IN, OUT } direction_t;
120 typedef enum { CONTROL = 0, ISOCHRONOUS = 1, BULK = 2, INTERRUPT = 3
126 direction_t direction;
130 int interval; /* expressed as binary logarithm of the number
131 of microframes (i.e. t = 125us * 2^interval) */
134 enum { FULL_SPEED = 0, LOW_SPEED = 1, HIGH_SPEED = 2, SUPER_SPEED = 3 };
138 endpoint_t endpoints[32];
140 int address; // usb address
141 int hub; // hub, device is attached to
142 int port; // port where device is attached
143 int speed; // 1: lowspeed, 0: fullspeed, 2: highspeed
144 u32 quirks; // quirks field. got to love usb
148 void (*init) (usbdev_t *dev);
149 void (*destroy) (usbdev_t *dev);
150 void (*poll) (usbdev_t *dev);
153 typedef enum { OHCI = 0, UHCI = 1, EHCI = 2, XHCI = 3} hc_type;
159 usbdev_t *devices[128]; // dev 0 is root hub, 127 is last addressable
161 /* start(): Resume operation. */
162 void (*start) (hci_t *controller);
163 /* stop(): Stop operation but keep controller initialized. */
164 void (*stop) (hci_t *controller);
165 /* reset(): Perform a controller reset. The controller needs to
166 be (re)initialized afterwards to work (again). */
167 void (*reset) (hci_t *controller);
168 /* init(): Initialize a (previously reset) controller
169 to a working state. */
170 void (*init) (hci_t *controller);
171 /* shutdown(): Stop operation, detach host controller and shutdown
172 this driver instance. After calling shutdown() any
173 other usage of this hci_t* is invalid. */
174 void (*shutdown) (hci_t *controller);
176 int (*bulk) (endpoint_t *ep, int size, u8 *data, int finalize);
177 int (*control) (usbdev_t *dev, direction_t pid, int dr_length,
178 void *devreq, int data_length, u8 *data);
179 void* (*create_intr_queue) (endpoint_t *ep, int reqsize, int reqcount, int reqtiming);
180 void (*destroy_intr_queue) (endpoint_t *ep, void *queue);
181 u8* (*poll_intr_queue) (void *queue);
184 /* set_address(): Tell the usb device its address and
185 return it. xHCI controllers want to
186 do this by themself. Also, the usbdev
187 structure has to be allocated and
189 int (*set_address) (hci_t *controller, int speed, int hubport, int hubaddr);
190 /* finish_device_config(): Another hook for xHCI,
191 returns 0 on success. */
192 int (*finish_device_config) (usbdev_t *dev);
193 /* destroy_device(): Finally, destroy all structures that
194 were allocated during set_address()
195 and finish_device_config(). */
196 void (*destroy_device) (hci_t *controller, int devaddr);
200 unsigned char bDescLength;
201 unsigned char bDescriptorType;
202 unsigned char bNbrPorts;
205 #ifdef CONFIG_BIG_ENDIAN
207 unsigned long arePortIndicatorsSupported:1;
208 unsigned long ttThinkTime:2;
209 unsigned long overcurrentProtectionMode:2;
210 unsigned long isCompoundDevice:1;
211 unsigned long logicalPowerSwitchingMode:2;
213 unsigned long logicalPowerSwitchingMode:2;
214 unsigned long isCompoundDevice:1;
215 unsigned long overcurrentProtectionMode:2;
216 unsigned long ttThinkTime:2;
217 unsigned long arePortIndicatorsSupported:1;
220 } __attribute__ ((packed));
221 unsigned short wHubCharacteristics;
222 } __attribute__ ((packed));
223 unsigned char bPowerOn2PwrGood;
224 unsigned char bHubContrCurrent;
225 char DeviceRemovable[];
226 } __attribute__ ((packed)) hub_descriptor_t;
229 unsigned char bLength;
230 unsigned char bDescriptorType;
231 unsigned short bcdUSB;
232 unsigned char bDeviceClass;
233 unsigned char bDeviceSubClass;
234 unsigned char bDeviceProtocol;
235 unsigned char bMaxPacketSize0;
236 unsigned short idVendor;
237 unsigned short idProduct;
238 unsigned short bcdDevice;
239 unsigned char iManufacturer;
240 unsigned char iProduct;
241 unsigned char iSerialNumber;
242 unsigned char bNumConfigurations;
243 } __attribute__ ((packed)) device_descriptor_t;
246 unsigned char bLength;
247 unsigned char bDescriptorType;
248 unsigned short wTotalLength;
249 unsigned char bNumInterfaces;
250 unsigned char bConfigurationValue;
251 unsigned char iConfiguration;
252 unsigned char bmAttributes;
253 unsigned char bMaxPower;
254 } __attribute__ ((packed)) configuration_descriptor_t;
257 unsigned char bLength;
258 unsigned char bDescriptorType;
259 unsigned char bInterfaceNumber;
260 unsigned char bAlternateSetting;
261 unsigned char bNumEndpoints;
262 unsigned char bInterfaceClass;
263 unsigned char bInterfaceSubClass;
264 unsigned char bInterfaceProtocol;
265 unsigned char iInterface;
266 } __attribute__ ((packed)) interface_descriptor_t;
269 unsigned char bLength;
270 unsigned char bDescriptorType;
271 unsigned char bEndpointAddress;
272 unsigned char bmAttributes;
273 unsigned short wMaxPacketSize;
274 unsigned char bInterval;
275 } __attribute__ ((packed)) endpoint_descriptor_t;
278 unsigned char bLength;
279 unsigned char bDescriptorType;
280 unsigned short bcdHID;
281 unsigned char bCountryCode;
282 unsigned char bNumDescriptors;
283 unsigned char bReportDescriptorType;
284 unsigned short wReportDescriptorLength;
285 } __attribute__ ((packed)) hid_descriptor_t;
287 hci_t *new_controller (void);
288 void detach_controller (hci_t *controller);
289 void usb_poll (void);
290 void init_device_entry (hci_t *controller, int num);
292 void set_feature (usbdev_t *dev, int endp, int feature, int rtype);
293 void get_status (usbdev_t *dev, int endp, int rtype, int len, void *data);
294 void set_configuration (usbdev_t *dev);
295 int clear_feature (usbdev_t *dev, int endp, int feature, int rtype);
296 int clear_stall (endpoint_t *ep);
298 void usb_hub_init (usbdev_t *dev);
299 void usb_hid_init (usbdev_t *dev);
300 void usb_msc_init (usbdev_t *dev);
301 void usb_generic_init (usbdev_t *dev);
303 u8 *get_descriptor (usbdev_t *dev, unsigned char bmRequestType,
304 int descType, int descIdx, int langID);
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 int generic_set_address (hci_t *controller, int speed, int hubport, int hubaddr);
315 void usb_detach_device(hci_t *controller, int devno);
316 int usb_attach_device(hci_t *controller, int hubaddress, int port, int speed);
318 u32 usb_quirk_check(u16 vendor, u16 device);
319 int usb_interface_check(u16 vendor, u16 device);
321 #define USB_QUIRK_MSC_FORCE_PROTO_SCSI (1 << 0)
322 #define USB_QUIRK_MSC_FORCE_PROTO_ATAPI (1 << 1)
323 #define USB_QUIRK_MSC_FORCE_PROTO_UFI (1 << 2)
324 #define USB_QUIRK_MSC_FORCE_PROTO_RBC (1 << 3)
325 #define USB_QUIRK_MSC_FORCE_TRANS_BBB (1 << 4)
326 #define USB_QUIRK_MSC_FORCE_TRANS_CBI (1 << 5)
327 #define USB_QUIRK_MSC_FORCE_TRANS_CBI_I (1 << 6)
328 #define USB_QUIRK_MSC_NO_TEST_UNIT_READY (1 << 7)
329 #define USB_QUIRK_MSC_SHORT_INQUIRY (1 << 8)
330 #define USB_QUIRK_TEST (1 << 31)
331 #define USB_QUIRK_NONE 0
333 #ifdef CONFIG_DEBUG_USB
334 #define usb_debug(fmt, args...) do { printk(fmt , ##args); } while (0)
336 #define usb_debug(fmt, args...)
340 * To be implemented by libpayload-client. It's called by the USB stack
341 * when a new USB device is found which isn't claimed by a built in driver,
342 * so the client has the chance to know about it.
344 * @param dev descriptor for the USB device
346 void __attribute__((weak)) usb_generic_create (usbdev_t *dev);
349 * To be implemented by libpayload-client. It's called by the USB stack
350 * when it finds out that a USB device is removed which wasn't claimed by a
353 * @param dev descriptor for the USB device
355 void __attribute__((weak)) usb_generic_remove (usbdev_t *dev);