Rename sprintf -> ksprintf
[dfdiff.git] / sys / bus / usb / usb_subr.c
blobbe96c13882cf39d866fe957d153e588d664d9bdf
1 /* $NetBSD: usb_subr.c,v 1.99 2002/07/11 21:14:34 augustss Exp $ */
2 /* $FreeBSD: src/sys/dev/usb/usb_subr.c,v 1.76.2.3 2006/03/01 01:59:05 iedowse Exp $ */
3 /* $DragonFly: src/sys/bus/usb/usb_subr.c,v 1.16 2006/12/20 18:14:37 dillon Exp $ */
5 /* Also already have from NetBSD:
6 * $NetBSD: usb_subr.c,v 1.102 2003/01/01 16:21:50 augustss Exp $
7 * $NetBSD: usb_subr.c,v 1.103 2003/01/10 11:19:13 augustss Exp $
8 * $NetBSD: usb_subr.c,v 1.111 2004/03/15 10:35:04 augustss Exp $
9 * $NetBSD: usb_subr.c,v 1.114 2004/06/23 02:30:52 mycroft Exp $
10 * $NetBSD: usb_subr.c,v 1.115 2004/06/23 05:23:19 mycroft Exp $
11 * $NetBSD: usb_subr.c,v 1.116 2004/06/23 06:27:54 mycroft Exp $
12 * $NetBSD: usb_subr.c,v 1.119 2004/10/23 13:26:33 augustss Exp $
16 * Copyright (c) 1998 The NetBSD Foundation, Inc.
17 * All rights reserved.
19 * This code is derived from software contributed to The NetBSD Foundation
20 * by Lennart Augustsson (lennart@augustsson.net) at
21 * Carlstedt Research & Technology.
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions
25 * are met:
26 * 1. Redistributions of source code must retain the above copyright
27 * notice, this list of conditions and the following disclaimer.
28 * 2. Redistributions in binary form must reproduce the above copyright
29 * notice, this list of conditions and the following disclaimer in the
30 * documentation and/or other materials provided with the distribution.
31 * 3. All advertising materials mentioning features or use of this software
32 * must display the following acknowledgement:
33 * This product includes software developed by the NetBSD
34 * Foundation, Inc. and its contributors.
35 * 4. Neither the name of The NetBSD Foundation nor the names of its
36 * contributors may be used to endorse or promote products derived
37 * from this software without specific prior written permission.
39 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
40 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
41 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
43 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
44 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
45 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
46 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
47 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
49 * POSSIBILITY OF SUCH DAMAGE.
52 #include "opt_usb.h"
54 #include <sys/param.h>
55 #include <sys/systm.h>
56 #include <sys/kernel.h>
57 #include <sys/malloc.h>
58 #include <sys/module.h>
59 #include <sys/bus.h>
60 #include <sys/proc.h>
62 #include <bus/usb/usb.h>
64 #include <bus/usb/usbdi.h>
65 #include <bus/usb/usbdi_util.h>
66 #include <bus/usb/usbdivar.h>
67 #include "usbdevs.h"
68 #include <bus/usb/usb_quirks.h>
70 #if defined(__FreeBSD__) || defined(__DragonFly__)
71 #define delay(d) DELAY(d)
72 #endif
74 #ifdef USB_DEBUG
75 #define DPRINTF(x) if (usbdebug) logprintf x
76 #define DPRINTFN(n,x) if (usbdebug>(n)) logprintf x
77 extern int usbdebug;
78 #else
79 #define DPRINTF(x)
80 #define DPRINTFN(n,x)
81 #endif
83 Static usbd_status usbd_set_config(usbd_device_handle, int);
84 Static void usbd_devinfo_vp(usbd_device_handle, char *, char *, int);
85 Static int usbd_getnewaddr(usbd_bus_handle bus);
86 #if defined(__NetBSD__)
87 Static int usbd_print(void *aux, const char *pnp);
88 Static int usbd_submatch(device_ptr_t, struct cfdata *cf, void *);
89 #elif defined(__OpenBSD__)
90 Static int usbd_print(void *aux, const char *pnp);
91 Static int usbd_submatch(device_ptr_t, void *, void *);
92 #endif
93 Static void usbd_free_iface_data(usbd_device_handle dev, int ifcno);
94 Static void usbd_kill_pipe(usbd_pipe_handle);
95 Static usbd_status usbd_probe_and_attach(device_ptr_t parent,
96 usbd_device_handle dev, int port, int addr);
98 Static u_int32_t usb_cookie_no = 0;
100 #ifdef USBVERBOSE
101 typedef u_int16_t usb_vendor_id_t;
102 typedef u_int16_t usb_product_id_t;
105 * Descriptions of of known vendors and devices ("products").
107 struct usb_knowndev {
108 usb_vendor_id_t vendor;
109 usb_product_id_t product;
110 int flags;
111 char *vendorname, *productname;
113 #define USB_KNOWNDEV_NOPROD 0x01 /* match on vendor only */
115 #include "usbdevs_data.h"
116 #endif /* USBVERBOSE */
118 Static const char * const usbd_error_strs[] = {
119 "NORMAL_COMPLETION",
120 "IN_PROGRESS",
121 "PENDING_REQUESTS",
122 "NOT_STARTED",
123 "INVAL",
124 "NOMEM",
125 "CANCELLED",
126 "BAD_ADDRESS",
127 "IN_USE",
128 "NO_ADDR",
129 "SET_ADDR_FAILED",
130 "NO_POWER",
131 "TOO_DEEP",
132 "IOERROR",
133 "NOT_CONFIGURED",
134 "TIMEOUT",
135 "SHORT_XFER",
136 "STALLED",
137 "INTERRUPTED",
138 "XXX",
141 const char *
142 usbd_errstr(usbd_status err)
144 static char buffer[5];
146 if (err < USBD_ERROR_MAX) {
147 return usbd_error_strs[err];
148 } else {
149 ksnprintf(buffer, sizeof buffer, "%d", err);
150 return buffer;
154 usbd_status
155 usbd_get_string_desc(usbd_device_handle dev, int sindex, int langid,
156 usb_string_descriptor_t *sdesc, int *sizep)
158 usb_device_request_t req;
159 usbd_status err;
160 int actlen;
162 req.bmRequestType = UT_READ_DEVICE;
163 req.bRequest = UR_GET_DESCRIPTOR;
164 USETW2(req.wValue, UDESC_STRING, sindex);
165 USETW(req.wIndex, langid);
166 USETW(req.wLength, 2); /* only size byte first */
167 err = usbd_do_request_flags(dev, &req, sdesc, USBD_SHORT_XFER_OK,
168 &actlen, USBD_DEFAULT_TIMEOUT);
169 if (err)
170 return (err);
172 if (actlen < 2)
173 return (USBD_SHORT_XFER);
175 USETW(req.wLength, sdesc->bLength); /* the whole string */
176 err = usbd_do_request_flags(dev, &req, sdesc, USBD_SHORT_XFER_OK,
177 &actlen, USBD_DEFAULT_TIMEOUT);
178 if (err)
179 return (err);
181 if (actlen != sdesc->bLength) {
182 DPRINTFN(-1, ("usbd_get_string_desc: expected %d, got %d\n",
183 sdesc->bLength, actlen));
186 *sizep = actlen;
187 return (USBD_NORMAL_COMPLETION);
190 Static void
191 usbd_trim_spaces(char *p)
193 char *q, *e;
195 if (p == NULL)
196 return;
197 q = e = p;
198 while (*q == ' ') /* skip leading spaces */
199 q++;
200 while ((*p = *q++)) /* copy string */
201 if (*p++ != ' ') /* remember last non-space */
202 e = p;
203 *e = 0; /* kill trailing spaces */
206 Static void
207 usbd_devinfo_vp(usbd_device_handle dev, char *v, char *p, int usedev)
209 usb_device_descriptor_t *udd = &dev->ddesc;
210 char *vendor = 0, *product = 0;
211 #ifdef USBVERBOSE
212 const struct usb_knowndev *kdp;
213 #endif
215 if (dev == NULL) {
216 v[0] = p[0] = '\0';
217 return;
220 if (usedev) {
221 if (usbd_get_string(dev, udd->iManufacturer, v))
222 vendor = NULL;
223 else
224 vendor = v;
225 usbd_trim_spaces(vendor);
226 if (usbd_get_string(dev, udd->iProduct, p))
227 product = NULL;
228 else
229 product = p;
230 usbd_trim_spaces(product);
231 if (vendor && !*vendor)
232 vendor = NULL;
233 if (product && !*product)
234 product = NULL;
235 } else {
236 vendor = NULL;
237 product = NULL;
239 #ifdef USBVERBOSE
240 if (vendor == NULL || product == NULL) {
241 for(kdp = usb_knowndevs;
242 kdp->vendorname != NULL;
243 kdp++) {
244 if (kdp->vendor == UGETW(udd->idVendor) &&
245 (kdp->product == UGETW(udd->idProduct) ||
246 (kdp->flags & USB_KNOWNDEV_NOPROD) != 0))
247 break;
249 if (kdp->vendorname != NULL) {
250 if (vendor == NULL)
251 vendor = kdp->vendorname;
252 if (product == NULL)
253 product = (kdp->flags & USB_KNOWNDEV_NOPROD) == 0 ?
254 kdp->productname : NULL;
257 #endif
258 if (vendor != NULL && *vendor)
259 strcpy(v, vendor);
260 else
261 ksprintf(v, "vendor 0x%04x", UGETW(udd->idVendor));
262 if (product != NULL && *product)
263 strcpy(p, product);
264 else
265 ksprintf(p, "product 0x%04x", UGETW(udd->idProduct));
269 usbd_printBCD(char *cp, int bcd)
271 return (ksprintf(cp, "%x.%02x", bcd >> 8, bcd & 0xff));
274 void
275 usbd_devinfo(usbd_device_handle dev, int showclass, char *cp)
277 usb_device_descriptor_t *udd = &dev->ddesc;
278 usbd_interface_handle iface;
279 char vendor[USB_MAX_STRING_LEN];
280 char product[USB_MAX_STRING_LEN];
281 int bcdDevice, bcdUSB;
282 usb_interface_descriptor_t *id;
284 usbd_devinfo_vp(dev, vendor, product, 1);
285 cp += ksprintf(cp, "%s %s", vendor, product);
286 if (showclass & USBD_SHOW_DEVICE_CLASS)
287 cp += ksprintf(cp, ", class %d/%d",
288 udd->bDeviceClass, udd->bDeviceSubClass);
289 bcdUSB = UGETW(udd->bcdUSB);
290 bcdDevice = UGETW(udd->bcdDevice);
291 cp += ksprintf(cp, ", rev ");
292 cp += usbd_printBCD(cp, bcdUSB);
293 *cp++ = '/';
294 cp += usbd_printBCD(cp, bcdDevice);
295 cp += ksprintf(cp, ", addr %d", dev->address);
296 if (showclass & USBD_SHOW_INTERFACE_CLASS)
298 /* fetch the interface handle for the first interface */
299 (void)usbd_device2interface_handle(dev, 0, &iface);
300 id = usbd_get_interface_descriptor(iface);
301 cp += ksprintf(cp, ", iclass %d/%d",
302 id->bInterfaceClass, id->bInterfaceSubClass);
304 *cp = 0;
307 /* Delay for a certain number of ms */
308 void
309 usb_delay_ms(usbd_bus_handle bus, u_int ms)
311 /* Wait at least two clock ticks so we know the time has passed. */
312 if (bus->use_polling || cold)
313 delay((ms+1) * 1000);
314 else
315 tsleep(&ms, 0, "usbdly", (ms*hz+999)/1000 + 1);
318 /* Delay given a device handle. */
319 void
320 usbd_delay_ms(usbd_device_handle dev, u_int ms)
322 usb_delay_ms(dev->bus, ms);
325 usbd_status
326 usbd_reset_port(usbd_device_handle dev, int port, usb_port_status_t *ps)
328 usb_device_request_t req;
329 usbd_status err;
330 int n;
332 req.bmRequestType = UT_WRITE_CLASS_OTHER;
333 req.bRequest = UR_SET_FEATURE;
334 USETW(req.wValue, UHF_PORT_RESET);
335 USETW(req.wIndex, port);
336 USETW(req.wLength, 0);
337 err = usbd_do_request(dev, &req, 0);
338 DPRINTFN(1,("usbd_reset_port: port %d reset done, error=%s\n",
339 port, usbd_errstr(err)));
340 if (err)
341 return (err);
342 n = 10;
343 do {
344 /* Wait for device to recover from reset. */
345 usbd_delay_ms(dev, USB_PORT_RESET_DELAY);
346 err = usbd_get_port_status(dev, port, ps);
347 if (err) {
348 DPRINTF(("usbd_reset_port: get status failed %d\n",
349 err));
350 return (err);
352 /* If the device disappeared, just give up. */
353 if (!(UGETW(ps->wPortStatus) & UPS_CURRENT_CONNECT_STATUS))
354 return (USBD_NORMAL_COMPLETION);
355 } while ((UGETW(ps->wPortChange) & UPS_C_PORT_RESET) == 0 && --n > 0);
356 if (n == 0)
357 return (USBD_TIMEOUT);
358 err = usbd_clear_port_feature(dev, port, UHF_C_PORT_RESET);
359 #ifdef USB_DEBUG
360 if (err)
361 DPRINTF(("usbd_reset_port: clear port feature failed %d\n",
362 err));
363 #endif
365 /* Wait for the device to recover from reset. */
366 usbd_delay_ms(dev, USB_PORT_RESET_RECOVERY);
367 return (err);
370 usb_interface_descriptor_t *
371 usbd_find_idesc(usb_config_descriptor_t *cd, int ifaceidx, int altidx)
373 char *p = (char *)cd;
374 char *end = p + UGETW(cd->wTotalLength);
375 usb_interface_descriptor_t *d;
376 int curidx, lastidx, curaidx = 0;
378 for (curidx = lastidx = -1; p < end; ) {
379 d = (usb_interface_descriptor_t *)p;
380 DPRINTFN(4,("usbd_find_idesc: idx=%d(%d) altidx=%d(%d) len=%d "
381 "type=%d\n",
382 ifaceidx, curidx, altidx, curaidx,
383 d->bLength, d->bDescriptorType));
384 if (d->bLength == 0) /* bad descriptor */
385 break;
386 p += d->bLength;
387 if (p <= end && d->bDescriptorType == UDESC_INTERFACE) {
388 if (d->bInterfaceNumber != lastidx) {
389 lastidx = d->bInterfaceNumber;
390 curidx++;
391 curaidx = 0;
392 } else
393 curaidx++;
394 if (ifaceidx == curidx && altidx == curaidx)
395 return (d);
398 return (NULL);
401 usb_endpoint_descriptor_t *
402 usbd_find_edesc(usb_config_descriptor_t *cd, int ifaceidx, int altidx,
403 int endptidx)
405 char *p = (char *)cd;
406 char *end = p + UGETW(cd->wTotalLength);
407 usb_interface_descriptor_t *d;
408 usb_endpoint_descriptor_t *e;
409 int curidx;
411 d = usbd_find_idesc(cd, ifaceidx, altidx);
412 if (d == NULL)
413 return (NULL);
414 if (endptidx >= d->bNumEndpoints) /* quick exit */
415 return (NULL);
417 curidx = -1;
418 for (p = (char *)d + d->bLength; p < end; ) {
419 e = (usb_endpoint_descriptor_t *)p;
420 if (e->bLength == 0) /* bad descriptor */
421 break;
422 p += e->bLength;
423 if (p <= end && e->bDescriptorType == UDESC_INTERFACE)
424 return (NULL);
425 if (p <= end && e->bDescriptorType == UDESC_ENDPOINT) {
426 curidx++;
427 if (curidx == endptidx)
428 return (e);
431 return (NULL);
434 usbd_status
435 usbd_fill_iface_data(usbd_device_handle dev, int ifaceidx, int altidx)
437 usbd_interface_handle ifc = &dev->ifaces[ifaceidx];
438 usb_interface_descriptor_t *idesc;
439 char *p, *end;
440 int endpt, nendpt;
442 DPRINTFN(4,("usbd_fill_iface_data: ifaceidx=%d altidx=%d\n",
443 ifaceidx, altidx));
444 idesc = usbd_find_idesc(dev->cdesc, ifaceidx, altidx);
445 if (idesc == NULL)
446 return (USBD_INVAL);
447 ifc->device = dev;
448 ifc->idesc = idesc;
449 ifc->index = ifaceidx;
450 ifc->altindex = altidx;
451 nendpt = ifc->idesc->bNumEndpoints;
452 DPRINTFN(4,("usbd_fill_iface_data: found idesc nendpt=%d\n", nendpt));
453 if (nendpt != 0) {
454 ifc->endpoints = kmalloc(nendpt * sizeof(struct usbd_endpoint),
455 M_USB, M_INTWAIT);
456 } else {
457 ifc->endpoints = NULL;
459 ifc->priv = NULL;
460 p = (char *)ifc->idesc + ifc->idesc->bLength;
461 end = (char *)dev->cdesc + UGETW(dev->cdesc->wTotalLength);
462 #define ed ((usb_endpoint_descriptor_t *)p)
463 for (endpt = 0; endpt < nendpt; endpt++) {
464 DPRINTFN(10,("usbd_fill_iface_data: endpt=%d\n", endpt));
465 for (; p < end; p += ed->bLength) {
466 DPRINTFN(10,("usbd_fill_iface_data: p=%p end=%p "
467 "len=%d type=%d\n",
468 p, end, ed->bLength, ed->bDescriptorType));
469 if (p + ed->bLength <= end && ed->bLength != 0 &&
470 ed->bDescriptorType == UDESC_ENDPOINT)
471 goto found;
472 if (ed->bLength == 0 ||
473 ed->bDescriptorType == UDESC_INTERFACE)
474 break;
476 /* passed end, or bad desc */
477 printf("usbd_fill_iface_data: bad descriptor(s): %s\n",
478 ed->bLength == 0 ? "0 length" :
479 ed->bDescriptorType == UDESC_INTERFACE ? "iface desc":
480 "out of data");
481 goto bad;
482 found:
483 ifc->endpoints[endpt].edesc = ed;
484 if (dev->speed == USB_SPEED_HIGH) {
485 u_int mps;
486 /* Control and bulk endpoints have max packet limits. */
487 switch (UE_GET_XFERTYPE(ed->bmAttributes)) {
488 case UE_CONTROL:
489 mps = USB_2_MAX_CTRL_PACKET;
490 goto check;
491 case UE_BULK:
492 mps = USB_2_MAX_BULK_PACKET;
493 check:
494 if (UGETW(ed->wMaxPacketSize) != mps) {
495 USETW(ed->wMaxPacketSize, mps);
496 #ifdef DIAGNOSTIC
497 printf("usbd_fill_iface_data: bad max "
498 "packet size\n");
499 #endif
501 break;
502 default:
503 break;
506 ifc->endpoints[endpt].refcnt = 0;
507 ifc->endpoints[endpt].savedtoggle = 0;
508 p += ed->bLength;
510 #undef ed
511 LIST_INIT(&ifc->pipes);
512 return (USBD_NORMAL_COMPLETION);
514 bad:
515 if (ifc->endpoints != NULL) {
516 kfree(ifc->endpoints, M_USB);
517 ifc->endpoints = NULL;
519 return (USBD_INVAL);
522 void
523 usbd_free_iface_data(usbd_device_handle dev, int ifcno)
525 usbd_interface_handle ifc = &dev->ifaces[ifcno];
526 if (ifc->endpoints)
527 kfree(ifc->endpoints, M_USB);
530 Static usbd_status
531 usbd_set_config(usbd_device_handle dev, int conf)
533 usb_device_request_t req;
535 req.bmRequestType = UT_WRITE_DEVICE;
536 req.bRequest = UR_SET_CONFIG;
537 USETW(req.wValue, conf);
538 USETW(req.wIndex, 0);
539 USETW(req.wLength, 0);
540 return (usbd_do_request(dev, &req, 0));
543 usbd_status
544 usbd_set_config_no(usbd_device_handle dev, int no, int msg)
546 int index;
547 usb_config_descriptor_t cd;
548 usbd_status err;
550 if (no == USB_UNCONFIG_NO)
551 return (usbd_set_config_index(dev, USB_UNCONFIG_INDEX, msg));
553 DPRINTFN(5,("usbd_set_config_no: %d\n", no));
554 /* Figure out what config index to use. */
555 for (index = 0; index < dev->ddesc.bNumConfigurations; index++) {
556 err = usbd_get_config_desc(dev, index, &cd);
557 if (err)
558 return (err);
559 if (cd.bConfigurationValue == no)
560 return (usbd_set_config_index(dev, index, msg));
562 return (USBD_INVAL);
565 usbd_status
566 usbd_set_config_index(usbd_device_handle dev, int index, int msg)
568 usb_status_t ds;
569 usb_config_descriptor_t cd, *cdp;
570 usbd_status err;
571 int i, ifcidx, nifc, len, selfpowered, power;
573 DPRINTFN(5,("usbd_set_config_index: dev=%p index=%d\n", dev, index));
575 if (dev->config != USB_UNCONFIG_NO) {
576 nifc = dev->cdesc->bNumInterface;
578 /* Check that all interfaces are idle */
579 for (ifcidx = 0; ifcidx < nifc; ifcidx++) {
580 if (LIST_EMPTY(&dev->ifaces[ifcidx].pipes))
581 continue;
582 DPRINTF(("usbd_set_config_index: open pipes exist\n"));
583 return (USBD_IN_USE);
586 DPRINTF(("usbd_set_config_index: free old config\n"));
587 /* Free all configuration data structures. */
588 for (ifcidx = 0; ifcidx < nifc; ifcidx++)
589 usbd_free_iface_data(dev, ifcidx);
590 kfree(dev->ifaces, M_USB);
591 kfree(dev->cdesc, M_USB);
592 dev->ifaces = NULL;
593 dev->cdesc = NULL;
594 dev->config = USB_UNCONFIG_NO;
597 if (index == USB_UNCONFIG_INDEX) {
598 /* We are unconfiguring the device, so leave unallocated. */
599 DPRINTF(("usbd_set_config_index: set config 0\n"));
600 err = usbd_set_config(dev, USB_UNCONFIG_NO);
601 if (err)
602 DPRINTF(("usbd_set_config_index: setting config=0 "
603 "failed, error=%s\n", usbd_errstr(err)));
604 return (err);
607 /* Get the short descriptor. */
608 err = usbd_get_config_desc(dev, index, &cd);
609 if (err)
610 return (err);
611 len = UGETW(cd.wTotalLength);
612 cdp = kmalloc(len, M_USB, M_INTWAIT);
613 /* Get the full descriptor. Try a few times for slow devices. */
614 for (i = 0; i < 3; i++) {
615 err = usbd_get_desc(dev, UDESC_CONFIG, index, len, cdp);
616 if (!err)
617 break;
618 usbd_delay_ms(dev, 200);
620 if (err)
621 goto bad;
622 if (cdp->bDescriptorType != UDESC_CONFIG) {
623 DPRINTFN(-1,("usbd_set_config_index: bad desc %d\n",
624 cdp->bDescriptorType));
625 err = USBD_INVAL;
626 goto bad;
629 /* Figure out if the device is self or bus powered. */
630 selfpowered = 0;
631 if (!(dev->quirks->uq_flags & UQ_BUS_POWERED) &&
632 (cdp->bmAttributes & UC_SELF_POWERED)) {
633 /* May be self powered. */
634 if (cdp->bmAttributes & UC_BUS_POWERED) {
635 /* Must ask device. */
636 if (dev->quirks->uq_flags & UQ_POWER_CLAIM) {
638 * Hub claims to be self powered, but isn't.
639 * It seems that the power status can be
640 * determined by the hub characteristics.
642 usb_hub_descriptor_t hd;
643 usb_device_request_t req;
644 req.bmRequestType = UT_READ_CLASS_DEVICE;
645 req.bRequest = UR_GET_DESCRIPTOR;
646 USETW(req.wValue, 0);
647 USETW(req.wIndex, 0);
648 USETW(req.wLength, USB_HUB_DESCRIPTOR_SIZE);
649 err = usbd_do_request(dev, &req, &hd);
650 if (!err &&
651 (UGETW(hd.wHubCharacteristics) &
652 UHD_PWR_INDIVIDUAL))
653 selfpowered = 1;
654 DPRINTF(("usbd_set_config_index: charac=0x%04x"
655 ", error=%s\n",
656 UGETW(hd.wHubCharacteristics),
657 usbd_errstr(err)));
658 } else {
659 err = usbd_get_device_status(dev, &ds);
660 if (!err &&
661 (UGETW(ds.wStatus) & UDS_SELF_POWERED))
662 selfpowered = 1;
663 DPRINTF(("usbd_set_config_index: status=0x%04x"
664 ", error=%s\n",
665 UGETW(ds.wStatus), usbd_errstr(err)));
667 } else
668 selfpowered = 1;
670 DPRINTF(("usbd_set_config_index: (addr %d) cno=%d attr=0x%02x, "
671 "selfpowered=%d, power=%d\n",
672 cdp->bConfigurationValue, dev->address, cdp->bmAttributes,
673 selfpowered, cdp->bMaxPower * 2));
675 /* Check if we have enough power. */
676 #ifdef USB_DEBUG
677 if (dev->powersrc == NULL) {
678 DPRINTF(("usbd_set_config_index: No power source?\n"));
679 return (USBD_IOERROR);
681 #endif
682 power = cdp->bMaxPower * 2;
683 if (power > dev->powersrc->power) {
684 DPRINTF(("power exceeded %d %d\n", power,dev->powersrc->power));
685 /* XXX print nicer message. */
686 if (msg)
687 printf("%s: device addr %d (config %d) exceeds power "
688 "budget, %d mA > %d mA\n",
689 USBDEVNAME(dev->bus->bdev), dev->address,
690 cdp->bConfigurationValue,
691 power, dev->powersrc->power);
692 err = USBD_NO_POWER;
693 goto bad;
695 dev->power = power;
696 dev->self_powered = selfpowered;
698 /* Set the actual configuration value. */
699 DPRINTF(("usbd_set_config_index: set config %d\n",
700 cdp->bConfigurationValue));
701 err = usbd_set_config(dev, cdp->bConfigurationValue);
702 if (err) {
703 DPRINTF(("usbd_set_config_index: setting config=%d failed, "
704 "error=%s\n",
705 cdp->bConfigurationValue, usbd_errstr(err)));
706 goto bad;
709 /* Allocate and fill interface data. */
710 nifc = cdp->bNumInterface;
711 dev->ifaces = kmalloc(nifc * sizeof(struct usbd_interface),
712 M_USB, M_INTWAIT);
713 DPRINTFN(5,("usbd_set_config_index: dev=%p cdesc=%p\n", dev, cdp));
714 dev->cdesc = cdp;
715 dev->config = cdp->bConfigurationValue;
716 for (ifcidx = 0; ifcidx < nifc; ifcidx++) {
717 err = usbd_fill_iface_data(dev, ifcidx, 0);
718 if (err) {
719 while (--ifcidx >= 0)
720 usbd_free_iface_data(dev, ifcidx);
721 goto bad;
725 return (USBD_NORMAL_COMPLETION);
727 bad:
728 kfree(cdp, M_USB);
729 return (err);
732 /* XXX add function for alternate settings */
734 usbd_status
735 usbd_setup_pipe(usbd_device_handle dev, usbd_interface_handle iface,
736 struct usbd_endpoint *ep, int ival, usbd_pipe_handle *pipe)
738 usbd_pipe_handle p;
739 usbd_status err;
741 DPRINTFN(1,("usbd_setup_pipe: dev=%p iface=%p ep=%p pipe=%p\n",
742 dev, iface, ep, pipe));
743 p = kmalloc(dev->bus->pipe_size, M_USB, M_INTWAIT);
744 p->device = dev;
745 p->iface = iface;
746 p->endpoint = ep;
747 ep->refcnt++;
748 p->refcnt = 1;
749 p->intrxfer = 0;
750 p->running = 0;
751 p->aborting = 0;
752 p->repeat = 0;
753 p->interval = ival;
754 SIMPLEQ_INIT(&p->queue);
755 err = dev->bus->methods->open_pipe(p);
756 if (err) {
757 DPRINTFN(-1,("usbd_setup_pipe: endpoint=0x%x failed, error="
758 "%s\n",
759 ep->edesc->bEndpointAddress, usbd_errstr(err)));
760 kfree(p, M_USB);
761 return (err);
764 *pipe = p;
765 return (USBD_NORMAL_COMPLETION);
768 /* Abort the device control pipe. */
769 void
770 usbd_kill_pipe(usbd_pipe_handle pipe)
772 usbd_abort_pipe(pipe);
773 pipe->methods->close(pipe);
774 pipe->endpoint->refcnt--;
775 kfree(pipe, M_USB);
779 usbd_getnewaddr(usbd_bus_handle bus)
781 int addr;
783 for (addr = 1; addr < USB_MAX_DEVICES; addr++)
784 if (bus->devices[addr] == 0)
785 return (addr);
786 return (-1);
790 usbd_status
791 usbd_probe_and_attach(device_ptr_t parent, usbd_device_handle dev,
792 int port, int addr)
794 struct usb_attach_arg uaa;
795 usb_device_descriptor_t *dd = &dev->ddesc;
796 int found, i, confi, nifaces;
797 usbd_status err;
798 device_ptr_t dv;
799 device_ptr_t *tmpdv;
800 usbd_interface_handle ifaces[256]; /* 256 is the absolute max */
802 #if defined(__FreeBSD__) || defined(__DragonFly__)
803 /* XXX FreeBSD may leak resources on failure cases -- fixme */
804 device_t bdev;
805 struct usb_attach_arg *uaap;
807 bdev = device_add_child(parent, NULL, -1);
808 if (!bdev) {
809 device_printf(parent, "Device creation failed\n");
810 return (USBD_INVAL);
812 device_quiet(bdev);
813 uaap = kmalloc(sizeof(uaa), M_USB, M_WAITOK);
814 device_set_ivars(bdev, uaap);
815 #endif
816 uaa.device = dev;
817 uaa.iface = NULL;
818 uaa.ifaces = NULL;
819 uaa.nifaces = 0;
820 uaa.usegeneric = 0;
821 uaa.port = port;
822 uaa.configno = UHUB_UNK_CONFIGURATION;
823 uaa.ifaceno = UHUB_UNK_INTERFACE;
824 uaa.vendor = UGETW(dd->idVendor);
825 uaa.product = UGETW(dd->idProduct);
826 uaa.release = UGETW(dd->bcdDevice);
828 /* First try with device specific drivers. */
829 DPRINTF(("usbd_probe_and_attach: trying device specific drivers\n"));
831 dev->ifacenums = NULL;
832 dev->subdevs = kmalloc(2 * sizeof dv, M_USB, M_WAITOK);
833 dev->subdevs[0] = bdev;
834 dev->subdevs[1] = 0;
835 *uaap = uaa;
836 dv = USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print, usbd_submatch);
837 if (dv) {
838 return (USBD_NORMAL_COMPLETION);
841 * Free subdevs so we can reallocate it larger for the number of
842 * interfaces
844 tmpdv = dev->subdevs;
845 dev->subdevs = NULL;
846 kfree(tmpdv, M_USB);
847 DPRINTF(("usbd_probe_and_attach: no device specific driver found\n"));
849 DPRINTF(("usbd_probe_and_attach: looping over %d configurations\n",
850 dd->bNumConfigurations));
851 /* Next try with interface drivers. */
852 for (confi = 0; confi < dd->bNumConfigurations; confi++) {
853 DPRINTFN(1,("usbd_probe_and_attach: trying config idx=%d\n",
854 confi));
855 err = usbd_set_config_index(dev, confi, 1);
856 if (err) {
857 #ifdef USB_DEBUG
858 DPRINTF(("%s: port %d, set config at addr %d failed, "
859 "error=%s\n", USBDEVPTRNAME(parent), port,
860 addr, usbd_errstr(err)));
861 #else
862 printf("%s: port %d, set config at addr %d failed\n",
863 USBDEVPTRNAME(parent), port, addr);
864 #endif
865 return (err);
867 nifaces = dev->cdesc->bNumInterface;
868 uaa.configno = dev->cdesc->bConfigurationValue;
869 for (i = 0; i < nifaces; i++)
870 ifaces[i] = &dev->ifaces[i];
871 uaa.ifaces = ifaces;
872 uaa.nifaces = nifaces;
873 dev->subdevs = kmalloc((nifaces+1) * sizeof dv, M_USB,
874 M_WAITOK);
875 dev->ifacenums = kmalloc((nifaces) * sizeof(*dev->ifacenums),
876 M_USB, M_WAITOK);
878 found = 0;
879 for (i = 0; i < nifaces; i++) {
880 if (ifaces[i] == NULL)
881 continue; /* interface already claimed */
882 uaa.iface = ifaces[i];
883 uaa.ifaceno = ifaces[i]->idesc->bInterfaceNumber;
884 dev->subdevs[found] = bdev;
885 dev->subdevs[found + 1] = 0;
886 dev->ifacenums[found] = i;
887 *uaap = uaa;
888 dv = USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print,
889 usbd_submatch);
890 if (dv != NULL) {
891 ifaces[i] = 0; /* consumed */
892 found++;
894 #if defined(__FreeBSD__) || defined(__DragonFly__)
895 /* create another child for the next iface */
896 bdev = device_add_child(parent, NULL, -1);
897 if (!bdev) {
898 device_printf(parent,
899 "Device add failed\n");
900 return (USBD_NORMAL_COMPLETION);
902 uaap = kmalloc(sizeof(uaa), M_USB, M_WAITOK);
903 device_set_ivars(bdev, uaap);
904 device_quiet(bdev);
905 #endif
906 } else {
907 dev->subdevs[found] = 0;
910 if (found != 0) {
911 #if defined(__FreeBSD__) || defined(__DragonFly__)
912 /* remove the last created child. It is unused */
913 device_delete_child(parent, bdev);
914 /* kfree(uaap, M_USB); */ /* May be needed? xxx */
915 #endif
916 return (USBD_NORMAL_COMPLETION);
918 tmpdv = dev->subdevs;
919 dev->subdevs = NULL;
920 kfree(tmpdv, M_USB);
921 kfree(dev->ifacenums, M_USB);
922 dev->ifacenums = NULL;
924 /* No interfaces were attached in any of the configurations. */
926 if (dd->bNumConfigurations > 1) /* don't change if only 1 config */
927 usbd_set_config_index(dev, 0, 0);
929 DPRINTF(("usbd_probe_and_attach: no interface drivers found\n"));
931 /* Finally try the generic driver. */
932 uaa.iface = NULL;
933 uaa.usegeneric = 1;
934 uaa.configno = UHUB_UNK_CONFIGURATION;
935 uaa.ifaceno = UHUB_UNK_INTERFACE;
936 dev->subdevs = kmalloc(2 * sizeof dv, M_USB, M_WAITOK);
937 dev->subdevs[0] = bdev;
938 dev->subdevs[1] = 0;
939 *uaap = uaa;
940 dv = USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print, usbd_submatch);
941 if (dv != NULL) {
942 return (USBD_NORMAL_COMPLETION);
946 * The generic attach failed, but leave the device as it is.
947 * We just did not find any drivers, that's all. The device is
948 * fully operational and not harming anyone.
950 DPRINTF(("usbd_probe_and_attach: generic attach failed\n"));
951 return (USBD_NORMAL_COMPLETION);
956 * Called when a new device has been put in the powered state,
957 * but not yet in the addressed state.
958 * Get initial descriptor, set the address, get full descriptor,
959 * and attach a driver.
961 usbd_status
962 usbd_new_device(device_ptr_t parent, usbd_bus_handle bus, int depth,
963 int speed, int port, struct usbd_port *up)
965 usbd_device_handle dev, adev;
966 struct usbd_device *hub;
967 usb_device_descriptor_t *dd;
968 usb_port_status_t ps;
969 usbd_status err;
970 int addr;
971 int i;
972 int p;
974 DPRINTF(("usbd_new_device bus=%p port=%d depth=%d speed=%d\n",
975 bus, port, depth, speed));
976 addr = usbd_getnewaddr(bus);
977 if (addr < 0) {
978 printf("%s: No free USB addresses, new device ignored.\n",
979 USBDEVNAME(bus->bdev));
980 return (USBD_NO_ADDR);
983 dev = kmalloc(sizeof *dev, M_USB, M_INTWAIT | M_ZERO);
984 dev->bus = bus;
986 /* Set up default endpoint handle. */
987 dev->def_ep.edesc = &dev->def_ep_desc;
989 /* Set up default endpoint descriptor. */
990 dev->def_ep_desc.bLength = USB_ENDPOINT_DESCRIPTOR_SIZE;
991 dev->def_ep_desc.bDescriptorType = UDESC_ENDPOINT;
992 dev->def_ep_desc.bEndpointAddress = USB_CONTROL_ENDPOINT;
993 dev->def_ep_desc.bmAttributes = UE_CONTROL;
994 USETW(dev->def_ep_desc.wMaxPacketSize, USB_MAX_IPACKET);
995 dev->def_ep_desc.bInterval = 0;
997 dev->quirks = &usbd_no_quirk;
998 dev->address = USB_START_ADDR;
999 dev->ddesc.bMaxPacketSize = 0;
1000 dev->depth = depth;
1001 dev->powersrc = up;
1002 dev->myhub = up->parent;
1004 up->device = dev;
1006 /* Locate port on upstream high speed hub */
1007 for (adev = dev, hub = up->parent;
1008 hub != NULL && hub->speed != USB_SPEED_HIGH;
1009 adev = hub, hub = hub->myhub)
1011 if (hub) {
1012 for (p = 0; p < hub->hub->hubdesc.bNbrPorts; p++) {
1013 if (hub->hub->ports[p].device == adev) {
1014 dev->myhsport = &hub->hub->ports[p];
1015 goto found;
1018 panic("usbd_new_device: cannot find HS port\n");
1019 found:
1020 DPRINTFN(1,("usbd_new_device: high speed port %d\n", p));
1021 } else {
1022 dev->myhsport = NULL;
1024 dev->speed = speed;
1025 dev->langid = USBD_NOLANG;
1026 dev->cookie.cookie = ++usb_cookie_no;
1028 /* Establish the default pipe. */
1029 err = usbd_setup_pipe(dev, 0, &dev->def_ep, USBD_DEFAULT_INTERVAL,
1030 &dev->default_pipe);
1031 if (err) {
1032 usbd_remove_device(dev, up);
1033 return (err);
1036 /* Set the address. Do this early; some devices need that. */
1037 /* Try a few times in case the device is slow (i.e. outside specs.) */
1038 DPRINTFN(5,("usbd_new_device: setting device address=%d\n", addr));
1039 for (i = 0; i < 15; i++) {
1040 err = usbd_set_address(dev, addr);
1041 if (!err)
1042 break;
1043 usbd_delay_ms(dev, 200);
1044 if ((i & 3) == 3) {
1045 DPRINTFN(-1,("usb_new_device: set address %d "
1046 "failed - trying a port reset\n", addr));
1047 usbd_reset_port(up->parent, port, &ps);
1050 if (err) {
1051 DPRINTFN(-1,("usb_new_device: set address %d failed\n", addr));
1052 err = USBD_SET_ADDR_FAILED;
1053 usbd_remove_device(dev, up);
1054 return (err);
1056 /* Allow device time to set new address */
1057 usbd_delay_ms(dev, USB_SET_ADDRESS_SETTLE);
1058 dev->address = addr; /* New device address now */
1059 bus->devices[addr] = dev;
1061 dd = &dev->ddesc;
1062 /* Get the first 8 bytes of the device descriptor. */
1063 err = usbd_get_desc(dev, UDESC_DEVICE, 0, USB_MAX_IPACKET, dd);
1064 if (err) {
1065 DPRINTFN(-1, ("usbd_new_device: addr=%d, getting first desc "
1066 "failed\n", addr));
1067 usbd_remove_device(dev, up);
1068 return (err);
1071 if (speed == USB_SPEED_HIGH) {
1072 /* Max packet size must be 64 (sec 5.5.3). */
1073 if (dd->bMaxPacketSize != USB_2_MAX_CTRL_PACKET) {
1074 #ifdef DIAGNOSTIC
1075 printf("usbd_new_device: addr=%d bad max packet size\n",
1076 addr);
1077 #endif
1078 dd->bMaxPacketSize = USB_2_MAX_CTRL_PACKET;
1082 DPRINTF(("usbd_new_device: adding unit addr=%d, rev=%02x, class=%d, "
1083 "subclass=%d, protocol=%d, maxpacket=%d, len=%d, speed=%d\n",
1084 addr,UGETW(dd->bcdUSB), dd->bDeviceClass, dd->bDeviceSubClass,
1085 dd->bDeviceProtocol, dd->bMaxPacketSize, dd->bLength,
1086 dev->speed));
1088 if (dd->bDescriptorType != UDESC_DEVICE) {
1089 /* Illegal device descriptor */
1090 DPRINTFN(-1,("usbd_new_device: illegal descriptor %d\n",
1091 dd->bDescriptorType));
1092 usbd_remove_device(dev, up);
1093 return (USBD_INVAL);
1096 if (dd->bLength < USB_DEVICE_DESCRIPTOR_SIZE) {
1097 DPRINTFN(-1,("usbd_new_device: bad length %d\n", dd->bLength));
1098 usbd_remove_device(dev, up);
1099 return (USBD_INVAL);
1102 USETW(dev->def_ep_desc.wMaxPacketSize, dd->bMaxPacketSize);
1104 err = usbd_reload_device_desc(dev);
1105 if (err) {
1106 DPRINTFN(-1, ("usbd_new_device: addr=%d, getting full desc "
1107 "failed\n", addr));
1108 usbd_remove_device(dev, up);
1109 return (err);
1112 /* Assume 100mA bus powered for now. Changed when configured. */
1113 dev->power = USB_MIN_POWER;
1114 dev->self_powered = 0;
1116 DPRINTF(("usbd_new_device: new dev (addr %d), dev=%p, parent=%p\n",
1117 addr, dev, parent));
1119 err = usbd_probe_and_attach(parent, dev, port, addr);
1120 if (err) {
1121 usbd_remove_device(dev, up);
1122 return (err);
1125 usbd_add_dev_event(USB_EVENT_DEVICE_ATTACH, dev);
1127 return (USBD_NORMAL_COMPLETION);
1130 usbd_status
1131 usbd_reload_device_desc(usbd_device_handle dev)
1133 usbd_status err;
1134 int i;
1136 /* Get the full device descriptor. */
1137 for (i = 0; i < 3; ++i) {
1138 err = usbd_get_device_desc(dev, &dev->ddesc);
1139 if (!err)
1140 break;
1141 usbd_delay_ms(dev, 200);
1143 if (err)
1144 return (err);
1146 /* Figure out what's wrong with this device. */
1147 dev->quirks = usbd_find_quirk(&dev->ddesc);
1149 return (USBD_NORMAL_COMPLETION);
1152 void
1153 usbd_remove_device(usbd_device_handle dev, struct usbd_port *up)
1155 DPRINTF(("usbd_remove_device: %p\n", dev));
1157 if (dev->default_pipe != NULL)
1158 usbd_kill_pipe(dev->default_pipe);
1159 up->device = NULL;
1160 dev->bus->devices[dev->address] = NULL;
1162 kfree(dev, M_USB);
1165 #if defined(__NetBSD__) || defined(__OpenBSD__)
1167 usbd_print(void *aux, const char *pnp)
1169 struct usb_attach_arg *uaa = aux;
1170 char devinfo[1024];
1172 DPRINTFN(15, ("usbd_print dev=%p\n", uaa->device));
1173 if (pnp) {
1174 if (!uaa->usegeneric)
1175 return (QUIET);
1176 usbd_devinfo(uaa->device, 1, devinfo);
1177 printf("%s, %s", devinfo, pnp);
1179 if (uaa->port != 0)
1180 printf(" port %d", uaa->port);
1181 if (uaa->configno != UHUB_UNK_CONFIGURATION)
1182 printf(" configuration %d", uaa->configno);
1183 if (uaa->ifaceno != UHUB_UNK_INTERFACE)
1184 printf(" interface %d", uaa->ifaceno);
1185 #if 0
1187 * It gets very crowded with these locators on the attach line.
1188 * They are not really needed since they are printed in the clear
1189 * by each driver.
1191 if (uaa->vendor != UHUB_UNK_VENDOR)
1192 printf(" vendor 0x%04x", uaa->vendor);
1193 if (uaa->product != UHUB_UNK_PRODUCT)
1194 printf(" product 0x%04x", uaa->product);
1195 if (uaa->release != UHUB_UNK_RELEASE)
1196 printf(" release 0x%04x", uaa->release);
1197 #endif
1198 return (UNCONF);
1201 #if defined(__NetBSD__)
1203 usbd_submatch(struct device *parent, struct cfdata *cf, void *aux)
1205 #elif defined(__OpenBSD__)
1207 usbd_submatch(struct device *parent, void *match, void *aux)
1209 struct cfdata *cf = match;
1210 #endif
1211 struct usb_attach_arg *uaa = aux;
1213 DPRINTFN(5,("usbd_submatch port=%d,%d configno=%d,%d "
1214 "ifaceno=%d,%d vendor=%d,%d product=%d,%d release=%d,%d\n",
1215 uaa->port, cf->uhubcf_port,
1216 uaa->configno, cf->uhubcf_configuration,
1217 uaa->ifaceno, cf->uhubcf_interface,
1218 uaa->vendor, cf->uhubcf_vendor,
1219 uaa->product, cf->uhubcf_product,
1220 uaa->release, cf->uhubcf_release));
1221 if (uaa->port != 0 && /* root hub has port 0, it should match */
1222 ((uaa->port != 0 &&
1223 cf->uhubcf_port != UHUB_UNK_PORT &&
1224 cf->uhubcf_port != uaa->port) ||
1225 (uaa->configno != UHUB_UNK_CONFIGURATION &&
1226 cf->uhubcf_configuration != UHUB_UNK_CONFIGURATION &&
1227 cf->uhubcf_configuration != uaa->configno) ||
1228 (uaa->ifaceno != UHUB_UNK_INTERFACE &&
1229 cf->uhubcf_interface != UHUB_UNK_INTERFACE &&
1230 cf->uhubcf_interface != uaa->ifaceno) ||
1231 (uaa->vendor != UHUB_UNK_VENDOR &&
1232 cf->uhubcf_vendor != UHUB_UNK_VENDOR &&
1233 cf->uhubcf_vendor != uaa->vendor) ||
1234 (uaa->product != UHUB_UNK_PRODUCT &&
1235 cf->uhubcf_product != UHUB_UNK_PRODUCT &&
1236 cf->uhubcf_product != uaa->product) ||
1237 (uaa->release != UHUB_UNK_RELEASE &&
1238 cf->uhubcf_release != UHUB_UNK_RELEASE &&
1239 cf->uhubcf_release != uaa->release)
1242 return 0;
1243 if (cf->uhubcf_vendor != UHUB_UNK_VENDOR &&
1244 cf->uhubcf_vendor == uaa->vendor &&
1245 cf->uhubcf_product != UHUB_UNK_PRODUCT &&
1246 cf->uhubcf_product == uaa->product) {
1247 /* We have a vendor&product locator match */
1248 if (cf->uhubcf_release != UHUB_UNK_RELEASE &&
1249 cf->uhubcf_release == uaa->release)
1250 uaa->matchlvl = UMATCH_VENDOR_PRODUCT_REV;
1251 else
1252 uaa->matchlvl = UMATCH_VENDOR_PRODUCT;
1253 } else
1254 uaa->matchlvl = 0;
1255 return ((*cf->cf_attach->ca_match)(parent, cf, aux));
1258 #endif
1260 void
1261 usbd_fill_deviceinfo(usbd_device_handle dev, struct usb_device_info *di,
1262 int usedev)
1264 struct usbd_port *p;
1265 int i, err, s;
1267 di->udi_bus = USBDEVUNIT(dev->bus->bdev);
1268 di->udi_addr = dev->address;
1269 di->udi_cookie = dev->cookie;
1270 usbd_devinfo_vp(dev, di->udi_vendor, di->udi_product, usedev);
1271 usbd_printBCD(di->udi_release, UGETW(dev->ddesc.bcdDevice));
1272 di->udi_vendorNo = UGETW(dev->ddesc.idVendor);
1273 di->udi_productNo = UGETW(dev->ddesc.idProduct);
1274 di->udi_releaseNo = UGETW(dev->ddesc.bcdDevice);
1275 di->udi_class = dev->ddesc.bDeviceClass;
1276 di->udi_subclass = dev->ddesc.bDeviceSubClass;
1277 di->udi_protocol = dev->ddesc.bDeviceProtocol;
1278 di->udi_config = dev->config;
1279 di->udi_power = dev->self_powered ? 0 : dev->power;
1280 di->udi_speed = dev->speed;
1282 if (dev->subdevs != NULL) {
1283 for (i = 0; dev->subdevs[i] && i < USB_MAX_DEVNAMES; i++) {
1284 if (device_is_attached(dev->subdevs[i]))
1285 strlcpy(di->udi_devnames[i],
1286 USBDEVPTRNAME(dev->subdevs[i]),
1287 USB_MAX_DEVNAMELEN);
1288 else
1289 di->udi_devnames[i][0] = 0;
1291 } else {
1292 i = 0;
1294 for (/*i is set */; i < USB_MAX_DEVNAMES; i++)
1295 di->udi_devnames[i][0] = 0; /* empty */
1297 if (dev->hub) {
1298 for (i = 0;
1299 i < sizeof(di->udi_ports) / sizeof(di->udi_ports[0]) &&
1300 i < dev->hub->hubdesc.bNbrPorts;
1301 i++) {
1302 p = &dev->hub->ports[i];
1303 if (p->device)
1304 err = p->device->address;
1305 else {
1306 s = UGETW(p->status.wPortStatus);
1307 if (s & UPS_PORT_ENABLED)
1308 err = USB_PORT_ENABLED;
1309 else if (s & UPS_SUSPEND)
1310 err = USB_PORT_SUSPENDED;
1311 else if (s & UPS_PORT_POWER)
1312 err = USB_PORT_POWERED;
1313 else
1314 err = USB_PORT_DISABLED;
1316 di->udi_ports[i] = err;
1318 di->udi_nports = dev->hub->hubdesc.bNbrPorts;
1319 } else
1320 di->udi_nports = 0;
1323 void
1324 usb_free_device(usbd_device_handle dev)
1326 int ifcidx, nifc;
1328 if (dev->default_pipe != NULL)
1329 usbd_kill_pipe(dev->default_pipe);
1330 if (dev->ifaces != NULL) {
1331 nifc = dev->cdesc->bNumInterface;
1332 for (ifcidx = 0; ifcidx < nifc; ifcidx++)
1333 usbd_free_iface_data(dev, ifcidx);
1334 kfree(dev->ifaces, M_USB);
1336 if (dev->cdesc != NULL)
1337 kfree(dev->cdesc, M_USB);
1338 if (dev->subdevs != NULL)
1339 kfree(dev->subdevs, M_USB);
1340 if (dev->ifacenums != NULL)
1341 kfree(dev->ifacenums, M_USB);
1342 kfree(dev, M_USB);
1346 * The general mechanism for detaching drivers works as follows: Each
1347 * driver is responsible for maintaining a reference count on the
1348 * number of outstanding references to its softc (e.g. from
1349 * processing hanging in a read or write). The detach method of the
1350 * driver decrements this counter and flags in the softc that the
1351 * driver is dying and then wakes any sleepers. It then sleeps on the
1352 * softc. Each place that can sleep must maintain the reference
1353 * count. When the reference count drops to -1 (0 is the normal value
1354 * of the reference count) the a wakeup on the softc is performed
1355 * signaling to the detach waiter that all references are gone.
1359 * Called from process context when we discover that a port has
1360 * been disconnected.
1362 void
1363 usb_disconnect_port(struct usbd_port *up, device_ptr_t parent)
1365 usbd_device_handle dev = up->device;
1366 const char *hubname = USBDEVPTRNAME(parent);
1367 int i;
1369 DPRINTFN(3,("uhub_disconnect: up=%p dev=%p port=%d\n",
1370 up, dev, up->portno));
1372 #ifdef DIAGNOSTIC
1373 if (dev == NULL) {
1374 printf("usb_disconnect_port: no device\n");
1375 return;
1377 #endif
1379 if (dev->subdevs != NULL) {
1380 DPRINTFN(3,("usb_disconnect_port: disconnect subdevs\n"));
1381 for (i = 0; dev->subdevs[i]; i++) {
1382 printf("%s: at %s", USBDEVPTRNAME(dev->subdevs[i]),
1383 hubname);
1384 if (up->portno != 0)
1385 printf(" port %d", up->portno);
1386 printf(" (addr %d) disconnected\n", dev->address);
1387 config_detach(dev->subdevs[i], DETACH_FORCE);
1388 dev->subdevs[i] = NULL;
1392 usbd_add_dev_event(USB_EVENT_DEVICE_DETACH, dev);
1393 dev->bus->devices[dev->address] = NULL;
1394 up->device = NULL;
1395 usb_free_device(dev);
1398 #ifdef __OpenBSD__
1399 void *
1400 usb_realloc(void *p, u_int size, int pool, int flags)
1402 void *q;
1404 q = malloc(size, pool, flags);
1405 if (q == NULL)
1406 return (NULL);
1407 bcopy(p, q, size);
1408 free(p, pool);
1409 return (q);
1411 #endif