xref: /aosp_15_r20/external/coreboot/payloads/libpayload/drivers/usb/usb.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /*
2  *
3  * Copyright (C) 2008-2010 coresystems GmbH
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
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.
15  *
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
26  * SUCH DAMAGE.
27  */
28 
29 //#define USB_DEBUG
30 
31 #include <inttypes.h>
32 #include <libpayload-config.h>
33 #include <usb/usb.h>
34 
35 #define DR_DESC gen_bmRequestType(device_to_host, standard_type, dev_recp)
36 
37 hci_t *usb_hcs = 0;
38 
39 hci_t *
new_controller(void)40 new_controller(void)
41 {
42 	hci_t *controller = xzalloc(sizeof(hci_t));
43 	controller->next = usb_hcs;
44 	usb_hcs = controller;
45 	return controller;
46 }
47 
48 void
detach_controller(hci_t * controller)49 detach_controller(hci_t *controller)
50 {
51 	if (controller == NULL)
52 		return;
53 
54 	usb_detach_device(controller, 0);	/* tear down root hub tree */
55 
56 	if (usb_hcs == controller) {
57 		usb_hcs = controller->next;
58 	} else {
59 		hci_t *it = usb_hcs;
60 		while (it != NULL) {
61 			if (it->next == controller) {
62 				it->next = controller->next;
63 				return;
64 			}
65 			it = it->next;
66 		}
67 	}
68 }
69 
70 /**
71  * Shut down all controllers
72  */
73 int
usb_exit(void)74 usb_exit(void)
75 {
76 	while (usb_hcs != NULL) {
77 		usb_hcs->shutdown(usb_hcs);
78 	}
79 	return 0;
80 }
81 
82 /**
83  * Polls all hubs on all USB controllers, to find out about device changes
84  */
85 void
usb_poll(void)86 usb_poll(void)
87 {
88 	if (usb_hcs == 0)
89 		return;
90 
91 	if (usb_poll_prepare)
92 		usb_poll_prepare();
93 
94 	hci_t *controller = usb_hcs;
95 	while (controller != NULL) {
96 		int i;
97 		for (i = 0; i < 128; i++) {
98 			if (controller->devices[i] != 0) {
99 				controller->devices[i]->poll(controller->devices[i]);
100 			}
101 		}
102 		controller = controller->next;
103 	}
104 }
105 
106 usbdev_t *
init_device_entry(hci_t * controller,int i)107 init_device_entry(hci_t *controller, int i)
108 {
109 	usbdev_t *dev = calloc(1, sizeof(usbdev_t));
110 	if (!dev) {
111 		usb_debug("no memory to allocate device structure\n");
112 		return NULL;
113 	}
114 	if (controller->devices[i] != 0)
115 		usb_debug("warning: device %d reassigned?\n", i);
116 	controller->devices[i] = dev;
117 	dev->controller = controller;
118 	dev->address = -1;
119 	dev->hub = -1;
120 	dev->port = -1;
121 	dev->init = usb_nop_init;
122 	dev->init(controller->devices[i]);
123 	return dev;
124 }
125 
126 int
set_feature(usbdev_t * dev,int endp,int feature,int rtype)127 set_feature(usbdev_t *dev, int endp, int feature, int rtype)
128 {
129 	dev_req_t dr;
130 
131 	dr.bmRequestType = rtype;
132 	dr.data_dir = host_to_device;
133 	dr.bRequest = SET_FEATURE;
134 	dr.wValue = feature;
135 	dr.wIndex = endp;
136 	dr.wLength = 0;
137 
138 	return dev->controller->control(dev, OUT, sizeof(dr), &dr, 0, 0);
139 }
140 
141 int
get_status(usbdev_t * dev,int intf,int rtype,int len,void * data)142 get_status(usbdev_t *dev, int intf, int rtype, int len, void *data)
143 {
144 	dev_req_t dr;
145 
146 	dr.bmRequestType = rtype;
147 	dr.data_dir = device_to_host;
148 	dr.bRequest = GET_STATUS;
149 	dr.wValue = 0;
150 	dr.wIndex = intf;
151 	dr.wLength = len;
152 
153 	return dev->controller->control(dev, IN, sizeof(dr), &dr, len, data);
154 }
155 
156 /*
157  * Certain Lexar / Micron USB 2.0 disks will fail the get_descriptor(DT_CFG)
158  * call due to timing issues. Work around this by making extra attempts on
159  * failure.
160  */
161 #define GET_DESCRIPTOR_TRIES 3
162 
163 int
get_descriptor(usbdev_t * dev,int rtype,int desc_type,int desc_idx,void * data,size_t len)164 get_descriptor(usbdev_t *dev, int rtype, int desc_type, int desc_idx,
165 		void *data, size_t len)
166 {
167 	dev_req_t dr;
168 	int fail_tries = 0;
169 	int ret = 0;
170 
171 	while (fail_tries++ < GET_DESCRIPTOR_TRIES) {
172 		dr.bmRequestType = rtype;
173 		dr.bRequest = GET_DESCRIPTOR;
174 		dr.wValue = desc_type << 8 | desc_idx;
175 		dr.wIndex = 0;
176 		dr.wLength = len;
177 
178 		ret = dev->controller->control(dev, IN,
179 				sizeof(dr), &dr, len, data);
180 
181 		if (ret == len)
182 			break;
183 		udelay(10);
184 	}
185 	return ret;
186 }
187 
188 int
set_configuration(usbdev_t * dev)189 set_configuration(usbdev_t *dev)
190 {
191 	dev_req_t dr;
192 
193 	dr.bmRequestType = 0;
194 	dr.bRequest = SET_CONFIGURATION;
195 	dr.wValue = dev->configuration->bConfigurationValue;
196 	dr.wIndex = 0;
197 	dr.wLength = 0;
198 
199 	return dev->controller->control(dev, OUT, sizeof(dr), &dr, 0, 0);
200 }
201 
202 int
clear_feature(usbdev_t * dev,int endp,int feature,int rtype)203 clear_feature(usbdev_t *dev, int endp, int feature, int rtype)
204 {
205 	dev_req_t dr;
206 
207 	dr.bmRequestType = rtype;
208 	dr.data_dir = host_to_device;
209 	dr.bRequest = CLEAR_FEATURE;
210 	dr.wValue = feature;
211 	dr.wIndex = endp;
212 	dr.wLength = 0;
213 
214 	return dev->controller->control(dev, OUT, sizeof(dr), &dr, 0, 0) < 0;
215 }
216 
217 int
clear_stall(endpoint_t * ep)218 clear_stall(endpoint_t *ep)
219 {
220 	int ret = clear_feature(ep->dev, ep->endpoint, ENDPOINT_HALT,
221 		gen_bmRequestType(host_to_device, standard_type, endp_recp));
222 	ep->toggle = 0;
223 	return ret;
224 }
225 
226 /* returns free address or -1 */
227 static int
get_free_address(hci_t * controller)228 get_free_address(hci_t *controller)
229 {
230 	int i = controller->latest_address + 1;
231 	for (; i != controller->latest_address; i++) {
232 		if (i >= ARRAY_SIZE(controller->devices) || i < 1) {
233 			usb_debug("WARNING: Device addresses for controller %#" PRIxPTR
234 				  " wrapped around!\n", controller->reg_base);
235 			i = 0;
236 			continue;
237 		}
238 		if (controller->devices[i] == 0) {
239 			controller->latest_address = i;
240 			return i;
241 		}
242 	}
243 	usb_debug("no free address found\n");
244 	return -1;		// no free address
245 }
246 
247 int
usb_decode_mps0(usb_speed speed,u8 bMaxPacketSize0)248 usb_decode_mps0(usb_speed speed, u8 bMaxPacketSize0)
249 {
250 	switch (speed) {
251 	case LOW_SPEED:
252 		if (bMaxPacketSize0 != 8) {
253 			usb_debug("Invalid MPS0: 0x%02x\n", bMaxPacketSize0);
254 			bMaxPacketSize0 = 8;
255 		}
256 		return bMaxPacketSize0;
257 	case FULL_SPEED:
258 		switch (bMaxPacketSize0) {
259 		case 8: case 16: case 32: case 64:
260 			return bMaxPacketSize0;
261 		default:
262 			usb_debug("Invalid MPS0: 0x%02x\n", bMaxPacketSize0);
263 			return 8;
264 		}
265 	case HIGH_SPEED:
266 		if (bMaxPacketSize0 != 64) {
267 			usb_debug("Invalid MPS0: 0x%02x\n", bMaxPacketSize0);
268 			bMaxPacketSize0 = 64;
269 		}
270 		return bMaxPacketSize0;
271 	case SUPER_SPEED:
272 	/* Intentional fallthrough */
273 	case SUPER_SPEED_PLUS:
274 		if (bMaxPacketSize0 != 9) {
275 			usb_debug("Invalid MPS0: 0x%02x\n", bMaxPacketSize0);
276 			bMaxPacketSize0 = 9;
277 		}
278 		return 1 << bMaxPacketSize0;
279 	default:	/* GCC is stupid and cannot deal with enums correctly */
280 		return 8;
281 	}
282 }
283 
speed_to_default_mps(usb_speed speed)284 int speed_to_default_mps(usb_speed speed)
285 {
286 	switch (speed) {
287 	case LOW_SPEED:
288 		return 8;
289 	case FULL_SPEED:
290 	case HIGH_SPEED:
291 		return 64;
292 	case SUPER_SPEED:
293 	/* Intentional fallthrough */
294 	case SUPER_SPEED_PLUS:
295 	default:
296 		return 512;
297 	}
298 }
299 
300 /* Normalize bInterval to log2 of microframes */
301 static int
usb_decode_interval(usb_speed speed,const endpoint_type type,const unsigned char bInterval)302 usb_decode_interval(usb_speed speed, const endpoint_type type, const unsigned char bInterval)
303 {
304 #define LOG2(a) ((sizeof(unsigned) << 3) - __builtin_clz(a) - 1)
305 	switch (speed) {
306 	case LOW_SPEED:
307 		switch (type) {
308 		case ISOCHRONOUS: case INTERRUPT:
309 			return LOG2(bInterval) + 3;
310 		default:
311 			return 0;
312 		}
313 	case FULL_SPEED:
314 		switch (type) {
315 		case ISOCHRONOUS:
316 			return (bInterval - 1) + 3;
317 		case INTERRUPT:
318 			return LOG2(bInterval) + 3;
319 		default:
320 			return 0;
321 		}
322 	case HIGH_SPEED:
323 		switch (type) {
324 		case ISOCHRONOUS: case INTERRUPT:
325 			return bInterval - 1;
326 		default:
327 			return LOG2(bInterval);
328 		}
329 	case SUPER_SPEED:
330 	/* Intentional fallthrough */
331 	case SUPER_SPEED_PLUS:
332 		switch (type) {
333 		case ISOCHRONOUS: case INTERRUPT:
334 			return bInterval - 1;
335 		default:
336 			return 0;
337 		}
338 	default:
339 		return 0;
340 	}
341 #undef LOG2
342 }
343 
344 usbdev_t *
generic_set_address(hci_t * controller,usb_speed speed,int hubport,int hubaddr)345 generic_set_address(hci_t *controller, usb_speed speed,
346 		     int hubport, int hubaddr)
347 {
348 	int adr = get_free_address(controller);	// address to set
349 	if (adr < 0)
350 		return NULL;
351 	dev_req_t dr;
352 
353 	memset(&dr, 0, sizeof(dr));
354 	dr.data_dir = host_to_device;
355 	dr.req_type = standard_type;
356 	dr.req_recp = dev_recp;
357 	dr.bRequest = SET_ADDRESS;
358 	dr.wValue = adr;
359 	dr.wIndex = 0;
360 	dr.wLength = 0;
361 
362 	usbdev_t *dev = init_device_entry(controller, adr);
363 	if (!dev)
364 		return NULL;
365 
366 	// dummy values for registering the address
367 	dev->address = 0;
368 	dev->hub = hubaddr;
369 	dev->port = hubport;
370 	dev->speed = speed;
371 	dev->endpoints[0].dev = dev;
372 	dev->endpoints[0].endpoint = 0;
373 	dev->endpoints[0].maxpacketsize = 8;
374 	dev->endpoints[0].toggle = 0;
375 	dev->endpoints[0].direction = SETUP;
376 	dev->endpoints[0].type = CONTROL;
377 	if (dev->controller->control(dev, OUT, sizeof(dr), &dr, 0, 0) < 0) {
378 		usb_debug("set_address failed\n");
379 		usb_detach_device(controller, adr);
380 		return NULL;
381 	}
382 	mdelay(SET_ADDRESS_MDELAY);
383 
384 	u8 buf[8];
385 	dev->address = adr;
386 	if (get_descriptor(dev, DR_DESC, DT_DEV, 0, buf, sizeof(buf))
387 			!= sizeof(buf)) {
388 		usb_debug("first get_descriptor(DT_DEV) failed\n");
389 		usb_detach_device(controller, adr);
390 		return NULL;
391 	}
392 	dev->endpoints[0].maxpacketsize = usb_decode_mps0(speed, buf[7]);
393 
394 	return dev;
395 }
396 
397 static int
set_address(hci_t * controller,usb_speed speed,int hubport,int hubaddr)398 set_address(hci_t *controller, usb_speed speed, int hubport, int hubaddr)
399 {
400 	usbdev_t *dev = controller->set_address(controller, speed,
401 						hubport, hubaddr);
402 	if (!dev) {
403 		usb_debug("set_address failed\n");
404 		return -1;
405 	}
406 
407 	dev->descriptor = malloc(sizeof(*dev->descriptor));
408 	if (!dev->descriptor || get_descriptor(dev, DR_DESC, DT_DEV, 0,
409 			dev->descriptor, sizeof(*dev->descriptor))
410 			!= sizeof(*dev->descriptor)) {
411 		usb_debug("get_descriptor(DT_DEV) failed\n");
412 		usb_detach_device(controller, dev->address);
413 		return -1;
414 	}
415 
416 	usb_debug("* found device (0x%04x:0x%04x, USB %x.%x, MPS0: %d)\n",
417 		 dev->descriptor->idVendor, dev->descriptor->idProduct,
418 		 dev->descriptor->bcdUSB >> 8, dev->descriptor->bcdUSB & 0xff,
419 		 dev->endpoints[0].maxpacketsize);
420 	dev->quirks = usb_quirk_check(dev->descriptor->idVendor,
421 				      dev->descriptor->idProduct);
422 
423 	usb_debug("device has %d configurations\n",
424 		   dev->descriptor->bNumConfigurations);
425 	if (dev->descriptor->bNumConfigurations == 0) {
426 		/* device isn't usable */
427 		usb_debug("... no usable configuration!\n");
428 		usb_detach_device(controller, dev->address);
429 		return -1;
430 	}
431 
432 	u16 buf[2];
433 	if (get_descriptor(dev, DR_DESC, DT_CFG, 0, buf, sizeof(buf))
434 			!= sizeof(buf)) {
435 		usb_debug("first get_descriptor(DT_CFG) failed\n");
436 		usb_detach_device(controller, dev->address);
437 		return -1;
438 	}
439 	/* workaround for some USB devices: wait until they're ready, or
440 	 * they send a NAK when they're not allowed to do. 1ms is enough */
441 	mdelay(1);
442 	dev->configuration = malloc(buf[1]);
443 	if (!dev->configuration) {
444 		usb_debug("could not allocate %d bytes for DT_CFG\n", buf[1]);
445 		usb_detach_device(controller, dev->address);
446 		return -1;
447 	}
448 	if (get_descriptor(dev, DR_DESC, DT_CFG, 0, dev->configuration,
449 			    buf[1]) != buf[1]) {
450 		usb_debug("get_descriptor(DT_CFG) failed\n");
451 		usb_detach_device(controller, dev->address);
452 		return -1;
453 	}
454 	configuration_descriptor_t *cd = dev->configuration;
455 	if (cd->wTotalLength != buf[1]) {
456 		usb_debug("configuration descriptor size changed, aborting\n");
457 		usb_detach_device(controller, dev->address);
458 		return -1;
459 	}
460 
461 	/*
462 	 * If the device is not well known (ifnum == -1), we use the first
463 	 * interface we encounter, as there was no need to implement something
464 	 * else for the time being. If you need it, see the SetInterface and
465 	 * GetInterface functions in the USB specification and set it yourself.
466 	 */
467 	usb_debug("device has %x interfaces\n", cd->bNumInterfaces);
468 	int ifnum = usb_interface_check(dev->descriptor->idVendor,
469 					dev->descriptor->idProduct);
470 	if (cd->bNumInterfaces > 1 && ifnum < 0)
471 		usb_debug("NOTICE: Your device has multiple interfaces and\n"
472 			   "this driver will only use the first one. That may\n"
473 			   "be the wrong choice and cause the device to not\n"
474 			   "work correctly. Please report this case\n"
475 			   "(including the above debugging output) to\n"
476 			   "[email protected] to have the device added to\n"
477 			   "the list of well-known quirks.\n");
478 
479 	u8 *end = (void *)dev->configuration + cd->wTotalLength;
480 	interface_descriptor_t *intf;
481 	u8 *ptr;
482 
483 	/* Find our interface (or the first good one if we don't know) */
484 	for (ptr = (void *)dev->configuration + sizeof(*cd); ; ptr += ptr[0]) {
485 		if (ptr + 2 > end || !ptr[0] || ptr + ptr[0] > end) {
486 			usb_debug("Couldn't find usable DT_INTF\n");
487 			usb_detach_device(controller, dev->address);
488 			return -1;
489 		}
490 		if (ptr[1] != DT_INTF)
491 			continue;
492 		intf = (void *)ptr;
493 		if (intf->bLength != sizeof(*intf)) {
494 			usb_debug("Skipping broken DT_INTF\n");
495 			continue;
496 		}
497 		if (ifnum >= 0 && intf->bInterfaceNumber != ifnum)
498 			continue;
499 		usb_debug("Interface %d: class 0x%x, sub 0x%x. proto 0x%x\n",
500 			intf->bInterfaceNumber, intf->bInterfaceClass,
501 			intf->bInterfaceSubClass, intf->bInterfaceProtocol);
502 		ptr += sizeof(*intf);
503 		break;
504 	}
505 
506 	/* Gather up all endpoints belonging to this interface */
507 	dev->num_endp = 1;
508 	for (; ptr + 2 <= end && ptr[0] && ptr + ptr[0] <= end; ptr += ptr[0]) {
509 		if (ptr[1] == DT_INTF || ptr[1] == DT_CFG ||
510 				dev->num_endp >= ARRAY_SIZE(dev->endpoints))
511 			break;
512 		if (ptr[1] != DT_ENDP)
513 			continue;
514 
515 		endpoint_descriptor_t *desc = (void *)ptr;
516 		static const char *transfertypes[4] = {
517 			"control", "isochronous", "bulk", "interrupt"
518 		};
519 		usb_debug(" #Endpoint %d (%s), max packet size %x, type %s\n",
520 			desc->bEndpointAddress & 0x7f,
521 			(desc->bEndpointAddress & 0x80) ? "in" : "out",
522 			desc->wMaxPacketSize,
523 			transfertypes[desc->bmAttributes & 0x3]);
524 
525 		endpoint_t *ep = &dev->endpoints[dev->num_endp++];
526 		ep->dev = dev;
527 		ep->endpoint = desc->bEndpointAddress;
528 		ep->toggle = 0;
529 		ep->maxpacketsize = desc->wMaxPacketSize;
530 		ep->direction = (desc->bEndpointAddress & 0x80) ? IN : OUT;
531 		ep->type = desc->bmAttributes & 0x3;
532 		ep->interval = usb_decode_interval(dev->speed, ep->type,
533 						    desc->bInterval);
534 	}
535 
536 	if ((controller->finish_device_config &&
537 			controller->finish_device_config(dev)) ||
538 			set_configuration(dev) < 0) {
539 		usb_debug("Could not finalize device configuration\n");
540 		usb_detach_device(controller, dev->address);
541 		return -1;
542 	}
543 
544 	int class = dev->descriptor->bDeviceClass;
545 	if (class == 0)
546 		class = intf->bInterfaceClass;
547 
548 	enum {
549 		audio_device      = 0x01,
550 		comm_device       = 0x02,
551 		hid_device        = 0x03,
552 		physical_device   = 0x05,
553 		imaging_device    = 0x06,
554 		printer_device    = 0x07,
555 		msc_device        = 0x08,
556 		hub_device        = 0x09,
557 		cdc_device        = 0x0a,
558 		ccid_device       = 0x0b,
559 		security_device   = 0x0d,
560 		video_device      = 0x0e,
561 		healthcare_device = 0x0f,
562 		diagnostic_device = 0xdc,
563 		wireless_device   = 0xe0,
564 		misc_device       = 0xef,
565 	};
566 	usb_debug("Class: ");
567 	switch (class) {
568 	case audio_device:
569 		usb_debug("audio\n");
570 		break;
571 	case comm_device:
572 		usb_debug("communication\n");
573 		break;
574 	case hid_device:
575 		usb_debug("HID\n");
576 #if CONFIG(LP_USB_HID)
577 		dev->init = usb_hid_init;
578 		return dev->address;
579 #else
580 		usb_debug("NOTICE: USB HID support not compiled in\n");
581 #endif
582 		break;
583 	case physical_device:
584 		usb_debug("physical\n");
585 		break;
586 	case imaging_device:
587 		usb_debug("camera\n");
588 		break;
589 	case printer_device:
590 		usb_debug("printer\n");
591 		break;
592 	case msc_device:
593 		usb_debug("MSC\n");
594 #if CONFIG(LP_USB_MSC)
595 		dev->init = usb_msc_init;
596 		return dev->address;
597 #else
598 		usb_debug("NOTICE: USB MSC support not compiled in\n");
599 #endif
600 		break;
601 	case hub_device:
602 		usb_debug("hub\n");
603 #if CONFIG(LP_USB_HUB)
604 		dev->init = usb_hub_init;
605 		return dev->address;
606 #else
607 		usb_debug("NOTICE: USB hub support not compiled in\n");
608 #endif
609 		break;
610 	case cdc_device:
611 		usb_debug("CDC\n");
612 		break;
613 	case ccid_device:
614 		usb_debug("smartcard / CCID\n");
615 		break;
616 	case security_device:
617 		usb_debug("content security\n");
618 		break;
619 	case video_device:
620 		usb_debug("video\n");
621 		break;
622 	case healthcare_device:
623 		usb_debug("healthcare\n");
624 		break;
625 	case diagnostic_device:
626 		usb_debug("diagnostic\n");
627 		break;
628 	case wireless_device:
629 		usb_debug("wireless\n");
630 		break;
631 	default:
632 		usb_debug("unsupported class %x\n", class);
633 		break;
634 	}
635 	dev->init = usb_generic_init;
636 	return dev->address;
637 }
638 
639 /*
640  * Should be called by the hub drivers whenever a physical detach occurs
641  * and can be called by USB class drivers if they are unsatisfied with a
642  * malfunctioning device.
643  */
644 void
usb_detach_device(hci_t * controller,int devno)645 usb_detach_device(hci_t *controller, int devno)
646 {
647 	/* check if device exists, as we may have
648 	   been called yet by the USB class driver */
649 	if (controller->devices[devno]) {
650 		controller->devices[devno]->destroy(controller->devices[devno]);
651 
652 		if (controller->destroy_device)
653 			controller->destroy_device(controller, devno);
654 
655 		free(controller->devices[devno]->descriptor);
656 		controller->devices[devno]->descriptor = NULL;
657 		free(controller->devices[devno]->configuration);
658 		controller->devices[devno]->configuration = NULL;
659 
660 		/* Tear down the device itself *after* destroy_device()
661 		 * has had a chance to interrogate it. */
662 		free(controller->devices[devno]);
663 		controller->devices[devno] = NULL;
664 	}
665 }
666 
667 int
usb_attach_device(hci_t * controller,int hubaddress,int port,usb_speed speed)668 usb_attach_device(hci_t *controller, int hubaddress, int port, usb_speed speed)
669 {
670 	static const char *speeds[] = { "full", "low", "high", "super", "ultra" };
671 	usb_debug("%sspeed device\n", (speed < sizeof(speeds) / sizeof(char*))
672 		? speeds[speed] : "invalid value - no");
673 	int newdev = set_address(controller, speed, port, hubaddress);
674 	if (newdev == -1)
675 		return -1;
676 	usbdev_t *newdev_t = controller->devices[newdev];
677 	// determine responsible driver - current done in set_address
678 	newdev_t->init(newdev_t);
679 	/* init() may have called usb_detach_device() yet, so check */
680 	return controller->devices[newdev] ? newdev : -1;
681 }
682 
683 static void
usb_generic_destroy(usbdev_t * dev)684 usb_generic_destroy(usbdev_t *dev)
685 {
686 	if (usb_generic_remove)
687 		usb_generic_remove(dev);
688 }
689 
690 void
usb_generic_init(usbdev_t * dev)691 usb_generic_init(usbdev_t *dev)
692 {
693 	dev->data = NULL;
694 	dev->destroy = usb_generic_destroy;
695 
696 	if (usb_generic_create)
697 		usb_generic_create(dev);
698 
699 	if (dev->data == NULL) {
700 		usb_debug("Detaching device not used by payload\n");
701 		usb_detach_device(dev->controller, dev->address);
702 	}
703 }
704 
705 /*
706  * returns the speed is above SUPER_SPEED or not
707  */
is_usb_speed_ss(usb_speed speed)708 _Bool is_usb_speed_ss(usb_speed speed)
709 {
710 	return (speed == SUPER_SPEED || speed == SUPER_SPEED_PLUS);
711 }
712 
713 /*
714  * returns the address of the closest USB2.0 hub, which is responsible for
715  * split transactions, along with the number of the used downstream port
716  */
closest_usb2_hub(const usbdev_t * dev,int * const addr,int * const port)717 int closest_usb2_hub(const usbdev_t *dev, int *const addr, int *const port)
718 {
719 	const usbdev_t *usb1dev;
720 
721 	do {
722 		usb1dev = dev;
723 		if ((dev->hub >= 0) && (dev->hub < 128))
724 			dev = dev->controller->devices[dev->hub];
725 		else
726 			dev = NULL;
727 	} while (dev && (dev->speed < 2));
728 
729 	if (dev) {
730 		*addr = usb1dev->hub;
731 		*port = usb1dev->port;
732 		return 0;
733 	}
734 
735 	usb_debug("Couldn't find closest USB2.0 hub.\n");
736 	return 1;
737 }
738