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