blob: bb42f89826c8f460df652db452d6c0e2ecd4746f [file] [log] [blame]
Patrick Georgid21f68b2008-09-02 16:06:22 +00001/*
2 * This file is part of the libpayload project.
3 *
Stefan Reinauerb56f2d02010-03-25 22:17:36 +00004 * Copyright (C) 2008-2010 coresystems GmbH
Patrick Georgid21f68b2008-09-02 16:06:22 +00005 *
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
Stefan Reinauerb56f2d02010-03-25 22:17:36 +000030//#define USB_DEBUG
31
Jordan Crousedb8c0ab2008-11-24 17:54:46 +000032#include <libpayload-config.h>
Jordan Crouse29061a52008-09-11 17:29:00 +000033#include <usb/usb.h>
Patrick Georgid21f68b2008-09-02 16:06:22 +000034
Julius Wernerd13e2c42013-09-17 22:16:04 -070035#define DR_DESC gen_bmRequestType(device_to_host, standard_type, dev_recp)
36
Patrick Georgid21f68b2008-09-02 16:06:22 +000037hci_t *usb_hcs = 0;
38
39hci_t *
Stefan Reinauer5fe6e232009-07-31 11:39:55 +000040new_controller (void)
Patrick Georgid21f68b2008-09-02 16:06:22 +000041{
Julius Werner7234d602014-04-08 12:54:25 -070042 hci_t *controller = xzalloc(sizeof (hci_t));
43 controller->next = usb_hcs;
44 usb_hcs = controller;
Patrick Georgid21f68b2008-09-02 16:06:22 +000045 return controller;
46}
47
48void
49detach_controller (hci_t *controller)
50{
Stefan Reinauer5fe6e232009-07-31 11:39:55 +000051 if (controller == NULL)
Patrick Georgid21f68b2008-09-02 16:06:22 +000052 return;
Julius Werner7234d602014-04-08 12:54:25 -070053
54 usb_detach_device(controller, 0); /* tear down root hub tree */
55
Patrick Georgid21f68b2008-09-02 16:06:22 +000056 if (usb_hcs == controller) {
57 usb_hcs = controller->next;
58 } else {
59 hci_t *it = usb_hcs;
Stefan Reinauer5fe6e232009-07-31 11:39:55 +000060 while (it != NULL) {
Patrick Georgid21f68b2008-09-02 16:06:22 +000061 if (it->next == controller) {
62 it->next = controller->next;
63 return;
64 }
Anton Kochkov421303a2012-06-20 03:57:18 +040065 it = it->next;
Patrick Georgid21f68b2008-09-02 16:06:22 +000066 }
67 }
68}
69
70/**
Patrick Georgibbc52312011-11-04 12:06:06 +010071 * Shut down all controllers
72 */
73int
74usb_exit (void)
75{
Mathias Krause59c020a2013-03-24 19:40:02 +010076 while (usb_hcs != NULL) {
77 usb_hcs->shutdown(usb_hcs);
Patrick Georgibbc52312011-11-04 12:06:06 +010078 }
79 return 0;
80}
81
82/**
Patrick Georgid21f68b2008-09-02 16:06:22 +000083 * Polls all hubs on all USB controllers, to find out about device changes
84 */
85void
Stefan Reinauerb56f2d02010-03-25 22:17:36 +000086usb_poll (void)
Patrick Georgid21f68b2008-09-02 16:06:22 +000087{
88 if (usb_hcs == 0)
89 return;
90 hci_t *controller = usb_hcs;
Patrick Georgidb89ec92011-11-18 11:56:38 +010091 while (controller != NULL) {
Patrick Georgid21f68b2008-09-02 16:06:22 +000092 int i;
93 for (i = 0; i < 128; i++) {
Patrick Georgi4727c072008-10-16 19:20:51 +000094 if (controller->devices[i] != 0) {
Stefan Reinauerb56f2d02010-03-25 22:17:36 +000095 controller->devices[i]->poll (controller->devices[i]);
Patrick Georgid21f68b2008-09-02 16:06:22 +000096 }
97 }
98 controller = controller->next;
99 }
100}
101
Julius Wernerd13e2c42013-09-17 22:16:04 -0700102usbdev_t *
Patrick Georgid21f68b2008-09-02 16:06:22 +0000103init_device_entry (hci_t *controller, int i)
104{
Julius Wernerd13e2c42013-09-17 22:16:04 -0700105 usbdev_t *dev = calloc(1, sizeof(usbdev_t));
106 if (!dev) {
107 usb_debug("no memory to allocate device structure\n");
108 return NULL;
109 }
Patrick Georgi4727c072008-10-16 19:20:51 +0000110 if (controller->devices[i] != 0)
Gabe Black93ded592012-11-01 15:44:10 -0700111 usb_debug("warning: device %d reassigned?\n", i);
Julius Wernerd13e2c42013-09-17 22:16:04 -0700112 controller->devices[i] = dev;
113 dev->controller = controller;
114 dev->address = -1;
115 dev->hub = -1;
116 dev->port = -1;
117 dev->init = usb_nop_init;
118 dev->init (controller->devices[i]);
119 return dev;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000120}
121
Julius Wernerd13e2c42013-09-17 22:16:04 -0700122int
Patrick Georgid21f68b2008-09-02 16:06:22 +0000123set_feature (usbdev_t *dev, int endp, int feature, int rtype)
124{
125 dev_req_t dr;
126
127 dr.bmRequestType = rtype;
128 dr.data_dir = host_to_device;
129 dr.bRequest = SET_FEATURE;
130 dr.wValue = feature;
131 dr.wIndex = endp;
132 dr.wLength = 0;
Julius Wernerd13e2c42013-09-17 22:16:04 -0700133
134 return dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000135}
136
Julius Wernerd13e2c42013-09-17 22:16:04 -0700137int
Patrick Georgid21f68b2008-09-02 16:06:22 +0000138get_status (usbdev_t *dev, int intf, int rtype, int len, void *data)
139{
140 dev_req_t dr;
141
142 dr.bmRequestType = rtype;
143 dr.data_dir = device_to_host;
144 dr.bRequest = GET_STATUS;
145 dr.wValue = 0;
146 dr.wIndex = intf;
147 dr.wLength = len;
Julius Wernerd13e2c42013-09-17 22:16:04 -0700148
149 return dev->controller->control (dev, IN, sizeof (dr), &dr, len, data);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000150}
151
Shawn Nematbakhshff5d0b22015-09-24 14:45:10 -0700152/*
153 * Certain Lexar / Micron USB 2.0 disks will fail the get_descriptor(DT_CFG)
154 * call due to timing issues. Work around this by making extra attempts on
155 * failure.
156 */
157#define GET_DESCRIPTOR_TRIES 3
158
Julius Wernerd13e2c42013-09-17 22:16:04 -0700159int
Shawn Nematbakhshff5d0b22015-09-24 14:45:10 -0700160get_descriptor(usbdev_t *dev, int rtype, int desc_type, int desc_idx,
Julius Wernerd13e2c42013-09-17 22:16:04 -0700161 void *data, size_t len)
Patrick Georgid21f68b2008-09-02 16:06:22 +0000162{
Patrick Georgid21f68b2008-09-02 16:06:22 +0000163 dev_req_t dr;
Shawn Nematbakhshff5d0b22015-09-24 14:45:10 -0700164 int fail_tries = 0;
165 int ret = 0;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000166
Shawn Nematbakhshff5d0b22015-09-24 14:45:10 -0700167 while (fail_tries++ < GET_DESCRIPTOR_TRIES) {
168 dr.bmRequestType = rtype;
169 dr.bRequest = GET_DESCRIPTOR;
170 dr.wValue = desc_type << 8 | desc_idx;
171 dr.wIndex = 0;
172 dr.wLength = len;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000173
Shawn Nematbakhshff5d0b22015-09-24 14:45:10 -0700174 ret = dev->controller->control(dev, IN,
175 sizeof(dr), &dr, len, data);
176 if (ret)
177 udelay(10);
178 else
179 return 0;
180 }
181 return ret;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000182}
183
Julius Wernerd13e2c42013-09-17 22:16:04 -0700184int
Patrick Georgid21f68b2008-09-02 16:06:22 +0000185set_configuration (usbdev_t *dev)
186{
187 dev_req_t dr;
188
189 dr.bmRequestType = 0;
190 dr.bRequest = SET_CONFIGURATION;
Julius Wernerd13e2c42013-09-17 22:16:04 -0700191 dr.wValue = dev->configuration->bConfigurationValue;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000192 dr.wIndex = 0;
193 dr.wLength = 0;
Julius Wernerd13e2c42013-09-17 22:16:04 -0700194
195 return dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000196}
197
Nico Huber79e1f2f2012-06-01 09:50:11 +0200198int
Nico Huber5f595cb2012-05-21 16:19:05 +0200199clear_feature (usbdev_t *dev, int endp, int feature, int rtype)
200{
201 dev_req_t dr;
202
203 dr.bmRequestType = rtype;
204 dr.data_dir = host_to_device;
205 dr.bRequest = CLEAR_FEATURE;
206 dr.wValue = feature;
207 dr.wIndex = endp;
208 dr.wLength = 0;
Julius Wernerd13e2c42013-09-17 22:16:04 -0700209
Julius Wernere9738db2013-02-21 13:41:40 -0800210 return dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0) < 0;
Nico Huber5f595cb2012-05-21 16:19:05 +0200211}
212
Patrick Georgid21f68b2008-09-02 16:06:22 +0000213int
214clear_stall (endpoint_t *ep)
215{
Julius Wernerd13e2c42013-09-17 22:16:04 -0700216 int ret = clear_feature (ep->dev, ep->endpoint, ENDPOINT_HALT,
217 gen_bmRequestType (host_to_device, standard_type, endp_recp));
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000218 ep->toggle = 0;
Nico Huber79e1f2f2012-06-01 09:50:11 +0200219 return ret;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000220}
221
222/* returns free address or -1 */
223static int
224get_free_address (hci_t *controller)
225{
Julius Werner6af43802014-04-28 16:04:24 -0700226 int i = controller->latest_address + 1;
227 for (; i != controller->latest_address; i++) {
228 if (i >= ARRAY_SIZE(controller->devices) || i < 1) {
229 usb_debug("WARNING: Device addresses for controller %#x"
230 " wrapped around!\n", controller->reg_base);
231 i = 0;
232 continue;
233 }
234 if (controller->devices[i] == 0) {
235 controller->latest_address = i;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000236 return i;
Julius Werner6af43802014-04-28 16:04:24 -0700237 }
Patrick Georgid21f68b2008-09-02 16:06:22 +0000238 }
Gabe Black93ded592012-11-01 15:44:10 -0700239 usb_debug ("no free address found\n");
Patrick Georgid21f68b2008-09-02 16:06:22 +0000240 return -1; // no free address
241}
242
Patrick Georgi482af6d2013-05-24 15:48:56 +0200243int
Julius Wernere00ba212013-09-24 20:03:54 -0700244usb_decode_mps0(usb_speed speed, u8 bMaxPacketSize0)
Patrick Georgid21f68b2008-09-02 16:06:22 +0000245{
Julius Wernere00ba212013-09-24 20:03:54 -0700246 switch (speed) {
247 case LOW_SPEED:
248 if (bMaxPacketSize0 != 8) {
249 usb_debug("Invalid MPS0: 0x%02x\n", bMaxPacketSize0);
250 bMaxPacketSize0 = 8;
251 }
252 return bMaxPacketSize0;
253 case FULL_SPEED:
254 switch (bMaxPacketSize0) {
255 case 8: case 16: case 32: case 64:
256 return bMaxPacketSize0;
257 default:
258 usb_debug("Invalid MPS0: 0x%02x\n", bMaxPacketSize0);
259 return 8;
260 }
261 case HIGH_SPEED:
262 if (bMaxPacketSize0 != 64) {
263 usb_debug("Invalid MPS0: 0x%02x\n", bMaxPacketSize0);
264 bMaxPacketSize0 = 64;
265 }
266 return bMaxPacketSize0;
267 case SUPER_SPEED:
268 if (bMaxPacketSize0 != 9) {
269 usb_debug("Invalid MPS0: 0x%02x\n", bMaxPacketSize0);
270 bMaxPacketSize0 = 9;
271 }
Chunfeng Yun08e30132015-05-07 15:28:19 +0800272 return 1 << bMaxPacketSize0;
Julius Wernere00ba212013-09-24 20:03:54 -0700273 default: /* GCC is stupid and cannot deal with enums correctly */
274 return 8;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000275 }
Patrick Georgi482af6d2013-05-24 15:48:56 +0200276}
277
Varadarajan Narayanan8e0ffe22016-03-17 14:43:35 +0530278int speed_to_default_mps(usb_speed speed)
279{
280 switch (speed) {
281 case LOW_SPEED:
282 return 8;
283 case FULL_SPEED:
284 case HIGH_SPEED:
285 return 64;
286 case SUPER_SPEED:
287 default:
288 return 512;
289 }
290}
291
Nico Huberaee44fa2013-06-06 10:20:35 +0200292/* Normalize bInterval to log2 of microframes */
293static int
Julius Wernere00ba212013-09-24 20:03:54 -0700294usb_decode_interval(usb_speed speed, const endpoint_type type, const unsigned char bInterval)
Nico Huberaee44fa2013-06-06 10:20:35 +0200295{
296#define LOG2(a) ((sizeof(unsigned) << 3) - __builtin_clz(a) - 1)
297 switch (speed) {
298 case LOW_SPEED:
299 switch (type) {
300 case ISOCHRONOUS: case INTERRUPT:
301 return LOG2(bInterval) + 3;
302 default:
303 return 0;
304 }
305 case FULL_SPEED:
306 switch (type) {
307 case ISOCHRONOUS:
308 return (bInterval - 1) + 3;
309 case INTERRUPT:
310 return LOG2(bInterval) + 3;
311 default:
312 return 0;
313 }
314 case HIGH_SPEED:
315 switch (type) {
316 case ISOCHRONOUS: case INTERRUPT:
317 return bInterval - 1;
318 default:
319 return LOG2(bInterval);
320 }
321 case SUPER_SPEED:
322 switch (type) {
323 case ISOCHRONOUS: case INTERRUPT:
324 return bInterval - 1;
325 default:
326 return 0;
327 }
328 default:
329 return 0;
330 }
331#undef LOG2
332}
333
Julius Wernerd13e2c42013-09-17 22:16:04 -0700334usbdev_t *
Julius Wernere00ba212013-09-24 20:03:54 -0700335generic_set_address (hci_t *controller, usb_speed speed,
336 int hubport, int hubaddr)
337{
338 int adr = get_free_address (controller); // address to set
Patrick Georgib5623de2017-01-04 22:22:56 +0100339 if (adr < 0)
340 return NULL;
Julius Wernere00ba212013-09-24 20:03:54 -0700341 dev_req_t dr;
342
343 memset (&dr, 0, sizeof (dr));
344 dr.data_dir = host_to_device;
345 dr.req_type = standard_type;
346 dr.req_recp = dev_recp;
347 dr.bRequest = SET_ADDRESS;
348 dr.wValue = adr;
349 dr.wIndex = 0;
350 dr.wLength = 0;
351
Julius Wernerd13e2c42013-09-17 22:16:04 -0700352 usbdev_t *dev = init_device_entry(controller, adr);
353 if (!dev)
354 return NULL;
355
Julius Wernere00ba212013-09-24 20:03:54 -0700356 // dummy values for registering the address
357 dev->address = 0;
358 dev->hub = hubaddr;
359 dev->port = hubport;
360 dev->speed = speed;
361 dev->endpoints[0].dev = dev;
362 dev->endpoints[0].endpoint = 0;
363 dev->endpoints[0].maxpacketsize = 8;
364 dev->endpoints[0].toggle = 0;
365 dev->endpoints[0].direction = SETUP;
Julius Wernerd13e2c42013-09-17 22:16:04 -0700366 dev->endpoints[0].type = CONTROL;
Julius Wernere00ba212013-09-24 20:03:54 -0700367 if (dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0) < 0) {
368 usb_debug ("set_address failed\n");
Julius Wernerd13e2c42013-09-17 22:16:04 -0700369 usb_detach_device (controller, adr);
370 return NULL;
Julius Wernere00ba212013-09-24 20:03:54 -0700371 }
372 mdelay (SET_ADDRESS_MDELAY);
373
Julius Wernerd13e2c42013-09-17 22:16:04 -0700374 u8 buf[8];
375 dev->address = adr;
376 if (get_descriptor (dev, DR_DESC, DT_DEV, 0, buf, sizeof(buf))
377 != sizeof(buf)) {
378 usb_debug("first get_descriptor(DT_DEV) failed\n");
379 usb_detach_device (controller, adr);
380 return NULL;
381 }
382 dev->endpoints[0].maxpacketsize = usb_decode_mps0(speed, buf[7]);
383
384 return dev;
Julius Wernere00ba212013-09-24 20:03:54 -0700385}
386
Patrick Georgi482af6d2013-05-24 15:48:56 +0200387static int
Julius Wernere00ba212013-09-24 20:03:54 -0700388set_address (hci_t *controller, usb_speed speed, int hubport, int hubaddr)
Patrick Georgi482af6d2013-05-24 15:48:56 +0200389{
Julius Wernerd13e2c42013-09-17 22:16:04 -0700390 usbdev_t *dev = controller->set_address(controller, speed,
391 hubport, hubaddr);
392 if (!dev) {
Patrick Georgi482af6d2013-05-24 15:48:56 +0200393 usb_debug ("set_address failed\n");
394 return -1;
395 }
Patrick Georgi482af6d2013-05-24 15:48:56 +0200396
Julius Wernerd13e2c42013-09-17 22:16:04 -0700397 dev->descriptor = malloc(sizeof(*dev->descriptor));
398 if (!dev->descriptor || get_descriptor (dev, DR_DESC, DT_DEV, 0,
399 dev->descriptor, sizeof(*dev->descriptor))
400 != sizeof(*dev->descriptor)) {
401 usb_debug ("get_descriptor(DT_DEV) failed\n");
402 usb_detach_device (controller, dev->address);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000403 return -1;
404 }
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000405
Julius Wernerd13e2c42013-09-17 22:16:04 -0700406 usb_debug ("* found device (0x%04x:0x%04x, USB %x.%x, MPS0: %d)\n",
407 dev->descriptor->idVendor, dev->descriptor->idProduct,
408 dev->descriptor->bcdUSB >> 8, dev->descriptor->bcdUSB & 0xff,
409 dev->endpoints[0].maxpacketsize);
410 dev->quirks = usb_quirk_check(dev->descriptor->idVendor,
411 dev->descriptor->idProduct);
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000412
Julius Wernerd13e2c42013-09-17 22:16:04 -0700413 usb_debug ("device has %d configurations\n",
414 dev->descriptor->bNumConfigurations);
415 if (dev->descriptor->bNumConfigurations == 0) {
416 /* device isn't usable */
417 usb_debug ("... no usable configuration!\n");
418 usb_detach_device (controller, dev->address);
419 return -1;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000420 }
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000421
Julius Wernerd13e2c42013-09-17 22:16:04 -0700422 u16 buf[2];
423 if (get_descriptor (dev, DR_DESC, DT_CFG, 0, buf, sizeof(buf))
424 != sizeof(buf)) {
425 usb_debug ("first get_descriptor(DT_CFG) failed\n");
426 usb_detach_device (controller, dev->address);
427 return -1;
428 }
Patrick Georgif72d3282014-11-10 16:50:21 +0100429 /* workaround for some USB devices: wait until they're ready, or
430 * they send a NAK when they're not allowed to do. 1ms is enough */
431 mdelay(1);
Julius Wernerd13e2c42013-09-17 22:16:04 -0700432 dev->configuration = malloc(buf[1]);
433 if (!dev->configuration) {
434 usb_debug ("could not allocate %d bytes for DT_CFG\n", buf[1]);
435 usb_detach_device (controller, dev->address);
436 return -1;
437 }
438 if (get_descriptor (dev, DR_DESC, DT_CFG, 0, dev->configuration,
439 buf[1]) != buf[1]) {
440 usb_debug ("get_descriptor(DT_CFG) failed\n");
441 usb_detach_device (controller, dev->address);
442 return -1;
443 }
444 configuration_descriptor_t *cd = dev->configuration;
445 if (cd->wTotalLength != buf[1]) {
446 usb_debug ("configuration descriptor size changed, aborting\n");
447 usb_detach_device (controller, dev->address);
448 return -1;
449 }
Patrick Georgi482af6d2013-05-24 15:48:56 +0200450
Julius Wernerd13e2c42013-09-17 22:16:04 -0700451 /*
452 * If the device is not well known (ifnum == -1), we use the first
453 * interface we encounter, as there was no need to implement something
454 * else for the time being. If you need it, see the SetInterface and
455 * GetInterface functions in the USB specification and set it yourself.
456 */
457 usb_debug ("device has %x interfaces\n", cd->bNumInterfaces);
458 int ifnum = usb_interface_check(dev->descriptor->idVendor,
459 dev->descriptor->idProduct);
460 if (cd->bNumInterfaces > 1 && ifnum < 0)
461 usb_debug ("NOTICE: Your device has multiple interfaces and\n"
462 "this driver will only use the first one. That may\n"
463 "be the wrong choice and cause the device to not\n"
464 "work correctly. Please report this case\n"
465 "(including the above debugging output) to\n"
466 "coreboot@coreboot.org to have the device added to\n"
467 "the list of well-known quirks.\n");
Patrick Georgi482af6d2013-05-24 15:48:56 +0200468
Julius Wernerd13e2c42013-09-17 22:16:04 -0700469 u8 *end = (void *)dev->configuration + cd->wTotalLength;
470 interface_descriptor_t *intf;
471 u8 *ptr;
472
473 /* Find our interface (or the first good one if we don't know) */
474 for (ptr = (void *)dev->configuration + sizeof(*cd); ; ptr += ptr[0]) {
475 if (ptr + 2 > end || !ptr[0] || ptr + ptr[0] > end) {
476 usb_debug ("Couldn't find usable DT_INTF\n");
477 usb_detach_device (controller, dev->address);
478 return -1;
479 }
480 if (ptr[1] != DT_INTF)
481 continue;
482 intf = (void *)ptr;
483 if (intf->bLength != sizeof(*intf)) {
484 usb_debug ("Skipping broken DT_INTF\n");
485 continue;
486 }
487 if (ifnum >= 0 && intf->bInterfaceNumber != ifnum)
488 continue;
489 usb_debug ("Interface %d: class 0x%x, sub 0x%x. proto 0x%x\n",
490 intf->bInterfaceNumber, intf->bInterfaceClass,
491 intf->bInterfaceSubClass, intf->bInterfaceProtocol);
492 ptr += sizeof(*intf);
493 break;
494 }
495
496 /* Gather up all endpoints belonging to this inteface */
497 dev->num_endp = 1;
498 for (; ptr + 2 <= end && ptr[0] && ptr + ptr[0] <= end; ptr += ptr[0]) {
499 if (ptr[1] == DT_INTF || ptr[1] == DT_CFG ||
500 dev->num_endp >= ARRAY_SIZE(dev->endpoints))
501 break;
502 if (ptr[1] != DT_ENDP)
503 continue;
504
505 endpoint_descriptor_t *desc = (void *)ptr;
506 static const char *transfertypes[4] = {
507 "control", "isochronous", "bulk", "interrupt"
508 };
509 usb_debug (" #Endpoint %d (%s), max packet size %x, type %s\n",
510 desc->bEndpointAddress & 0x7f,
511 (desc->bEndpointAddress & 0x80) ? "in" : "out",
512 desc->wMaxPacketSize,
513 transfertypes[desc->bmAttributes & 0x3]);
514
515 endpoint_t *ep = &dev->endpoints[dev->num_endp++];
516 ep->dev = dev;
517 ep->endpoint = desc->bEndpointAddress;
518 ep->toggle = 0;
519 ep->maxpacketsize = desc->wMaxPacketSize;
520 ep->direction = (desc->bEndpointAddress & 0x80) ? IN : OUT;
521 ep->type = desc->bmAttributes & 0x3;
522 ep->interval = usb_decode_interval (dev->speed, ep->type,
523 desc->bInterval);
524 }
525
526 if ((controller->finish_device_config &&
527 controller->finish_device_config(dev)) ||
528 set_configuration(dev) < 0) {
529 usb_debug ("Could not finalize device configuration\n");
530 usb_detach_device (controller, dev->address);
531 return -1;
532 }
533
534 int class = dev->descriptor->bDeviceClass;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000535 if (class == 0)
Julius Wernerd13e2c42013-09-17 22:16:04 -0700536 class = intf->bInterfaceClass;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000537
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000538 enum {
539 audio_device = 0x01,
540 comm_device = 0x02,
541 hid_device = 0x03,
542 physical_device = 0x05,
543 imaging_device = 0x06,
544 printer_device = 0x07,
545 msc_device = 0x08,
546 hub_device = 0x09,
547 cdc_device = 0x0a,
548 ccid_device = 0x0b,
549 security_device = 0x0d,
550 video_device = 0x0e,
551 healthcare_device = 0x0f,
552 diagnostic_device = 0xdc,
553 wireless_device = 0xe0,
554 misc_device = 0xef,
555 };
Julius Wernerd13e2c42013-09-17 22:16:04 -0700556 usb_debug("Class: ");
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000557 switch (class) {
558 case audio_device:
Dave Frodin6bf11cf2012-12-11 13:08:07 -0700559 usb_debug("audio\n");
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000560 break;
561 case comm_device:
Dave Frodin6bf11cf2012-12-11 13:08:07 -0700562 usb_debug("communication\n");
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000563 break;
564 case hid_device:
Dave Frodin6bf11cf2012-12-11 13:08:07 -0700565 usb_debug ("HID\n");
Stefan Reinauer1b4d3942015-06-29 15:47:34 -0700566#if IS_ENABLED(CONFIG_LP_USB_HID)
Julius Wernerd13e2c42013-09-17 22:16:04 -0700567 dev->init = usb_hid_init;
568 return dev->address;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000569#else
Gabe Black93ded592012-11-01 15:44:10 -0700570 usb_debug ("NOTICE: USB HID support not compiled in\n");
Patrick Georgid21f68b2008-09-02 16:06:22 +0000571#endif
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000572 break;
573 case physical_device:
Dave Frodin6bf11cf2012-12-11 13:08:07 -0700574 usb_debug("physical\n");
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000575 break;
576 case imaging_device:
Dave Frodin6bf11cf2012-12-11 13:08:07 -0700577 usb_debug("camera\n");
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000578 break;
579 case printer_device:
Dave Frodin6bf11cf2012-12-11 13:08:07 -0700580 usb_debug("printer\n");
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000581 break;
582 case msc_device:
Dave Frodin6bf11cf2012-12-11 13:08:07 -0700583 usb_debug ("MSC\n");
Stefan Reinauer1b4d3942015-06-29 15:47:34 -0700584#if IS_ENABLED(CONFIG_LP_USB_MSC)
Julius Wernerd13e2c42013-09-17 22:16:04 -0700585 dev->init = usb_msc_init;
586 return dev->address;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000587#else
Gabe Black93ded592012-11-01 15:44:10 -0700588 usb_debug ("NOTICE: USB MSC support not compiled in\n");
Patrick Georgid21f68b2008-09-02 16:06:22 +0000589#endif
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000590 break;
591 case hub_device:
Julius Werner752fba72015-07-09 16:29:10 -0700592 usb_debug ("hub\n");
Stefan Reinauer1b4d3942015-06-29 15:47:34 -0700593#if IS_ENABLED(CONFIG_LP_USB_HUB)
Julius Werner752fba72015-07-09 16:29:10 -0700594 dev->init = usb_hub_init;
595 return dev->address;
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000596#else
Julius Werner752fba72015-07-09 16:29:10 -0700597 usb_debug ("NOTICE: USB hub support not compiled in\n");
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000598#endif
599 break;
600 case cdc_device:
Dave Frodin6bf11cf2012-12-11 13:08:07 -0700601 usb_debug("CDC\n");
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000602 break;
603 case ccid_device:
Dave Frodin6bf11cf2012-12-11 13:08:07 -0700604 usb_debug("smartcard / CCID\n");
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000605 break;
606 case security_device:
Dave Frodin6bf11cf2012-12-11 13:08:07 -0700607 usb_debug("content security\n");
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000608 break;
609 case video_device:
Dave Frodin6bf11cf2012-12-11 13:08:07 -0700610 usb_debug("video\n");
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000611 break;
612 case healthcare_device:
Dave Frodin6bf11cf2012-12-11 13:08:07 -0700613 usb_debug("healthcare\n");
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000614 break;
615 case diagnostic_device:
Dave Frodin6bf11cf2012-12-11 13:08:07 -0700616 usb_debug("diagnostic\n");
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000617 break;
618 case wireless_device:
Dave Frodin6bf11cf2012-12-11 13:08:07 -0700619 usb_debug("wireless\n");
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000620 break;
621 default:
Dave Frodin6bf11cf2012-12-11 13:08:07 -0700622 usb_debug("unsupported class %x\n", class);
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000623 break;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000624 }
Julius Wernerd13e2c42013-09-17 22:16:04 -0700625 dev->init = usb_generic_init;
626 return dev->address;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000627}
Patrick Georgi4727c072008-10-16 19:20:51 +0000628
Nico Huber79e1f2f2012-06-01 09:50:11 +0200629/*
630 * Should be called by the hub drivers whenever a physical detach occurs
631 * and can be called by usb class drivers if they are unsatisfied with a
632 * malfunctioning device.
633 */
Patrick Georgi4727c072008-10-16 19:20:51 +0000634void
635usb_detach_device(hci_t *controller, int devno)
636{
Nico Huber79e1f2f2012-06-01 09:50:11 +0200637 /* check if device exists, as we may have
638 been called yet by the usb class driver */
639 if (controller->devices[devno]) {
640 controller->devices[devno]->destroy (controller->devices[devno]);
Julius Wernere00ba212013-09-24 20:03:54 -0700641 if (controller->destroy_device)
642 controller->destroy_device(controller, devno);
Aaron Durbine3260ec2015-07-31 17:08:00 -0500643 /* Tear down the device itself *after* destroy_device()
644 * has had a chance to interoogate it. */
645 free(controller->devices[devno]);
646 controller->devices[devno] = NULL;
Nico Huber79e1f2f2012-06-01 09:50:11 +0200647 }
Patrick Georgi4727c072008-10-16 19:20:51 +0000648}
649
650int
Julius Wernere00ba212013-09-24 20:03:54 -0700651usb_attach_device(hci_t *controller, int hubaddress, int port, usb_speed speed)
Patrick Georgi4727c072008-10-16 19:20:51 +0000652{
Julius Wernere00ba212013-09-24 20:03:54 -0700653 static const char* speeds[] = { "full", "low", "high", "super" };
654 usb_debug ("%sspeed device\n", (speed < sizeof(speeds) / sizeof(char*))
655 ? speeds[speed] : "invalid value - no");
Nico Huber1ab60752012-05-23 09:21:54 +0200656 int newdev = set_address (controller, speed, port, hubaddress);
Patrick Georgi4727c072008-10-16 19:20:51 +0000657 if (newdev == -1)
658 return -1;
659 usbdev_t *newdev_t = controller->devices[newdev];
Patrick Georgi4727c072008-10-16 19:20:51 +0000660 // determine responsible driver - current done in set_address
661 newdev_t->init (newdev_t);
Nico Huberd8a66802012-06-21 11:21:23 +0200662 /* init() may have called usb_detach_device() yet, so check */
663 return controller->devices[newdev] ? newdev : -1;
Patrick Georgi4727c072008-10-16 19:20:51 +0000664}
Stefan Reinauer5fe6e232009-07-31 11:39:55 +0000665
Gabe Blackdc9e77f2013-02-01 20:19:27 -0800666static void
667usb_generic_destroy (usbdev_t *dev)
668{
669 if (usb_generic_remove)
670 usb_generic_remove(dev);
671}
672
673void
674usb_generic_init (usbdev_t *dev)
675{
676 dev->data = NULL;
677 dev->destroy = usb_generic_destroy;
678
679 if (usb_generic_create)
680 usb_generic_create(dev);
Shawn Nematbakhsh7faff542014-04-15 21:34:30 -0700681
682 if (dev->data == NULL) {
683 usb_debug("Detaching device not used by payload\n");
684 usb_detach_device(dev->controller, dev->address);
685 }
Gabe Blackdc9e77f2013-02-01 20:19:27 -0800686}
Yunzhi Liebd3da72015-07-02 15:28:11 +0800687
688/*
689 * returns the address of the closest USB2.0 hub, which is responsible for
690 * split transactions, along with the number of the used downstream port
691 */
692int closest_usb2_hub(const usbdev_t *dev, int *const addr, int *const port)
693{
694 const usbdev_t *usb1dev;
695
696 do {
697 usb1dev = dev;
698 if ((dev->hub >= 0) && (dev->hub < 128))
699 dev = dev->controller->devices[dev->hub];
700 else
701 dev = NULL;
702 } while (dev && (dev->speed < 2));
703
704 if (dev) {
705 *addr = usb1dev->hub;
706 *port = usb1dev->port;
707 return 0;
708 }
709
710 usb_debug("Couldn't find closest USB2.0 hub.\n");
711 return 1;
712}