Annotation of src/sys/dev/usb/usb_subr.c, Revision 1.34
1.34 ! augustss 1: /* $NetBSD: usb_subr.c,v 1.33 1999/06/14 17:09:57 augustss Exp $ */
1.1 augustss 2:
3: /*
4: * Copyright (c) 1998 The NetBSD Foundation, Inc.
5: * All rights reserved.
6: *
1.9 augustss 7: * This code is derived from software contributed to The NetBSD Foundation
8: * by Lennart Augustsson (augustss@carlstedt.se) at
9: * Carlstedt Research & Technology.
1.1 augustss 10: *
11: * Redistribution and use in source and binary forms, with or without
12: * modification, are permitted provided that the following conditions
13: * are met:
14: * 1. Redistributions of source code must retain the above copyright
15: * notice, this list of conditions and the following disclaimer.
16: * 2. Redistributions in binary form must reproduce the above copyright
17: * notice, this list of conditions and the following disclaimer in the
18: * documentation and/or other materials provided with the distribution.
19: * 3. All advertising materials mentioning features or use of this software
20: * must display the following acknowledgement:
21: * This product includes software developed by the NetBSD
22: * Foundation, Inc. and its contributors.
23: * 4. Neither the name of The NetBSD Foundation nor the names of its
24: * contributors may be used to endorse or promote products derived
25: * from this software without specific prior written permission.
26: *
27: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37: * POSSIBILITY OF SUCH DAMAGE.
38: */
39:
40: #include <sys/param.h>
41: #include <sys/systm.h>
42: #include <sys/kernel.h>
43: #include <sys/malloc.h>
1.18 augustss 44: #if defined(__NetBSD__)
1.1 augustss 45: #include <sys/device.h>
1.18 augustss 46: #elif defined(__FreeBSD__)
47: #include <sys/module.h>
48: #include <sys/bus.h>
49: #endif
1.1 augustss 50: #include <sys/proc.h>
51: #include <sys/select.h>
52:
53: #include <dev/usb/usb.h>
54:
55: #include <dev/usb/usbdi.h>
56: #include <dev/usb/usbdi_util.h>
57: #include <dev/usb/usbdivar.h>
58: #include <dev/usb/usbdevs.h>
59: #include <dev/usb/usb_quirks.h>
60:
1.27 augustss 61: #if defined(__FreeBSD__)
62: #include <machine/clock.h>
63: #define delay(d) DELAY(d)
64: #endif
65:
1.1 augustss 66: #ifdef USB_DEBUG
67: #define DPRINTF(x) if (usbdebug) printf x
68: #define DPRINTFN(n,x) if (usbdebug>(n)) printf x
69: extern int usbdebug;
70: #else
71: #define DPRINTF(x)
72: #define DPRINTFN(n,x)
73: #endif
74:
1.7 augustss 75: static usbd_status usbd_set_config __P((usbd_device_handle, int));
1.1 augustss 76: char *usbd_get_string __P((usbd_device_handle, int, char *));
77: int usbd_getnewaddr __P((usbd_bus_handle bus));
1.27 augustss 78: #if defined(__NetBSD__)
1.1 augustss 79: int usbd_print __P((void *aux, const char *pnp));
1.27 augustss 80: int usbd_submatch __P((bdevice *, struct cfdata *cf, void *));
1.18 augustss 81: #endif
1.1 augustss 82: void usbd_free_iface_data __P((usbd_device_handle dev, int ifcno));
83: void usbd_kill_pipe __P((usbd_pipe_handle));
1.18 augustss 84: usbd_status usbd_probe_and_attach
85: __P((bdevice *parent, usbd_device_handle dev, int port, int addr));
1.1 augustss 86:
1.27 augustss 87:
1.1 augustss 88: #ifdef USBVERBOSE
89: typedef u_int16_t usb_vendor_id_t;
90: typedef u_int16_t usb_product_id_t;
91:
92: /*
93: * Descriptions of of known vendors and devices ("products").
94: */
95: struct usb_knowndev {
96: usb_vendor_id_t vendor;
97: usb_product_id_t product;
98: int flags;
99: char *vendorname, *productname;
100: };
101: #define USB_KNOWNDEV_NOPROD 0x01 /* match on vendor only */
102:
103: #include <dev/usb/usbdevs_data.h>
104: #endif /* USBVERBOSE */
105:
1.12 augustss 106: #ifdef USB_DEBUG
107: char *usbd_error_strs[] = {
108: "NORMAL_COMPLETION",
109: "IN_PROGRESS",
110: "PENDING_REQUESTS",
111: "NOT_STARTED",
112: "INVAL",
113: "NOMEM",
114: "CANCELLED",
115: "BAD_ADDRESS",
116: "IN_USE",
117: "NO_ADDR",
118: "SET_ADDR_FAILED",
119: "NO_POWER",
120: "TOO_DEEP",
121: "IOERROR",
122: "NOT_CONFIGURED",
123: "TIMEOUT",
124: "SHORT_XFER",
125: "STALLED",
1.33 augustss 126: "INTERRUPTED",
1.12 augustss 127: "XXX",
128: };
129: #endif
1.1 augustss 130:
1.13 augustss 131: usbd_status
132: usbd_get_string_desc(dev, sindex, langid, sdesc)
133: usbd_device_handle dev;
134: int sindex;
135: int langid;
136: usb_string_descriptor_t *sdesc;
137: {
138: usb_device_request_t req;
139: usbd_status r;
140:
141: req.bmRequestType = UT_READ_DEVICE;
142: req.bRequest = UR_GET_DESCRIPTOR;
143: USETW2(req.wValue, UDESC_STRING, sindex);
144: USETW(req.wIndex, langid);
145: USETW(req.wLength, 1); /* only size byte first */
146: r = usbd_do_request(dev, &req, sdesc);
147: if (r != USBD_NORMAL_COMPLETION)
148: return (r);
149: USETW(req.wLength, sdesc->bLength); /* the whole string */
150: return (usbd_do_request(dev, &req, sdesc));
151: }
152:
1.1 augustss 153: char *
154: usbd_get_string(dev, si, buf)
155: usbd_device_handle dev;
156: int si;
157: char *buf;
158: {
159: int swap = dev->quirks->uq_flags & UQ_SWAP_UNICODE;
160: usb_string_descriptor_t us;
161: char *s;
162: int i, n;
163: u_int16_t c;
164: usbd_status r;
165:
166: if (si == 0)
1.11 augustss 167: return (0);
168: if (dev->quirks->uq_flags & UQ_NO_STRINGS)
169: return (0);
1.22 augustss 170: if (dev->langid == USBD_NOLANG) {
171: /* Set up default language */
172: r = usbd_get_string_desc(dev, USB_LANGUAGE_TABLE, 0, &us);
173: if (r != USBD_NORMAL_COMPLETION || us.bLength < 4) {
174: dev->langid = 0; /* Well, just pick English then */
175: } else {
176: /* Pick the first language as the default. */
177: dev->langid = UGETW(us.bString[0]);
178: }
179: }
180: r = usbd_get_string_desc(dev, si, dev->langid, &us);
1.1 augustss 181: if (r != USBD_NORMAL_COMPLETION)
1.13 augustss 182: return (0);
1.1 augustss 183: s = buf;
184: n = us.bLength / 2 - 1;
185: for (i = 0; i < n; i++) {
186: c = UGETW(us.bString[i]);
187: /* Convert from Unicode, handle buggy strings. */
188: if ((c & 0xff00) == 0)
189: *s++ = c;
190: else if ((c & 0x00ff) == 0 && swap)
191: *s++ = c >> 8;
192: else
193: *s++ = '?';
194: }
195: *s++ = 0;
196: return buf;
197: }
198:
199: void
200: usbd_devinfo_vp(dev, v, p)
201: usbd_device_handle dev;
202: char *v, *p;
203: {
204: usb_device_descriptor_t *udd = &dev->ddesc;
205: char *vendor = 0, *product = 0;
1.2 is 206: #ifdef USBVERBOSE
1.1 augustss 207: struct usb_knowndev *kdp;
1.2 is 208: #endif
1.1 augustss 209:
210: vendor = usbd_get_string(dev, udd->iManufacturer, v);
211: product = usbd_get_string(dev, udd->iProduct, p);
212: #ifdef USBVERBOSE
213: if (!vendor) {
214: for(kdp = usb_knowndevs;
215: kdp->vendorname != NULL;
216: kdp++) {
217: if (kdp->vendor == UGETW(udd->idVendor) &&
218: (kdp->product == UGETW(udd->idProduct) ||
219: (kdp->flags & USB_KNOWNDEV_NOPROD) != 0))
220: break;
221: }
222: if (kdp->vendorname == NULL)
223: vendor = product = NULL;
224: else {
225: vendor = kdp->vendorname;
226: product = (kdp->flags & USB_KNOWNDEV_NOPROD) == 0 ?
227: kdp->productname : NULL;
228: }
229: }
230: #endif
231: if (vendor)
232: strcpy(v, vendor);
233: else
234: sprintf(v, "vendor 0x%04x", UGETW(udd->idVendor));
235: if (product)
236: strcpy(p, product);
237: else
238: sprintf(p, "product 0x%04x", UGETW(udd->idProduct));
239: }
240:
241: int
242: usbd_printBCD(cp, bcd)
243: char *cp;
244: int bcd;
245: {
246: return (sprintf(cp, "%x.%02x", bcd >> 8, bcd & 0xff));
247: }
248:
249: void
250: usbd_devinfo(dev, showclass, cp)
251: usbd_device_handle dev;
252: int showclass;
253: char *cp;
254: {
255: usb_device_descriptor_t *udd = &dev->ddesc;
256: char vendor[USB_MAX_STRING_LEN];
257: char product[USB_MAX_STRING_LEN];
258: int bcdDevice, bcdUSB;
259:
260: usbd_devinfo_vp(dev, vendor, product);
1.11 augustss 261: cp += sprintf(cp, "%s %s", vendor, product);
1.1 augustss 262: if (showclass)
1.12 augustss 263: cp += sprintf(cp, ", class %d/%d",
1.1 augustss 264: udd->bDeviceClass, udd->bDeviceSubClass);
265: bcdUSB = UGETW(udd->bcdUSB);
266: bcdDevice = UGETW(udd->bcdDevice);
1.12 augustss 267: cp += sprintf(cp, ", rev ");
1.1 augustss 268: cp += usbd_printBCD(cp, bcdUSB);
269: *cp++ = '/';
270: cp += usbd_printBCD(cp, bcdDevice);
1.11 augustss 271: cp += sprintf(cp, ", addr %d", dev->address);
1.10 augustss 272: *cp = 0;
1.1 augustss 273: }
274:
275: /* Delay for a certain number of ms */
276: void
1.23 augustss 277: usb_delay_ms(bus, ms)
1.5 augustss 278: usbd_bus_handle bus;
1.23 augustss 279: u_int ms;
1.1 augustss 280: {
281: /* Wait at least two clock ticks so we know the time has passed. */
1.5 augustss 282: if (bus->use_polling)
1.1 augustss 283: delay((ms+1) * 1000);
284: else
285: tsleep(&ms, PRIBIO, "usbdly", (ms*hz+999)/1000 + 1);
286: }
287:
1.23 augustss 288: /* Delay given a device handle. */
289: void
290: usbd_delay_ms(dev, ms)
291: usbd_device_handle dev;
292: u_int ms;
293: {
294: usb_delay_ms(dev->bus, ms);
295: }
296:
1.1 augustss 297: usbd_status
298: usbd_reset_port(dev, port, ps)
299: usbd_device_handle dev;
300: int port;
301: usb_port_status_t *ps;
302: {
303: usb_device_request_t req;
304: usbd_status r;
305: int n;
306:
307: req.bmRequestType = UT_WRITE_CLASS_OTHER;
308: req.bRequest = UR_SET_FEATURE;
309: USETW(req.wValue, UHF_PORT_RESET);
310: USETW(req.wIndex, port);
311: USETW(req.wLength, 0);
312: r = usbd_do_request(dev, &req, 0);
1.12 augustss 313: DPRINTFN(1,("usbd_reset_port: port %d reset done, error=%d(%s)\n",
314: port, r, usbd_error_strs[r]));
1.1 augustss 315: if (r != USBD_NORMAL_COMPLETION)
316: return (r);
317: n = 10;
318: do {
319: /* Wait for device to recover from reset. */
1.23 augustss 320: usbd_delay_ms(dev, USB_PORT_RESET_DELAY);
1.1 augustss 321: r = usbd_get_port_status(dev, port, ps);
322: if (r != USBD_NORMAL_COMPLETION) {
323: DPRINTF(("usbd_reset_port: get status failed %d\n",r));
324: return (r);
325: }
326: } while ((UGETW(ps->wPortChange) & UPS_C_PORT_RESET) == 0 && --n > 0);
327: if (n == 0) {
328: printf("usbd_reset_port: timeout\n");
329: return (USBD_IOERROR);
330: }
331: r = usbd_clear_port_feature(dev, port, UHF_C_PORT_RESET);
332: #ifdef USB_DEBUG
333: if (r != USBD_NORMAL_COMPLETION)
334: DPRINTF(("usbd_reset_port: clear port feature failed %d\n",r));
335: #endif
1.18 augustss 336:
337: /* Wait for the device to recover from reset. */
1.23 augustss 338: usbd_delay_ms(dev, USB_PORT_RESET_RECOVERY);
1.1 augustss 339: return (r);
340: }
341:
1.12 augustss 342: usb_interface_descriptor_t *
343: usbd_find_idesc(cd, ifaceidx, altidx)
344: usb_config_descriptor_t *cd;
345: int ifaceidx;
346: int altidx;
347: {
348: char *p = (char *)cd;
349: char *end = p + UGETW(cd->wTotalLength);
350: usb_interface_descriptor_t *d;
1.19 augustss 351: int curidx, lastidx, curaidx = 0;
1.12 augustss 352:
1.19 augustss 353: for (curidx = lastidx = -1; p < end; ) {
1.12 augustss 354: d = (usb_interface_descriptor_t *)p;
1.18 augustss 355: DPRINTFN(4,("usbd_find_idesc: idx=%d(%d) altidx=%d(%d) len=%d "
356: "type=%d\n",
357: ifaceidx, curidx, altidx, curaidx,
358: d->bLength, d->bDescriptorType));
1.12 augustss 359: if (d->bLength == 0) /* bad descriptor */
360: break;
361: p += d->bLength;
362: if (p <= end && d->bDescriptorType == UDESC_INTERFACE) {
1.19 augustss 363: if (d->bInterfaceNumber != lastidx) {
364: lastidx = d->bInterfaceNumber;
1.12 augustss 365: curidx++;
366: curaidx = 0;
367: } else
368: curaidx++;
369: if (ifaceidx == curidx && altidx == curaidx)
370: return (d);
371: }
372: }
373: return (0);
374: }
375:
376: usb_endpoint_descriptor_t *
377: usbd_find_edesc(cd, ifaceidx, altidx, endptidx)
378: usb_config_descriptor_t *cd;
379: int ifaceidx;
380: int altidx;
381: int endptidx;
382: {
383: char *p = (char *)cd;
384: char *end = p + UGETW(cd->wTotalLength);
385: usb_interface_descriptor_t *d;
386: usb_endpoint_descriptor_t *e;
387: int curidx;
388:
389: d = usbd_find_idesc(cd, ifaceidx, altidx);
390: if (!d)
391: return (0);
392: if (endptidx >= d->bNumEndpoints) /* quick exit */
393: return (0);
394:
395: curidx = -1;
396: for (p = (char *)d + d->bLength; p < end; ) {
397: e = (usb_endpoint_descriptor_t *)p;
398: if (e->bLength == 0) /* bad descriptor */
399: break;
400: p += e->bLength;
401: if (p <= end && e->bDescriptorType == UDESC_INTERFACE)
402: return (0);
403: if (p <= end && e->bDescriptorType == UDESC_ENDPOINT) {
404: curidx++;
405: if (curidx == endptidx)
406: return (e);
407: }
1.1 augustss 408: }
409: return (0);
410: }
411:
412: usbd_status
1.13 augustss 413: usbd_fill_iface_data(dev, ifaceidx, altidx)
1.1 augustss 414: usbd_device_handle dev;
1.12 augustss 415: int ifaceidx;
1.13 augustss 416: int altidx;
1.1 augustss 417: {
1.12 augustss 418: usbd_interface_handle ifc = &dev->ifaces[ifaceidx];
1.1 augustss 419: char *p, *end;
420: int endpt, nendpt;
421:
1.18 augustss 422: DPRINTFN(4,("usbd_fill_iface_data: ifaceidx=%d altidx=%d\n",
1.14 drochner 423: ifaceidx, altidx));
1.1 augustss 424: ifc->device = dev;
1.13 augustss 425: ifc->idesc = usbd_find_idesc(dev->cdesc, ifaceidx, altidx);
1.19 augustss 426: if (ifc->idesc == 0)
427: return (USBD_INVAL);
1.13 augustss 428: ifc->index = ifaceidx;
429: ifc->altindex = altidx;
1.1 augustss 430: nendpt = ifc->idesc->bNumEndpoints;
431: DPRINTFN(10,("usbd_fill_iface_data: found idesc n=%d\n", nendpt));
432: if (nendpt != 0) {
433: ifc->endpoints = malloc(nendpt * sizeof(struct usbd_endpoint),
434: M_USB, M_NOWAIT);
435: if (ifc->endpoints == 0)
436: return (USBD_NOMEM);
437: } else
438: ifc->endpoints = 0;
439: ifc->priv = 0;
440: p = (char *)ifc->idesc + ifc->idesc->bLength;
441: end = (char *)dev->cdesc + UGETW(dev->cdesc->wTotalLength);
1.19 augustss 442: #define ed ((usb_endpoint_descriptor_t *)p)
1.1 augustss 443: for (endpt = 0; endpt < nendpt; endpt++) {
444: DPRINTFN(10,("usbd_fill_iface_data: endpt=%d\n", endpt));
445: for (; p < end; p += ed->bLength) {
446: ed = (usb_endpoint_descriptor_t *)p;
1.14 drochner 447: DPRINTFN(10,("usbd_fill_iface_data: p=%p end=%p "
448: "len=%d type=%d\n",
1.1 augustss 449: p, end, ed->bLength, ed->bDescriptorType));
1.24 augustss 450: if (p + ed->bLength <= end && ed->bLength != 0 &&
1.1 augustss 451: ed->bDescriptorType == UDESC_ENDPOINT)
1.24 augustss 452: goto found;
453: if (ed->bDescriptorType == UDESC_INTERFACE ||
454: ed->bLength == 0)
1.1 augustss 455: break;
456: }
1.24 augustss 457: /* passed end, or bad desc */
458: goto bad;
459: found:
1.1 augustss 460: ifc->endpoints[endpt].edesc = ed;
461: ifc->endpoints[endpt].refcnt = 0;
462: ifc->endpoints[endpt].toggle = 0;
1.24 augustss 463: p += ed->bLength;
1.1 augustss 464: }
1.19 augustss 465: #undef ed
1.1 augustss 466: LIST_INIT(&ifc->pipes);
467: return (USBD_NORMAL_COMPLETION);
1.24 augustss 468:
1.1 augustss 469: bad:
470: free(ifc->endpoints, M_USB);
1.24 augustss 471: return (USBD_INVAL);
1.1 augustss 472: }
473:
474: void
475: usbd_free_iface_data(dev, ifcno)
476: usbd_device_handle dev;
477: int ifcno;
478: {
479: usbd_interface_handle ifc = &dev->ifaces[ifcno];
480: if (ifc->endpoints)
481: free(ifc->endpoints, M_USB);
482: }
483:
1.7 augustss 484: static usbd_status
485: usbd_set_config(dev, conf)
486: usbd_device_handle dev;
487: int conf;
488: {
489: usb_device_request_t req;
490:
491: req.bmRequestType = UT_WRITE_DEVICE;
492: req.bRequest = UR_SET_CONFIG;
493: USETW(req.wValue, conf);
494: USETW(req.wIndex, 0);
495: USETW(req.wLength, 0);
496: return (usbd_do_request(dev, &req, 0));
497: }
498:
1.1 augustss 499: usbd_status
1.7 augustss 500: usbd_set_config_no(dev, no, msg)
1.1 augustss 501: usbd_device_handle dev;
502: int no;
1.7 augustss 503: int msg;
1.1 augustss 504: {
1.12 augustss 505: int index;
506: usb_config_descriptor_t cd;
507: usbd_status r;
508:
509: DPRINTFN(5,("usbd_set_config_no: %d\n", no));
510: /* Figure out what config index to use. */
511: for (index = 0; index < dev->ddesc.bNumConfigurations; index++) {
512: r = usbd_get_config_desc(dev, index, &cd);
513: if (r != USBD_NORMAL_COMPLETION)
514: return (r);
515: if (cd.bConfigurationValue == no)
516: return (usbd_set_config_index(dev, index, msg));
517: }
518: return (USBD_INVAL);
519: }
520:
521: usbd_status
522: usbd_set_config_index(dev, index, msg)
523: usbd_device_handle dev;
524: int index;
525: int msg;
526: {
1.1 augustss 527: usb_status_t ds;
528: usb_config_descriptor_t cd, *cdp;
529: usbd_status r;
1.12 augustss 530: int ifcidx, nifc, len, selfpowered, power;
1.1 augustss 531:
1.12 augustss 532: DPRINTFN(5,("usbd_set_config_index: dev=%p index=%d\n", dev, index));
1.1 augustss 533:
534: /* XXX check that all interfaces are idle */
535: if (dev->config != 0) {
1.12 augustss 536: DPRINTF(("usbd_set_config_index: free old config\n"));
1.1 augustss 537: /* Free all configuration data structures. */
538: nifc = dev->cdesc->bNumInterface;
1.12 augustss 539: for (ifcidx = 0; ifcidx < nifc; ifcidx++)
540: usbd_free_iface_data(dev, ifcidx);
1.1 augustss 541: free(dev->ifaces, M_USB);
542: free(dev->cdesc, M_USB);
543: dev->ifaces = 0;
544: dev->cdesc = 0;
545: dev->config = 0;
546: }
547:
548: /* Figure out what config number to use. */
1.12 augustss 549: r = usbd_get_config_desc(dev, index, &cd);
1.1 augustss 550: if (r != USBD_NORMAL_COMPLETION)
551: return (r);
552: len = UGETW(cd.wTotalLength);
553: cdp = malloc(len, M_USB, M_NOWAIT);
554: if (cdp == 0)
555: return (USBD_NOMEM);
1.12 augustss 556: r = usbd_get_desc(dev, UDESC_CONFIG, index, len, cdp);
1.1 augustss 557: if (r != USBD_NORMAL_COMPLETION)
558: goto bad;
1.18 augustss 559: if (cdp->bDescriptorType != UDESC_CONFIG) {
560: DPRINTFN(-1,("usbd_set_config_index: bad desc %d\n",
561: cdp->bDescriptorType));
562: r = USBD_INVAL;
563: goto bad;
564: }
1.1 augustss 565: selfpowered = 0;
566: if (cdp->bmAttributes & UC_SELF_POWERED) {
567: /* May be self powered. */
568: if (cdp->bmAttributes & UC_BUS_POWERED) {
569: /* Must ask device. */
1.33 augustss 570: r = usbd_get_device_status(dev, &ds);
571: if (r == USBD_NORMAL_COMPLETION &&
572: (UGETW(ds.wStatus) & UDS_SELF_POWERED))
573: selfpowered = 1;
1.14 drochner 574: DPRINTF(("usbd_set_config_index: status=0x%04x, "
575: "error=%d(%s)\n",
1.12 augustss 576: UGETW(ds.wStatus), r, usbd_error_strs[r]));
1.1 augustss 577: } else
578: selfpowered = 1;
579: }
1.14 drochner 580: DPRINTF(("usbd_set_config_index: (addr %d) attr=0x%02x, "
1.33 augustss 581: "selfpowered=%d, power=%d\n",
1.1 augustss 582: dev->address, cdp->bmAttributes,
1.33 augustss 583: selfpowered, cdp->bMaxPower * 2));
1.1 augustss 584: #ifdef USB_DEBUG
585: if (!dev->powersrc) {
1.12 augustss 586: printf("usbd_set_config_index: No power source?\n");
1.13 augustss 587: return (USBD_IOERROR);
1.1 augustss 588: }
589: #endif
590: power = cdp->bMaxPower * 2;
591: if (power > dev->powersrc->power) {
592: /* XXX print nicer message. */
1.7 augustss 593: if (msg)
1.18 augustss 594: printf("%s: device addr %d (config %d) exceeds power "
595: "budget, %d mA > %d mA\n",
596: USBDEVNAME(dev->bus->bdev), dev->address,
1.7 augustss 597: cdp->bConfigurationValue,
598: power, dev->powersrc->power);
1.1 augustss 599: r = USBD_NO_POWER;
600: goto bad;
601: }
602: dev->power = power;
603: dev->self_powered = selfpowered;
604:
1.18 augustss 605: DPRINTF(("usbd_set_config_index: set config %d\n",
606: cdp->bConfigurationValue));
1.1 augustss 607: r = usbd_set_config(dev, cdp->bConfigurationValue);
608: if (r != USBD_NORMAL_COMPLETION) {
1.14 drochner 609: DPRINTF(("usbd_set_config_index: setting config=%d failed, "
610: "error=%d(%s)\n",
1.12 augustss 611: cdp->bConfigurationValue, r, usbd_error_strs[r]));
1.1 augustss 612: goto bad;
613: }
1.12 augustss 614: DPRINTF(("usbd_set_config_index: setting new config %d\n",
1.1 augustss 615: cdp->bConfigurationValue));
616: nifc = cdp->bNumInterface;
617: dev->ifaces = malloc(nifc * sizeof(struct usbd_interface),
618: M_USB, M_NOWAIT);
619: if (dev->ifaces == 0) {
620: r = USBD_NOMEM;
621: goto bad;
622: }
1.12 augustss 623: DPRINTFN(5,("usbd_set_config_index: dev=%p cdesc=%p\n", dev, cdp));
1.1 augustss 624: dev->cdesc = cdp;
625: dev->config = cdp->bConfigurationValue;
1.12 augustss 626: for (ifcidx = 0; ifcidx < nifc; ifcidx++) {
627: r = usbd_fill_iface_data(dev, ifcidx, 0);
1.1 augustss 628: if (r != USBD_NORMAL_COMPLETION) {
1.12 augustss 629: while (--ifcidx >= 0)
630: usbd_free_iface_data(dev, ifcidx);
1.1 augustss 631: goto bad;
632: }
633: }
634:
635: return (USBD_NORMAL_COMPLETION);
636:
637: bad:
638: free(cdp, M_USB);
639: return (r);
640: }
641:
642: /* XXX add function for alternate settings */
643:
644: usbd_status
645: usbd_setup_pipe(dev, iface, ep, pipe)
646: usbd_device_handle dev;
647: usbd_interface_handle iface;
648: struct usbd_endpoint *ep;
649: usbd_pipe_handle *pipe;
650: {
651: usbd_pipe_handle p;
652: usbd_status r;
653:
654: DPRINTFN(1,("usbd_setup_pipe: dev=%p iface=%p ep=%p pipe=%p\n",
655: dev, iface, ep, pipe));
656: p = malloc(dev->bus->pipe_size, M_USB, M_NOWAIT);
657: if (p == 0)
658: return (USBD_NOMEM);
659: p->device = dev;
660: p->iface = iface;
661: p->endpoint = ep;
662: ep->refcnt++;
663: p->refcnt = 1;
664: p->intrreqh = 0;
665: p->running = 0;
1.34 ! augustss 666: p->repeat = 0;
1.1 augustss 667: SIMPLEQ_INIT(&p->queue);
668: r = dev->bus->open_pipe(p);
669: if (r != USBD_NORMAL_COMPLETION) {
1.19 augustss 670: DPRINTFN(-1,("usbd_setup_pipe: endpoint=0x%x failed, error=%d"
671: "(%s)\n",
1.12 augustss 672: ep->edesc->bEndpointAddress, r, usbd_error_strs[r]));
1.1 augustss 673: free(p, M_USB);
674: return (r);
675: }
676: *pipe = p;
677: return (USBD_NORMAL_COMPLETION);
678: }
679:
680: /* Abort the device control pipe. */
681: void
682: usbd_kill_pipe(pipe)
683: usbd_pipe_handle pipe;
684: {
685: pipe->methods->close(pipe);
686: pipe->endpoint->refcnt--;
687: free(pipe, M_USB);
688: }
689:
690: int
691: usbd_getnewaddr(bus)
692: usbd_bus_handle bus;
693: {
1.18 augustss 694: int addr;
1.1 augustss 695:
1.18 augustss 696: for (addr = 1; addr < USB_MAX_DEVICES; addr++)
697: if (bus->devices[addr] == 0)
698: return (addr);
1.1 augustss 699: return (-1);
700: }
701:
1.18 augustss 702:
703: usbd_status
704: usbd_probe_and_attach(parent, dev, port, addr)
705: bdevice *parent;
706: usbd_device_handle dev;
707: int port;
708: int addr;
709: {
710: struct usb_attach_arg uaa;
711: usb_device_descriptor_t *dd = &dev->ddesc;
1.20 augustss 712: int r, found, i, confi, nifaces;
1.34 ! augustss 713: struct device *dv;
1.20 augustss 714: usbd_interface_handle ifaces[256]; /* 256 is the absolute max */
1.18 augustss 715:
716: #if defined(__FreeBSD__)
1.28 augustss 717: /*
718: * XXX uaa is a static var. Not a problem as it _should_ be used only
719: * during probe and attach. Should be changed however.
720: */
1.18 augustss 721: bdevice bdev;
722: bdev = device_add_child(*parent, NULL, -1, &uaa);
1.26 augustss 723: if (!bdev) {
1.18 augustss 724: printf("%s: Device creation failed\n", USBDEVNAME(dev->bus->bdev));
725: return (USBD_INVAL);
726: }
727: #endif
728:
729: uaa.device = dev;
730: uaa.iface = 0;
1.20 augustss 731: uaa.ifaces = 0;
732: uaa.nifaces = 0;
1.18 augustss 733: uaa.usegeneric = 0;
734: uaa.port = port;
735: uaa.configno = UHUB_UNK_CONFIGURATION;
736: uaa.ifaceno = UHUB_UNK_INTERFACE;
1.32 augustss 737: uaa.vendor = UGETW(dd->idVendor);
738: uaa.product = UGETW(dd->idProduct);
739: uaa.release = UGETW(dd->bcdDevice);
1.18 augustss 740:
741: /* First try with device specific drivers. */
1.34 ! augustss 742: dv = USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print, usbd_submatch);
! 743: if (dv) {
! 744: dev->subdevs = malloc(2 * sizeof dv, M_USB, M_NOWAIT);
! 745: if (dev->subdevs == 0)
! 746: return (USBD_NOMEM);
! 747: dev->subdevs[0] = dv;
! 748: dev->subdevs[1] = 0;
1.18 augustss 749: return (USBD_NORMAL_COMPLETION);
1.34 ! augustss 750: }
1.18 augustss 751:
752: DPRINTF(("usbd_probe_and_attach: no device specific driver found\n"));
753:
754: /* Next try with interface drivers. */
755: for (confi = 0; confi < dd->bNumConfigurations; confi++) {
756: DPRINTFN(1,("usbd_probe_and_attach: trying config idx=%d\n",
757: confi));
758: r = usbd_set_config_index(dev, confi, 1);
759: if (r != USBD_NORMAL_COMPLETION) {
760: #ifdef USB_DEBUG
761: DPRINTF(("%s: port %d, set config at addr %d failed, "
762: "error=%d(%s)\n", USBDEVNAME(*parent), port,
763: addr, r, usbd_error_strs[r]));
764: #else
765: printf("%s: port %d, set config at addr %d failed\n",
766: USBDEVNAME(*parent), port, addr);
767: #endif
1.27 augustss 768: #if defined(__FreeBSD__)
769: device_delete_child(*parent, bdev);
770: #endif
771: return (r);
1.18 augustss 772: }
1.20 augustss 773: nifaces = dev->cdesc->bNumInterface;
1.23 augustss 774: uaa.configno = dev->cdesc->bConfigurationValue;
1.20 augustss 775: for (i = 0; i < nifaces; i++)
776: ifaces[i] = &dev->ifaces[i];
777: uaa.ifaces = ifaces;
778: uaa.nifaces = nifaces;
1.34 ! augustss 779: dev->subdevs = malloc((nifaces+1) * sizeof dv, M_USB,M_NOWAIT);
! 780: if (dev->subdevs == 0)
! 781: return (USBD_NOMEM);
1.20 augustss 782: for (found = i = 0; i < nifaces; i++) {
783: if (!ifaces[i])
784: continue; /* interface already claimed */
785: uaa.iface = ifaces[i];
786: uaa.ifaceno = ifaces[i]->idesc->bInterfaceNumber;
1.34 ! augustss 787: dv = USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print,
! 788: usbd_submatch);
! 789: if (dv) {
! 790: dev->subdevs[found++] = dv;
! 791: dev->subdevs[found] = 0;
1.20 augustss 792: ifaces[i] = 0; /* consumed */
793: }
1.18 augustss 794: }
795: if (found != 0)
796: return (USBD_NORMAL_COMPLETION);
1.34 ! augustss 797: free(dev->subdevs, M_USB);
! 798: dev->subdevs = 0;
1.18 augustss 799: }
1.21 augustss 800: /* No interfaces were attached in any of the configurations. */
1.34 ! augustss 801:
! 802: if (dd->bNumConfigurations > 1) /* don't change if only 1 config */
1.18 augustss 803: usbd_set_config_index(dev, 0, 0);
804:
805: DPRINTF(("usbd_probe_and_attach: no interface drivers found\n"));
806:
807: /* Finally try the generic driver. */
808: uaa.iface = 0;
809: uaa.usegeneric = 1;
810: uaa.configno = UHUB_UNK_CONFIGURATION;
811: uaa.ifaceno = UHUB_UNK_INTERFACE;
1.32 augustss 812: uaa.vendor = UHUB_UNK_VENDOR;
813: uaa.product = UHUB_UNK_PRODUCT;
814: uaa.release = UHUB_UNK_RELEASE;
1.34 ! augustss 815: dv = USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print, usbd_submatch);
! 816: if (dv) {
! 817: dev->subdevs = malloc(2 * sizeof dv, M_USB, M_NOWAIT);
! 818: if (dev->subdevs == 0)
! 819: return (USBD_NOMEM);
! 820: dev->subdevs[0] = dv;
! 821: dev->subdevs[1] = 0;
1.18 augustss 822: return (USBD_NORMAL_COMPLETION);
1.34 ! augustss 823: }
1.18 augustss 824:
825: /*
826: * The generic attach failed, but leave the device as it is.
827: * We just did not find any drivers, that's all. The device is
828: * fully operational and not harming anyone.
829: */
830: DPRINTF(("usbd_probe_and_attach: generic attach failed\n"));
1.27 augustss 831: #if defined(__FreeBSD__)
832: /*
833: * XXX should we delete the child again? Left for now to avoid dangling
834: * references.
835: device_delete_child(*parent, bdev);
836: */
837: #endif
838: return (USBD_NORMAL_COMPLETION);
1.18 augustss 839: }
840:
841:
842:
1.1 augustss 843: /*
844: * Called when a new device has been put in the powered state,
845: * but not yet in the addressed state.
846: * Get initial descriptor, set the address, get full descriptor,
847: * and attach a driver.
848: */
849: usbd_status
850: usbd_new_device(parent, bus, depth, lowspeed, port, up)
1.18 augustss 851: bdevice *parent;
1.1 augustss 852: usbd_bus_handle bus;
853: int depth;
854: int lowspeed;
855: int port;
856: struct usbd_port *up;
857: {
858: usbd_device_handle dev;
1.18 augustss 859: usb_device_descriptor_t *dd;
1.1 augustss 860: usbd_status r;
861: int addr;
1.18 augustss 862: int i;
1.1 augustss 863:
864: DPRINTF(("usbd_new_device bus=%p depth=%d lowspeed=%d\n",
865: bus, depth, lowspeed));
866: addr = usbd_getnewaddr(bus);
867: if (addr < 0) {
1.18 augustss 868: printf("%s: No free USB addresses, new device ignored.\n",
869: USBDEVNAME(bus->bdev));
1.1 augustss 870: return (USBD_NO_ADDR);
871: }
872:
873: dev = malloc(sizeof *dev, M_USB, M_NOWAIT);
874: if (dev == 0)
875: return (USBD_NOMEM);
876: memset(dev, 0, sizeof(*dev));
877:
878: dev->bus = bus;
879:
880: /* Set up default endpoint handle. */
881: dev->def_ep.edesc = &dev->def_ep_desc;
882:
883: /* Set up default endpoint descriptor. */
884: dev->def_ep_desc.bLength = USB_ENDPOINT_DESCRIPTOR_SIZE;
885: dev->def_ep_desc.bDescriptorType = UDESC_ENDPOINT;
886: dev->def_ep_desc.bEndpointAddress = USB_CONTROL_ENDPOINT;
887: dev->def_ep_desc.bmAttributes = UE_CONTROL;
888: USETW(dev->def_ep_desc.wMaxPacketSize, USB_MAX_IPACKET);
889: dev->def_ep_desc.bInterval = 0;
890:
891: dev->quirks = &usbd_no_quirk;
892: dev->address = USB_START_ADDR;
1.4 augustss 893: dev->ddesc.bMaxPacketSize = 0;
1.1 augustss 894: dev->lowspeed = lowspeed != 0;
895: dev->depth = depth;
896: dev->powersrc = up;
1.22 augustss 897: dev->langid = USBD_NOLANG;
1.1 augustss 898:
899: /* Establish the the default pipe. */
900: r = usbd_setup_pipe(dev, 0, &dev->def_ep, &dev->default_pipe);
1.18 augustss 901: if (r != USBD_NORMAL_COMPLETION) {
902: usbd_remove_device(dev, up);
1.19 augustss 903: return (r);
1.18 augustss 904: }
1.1 augustss 905:
906: up->device = dev;
1.18 augustss 907: dd = &dev->ddesc;
1.6 augustss 908: /* Try a few times in case the device is slow (i.e. outside specs.) */
909: for (i = 0; i < 5; i++) {
910: /* Get the first 8 bytes of the device descriptor. */
1.18 augustss 911: r = usbd_get_desc(dev, UDESC_DEVICE, 0, USB_MAX_IPACKET, dd);
1.6 augustss 912: if (r == USBD_NORMAL_COMPLETION)
913: break;
1.23 augustss 914: usbd_delay_ms(dev, 200);
1.6 augustss 915: }
1.1 augustss 916: if (r != USBD_NORMAL_COMPLETION) {
1.14 drochner 917: DPRINTFN(-1, ("usbd_new_device: addr=%d, getting first desc "
918: "failed\n",
1.6 augustss 919: addr));
1.18 augustss 920: usbd_remove_device(dev, up);
921: return (r);
922: }
923:
924: if (dd->bDescriptorType != UDESC_DEVICE) {
925: /* Illegal device descriptor */
926: DPRINTFN(-1,("usbd_new_device: illegal descriptor %d\n",
927: dd->bDescriptorType));
928: usbd_remove_device(dev, up);
929: return (USBD_INVAL);
1.1 augustss 930: }
931:
1.14 drochner 932: DPRINTF(("usbd_new_device: adding unit addr=%d, rev=%02x, class=%d, "
933: "subclass=%d, protocol=%d, maxpacket=%d, ls=%d\n",
1.18 augustss 934: addr,UGETW(dd->bcdUSB), dd->bDeviceClass, dd->bDeviceSubClass,
935: dd->bDeviceProtocol, dd->bMaxPacketSize, dev->lowspeed));
1.4 augustss 936:
1.18 augustss 937: USETW(dev->def_ep_desc.wMaxPacketSize, dd->bMaxPacketSize);
1.1 augustss 938:
939: /* Get the full device descriptor. */
1.18 augustss 940: r = usbd_get_device_desc(dev, dd);
1.1 augustss 941: if (r != USBD_NORMAL_COMPLETION) {
1.14 drochner 942: DPRINTFN(-1, ("usbd_new_device: addr=%d, getting full desc "
943: "failed\n", addr));
1.18 augustss 944: usbd_remove_device(dev, up);
945: return (r);
1.1 augustss 946: }
947:
948: /* Figure out what's wrong with this device. */
1.18 augustss 949: dev->quirks = usbd_find_quirk(dd);
1.1 augustss 950:
951: /* Set the address */
952: r = usbd_set_address(dev, addr);
953: if (r != USBD_NORMAL_COMPLETION) {
954: DPRINTFN(-1,("usb_new_device: set address %d failed\n",addr));
955: r = USBD_SET_ADDR_FAILED;
1.18 augustss 956: usbd_remove_device(dev, up);
957: return (r);
1.1 augustss 958: }
1.18 augustss 959: /* Allow device time to set new address */
1.23 augustss 960: usbd_delay_ms(dev, USB_SET_ADDRESS_SETTLE);
1.18 augustss 961:
1.1 augustss 962: dev->address = addr; /* New device address now */
963: bus->devices[addr] = dev;
964:
965: /* Assume 100mA bus powered for now. Changed when configured. */
966: dev->power = USB_MIN_POWER;
967: dev->self_powered = 0;
968:
969: DPRINTF(("usbd_new_device: new dev (addr %d), dev=%p, parent=%p\n",
970: addr, dev, parent));
971:
1.18 augustss 972: r = usbd_probe_and_attach(parent, dev, port, addr);
973: if (r != USBD_NORMAL_COMPLETION) {
974: usbd_remove_device(dev, up);
975: return (r);
976: }
977:
978: return (USBD_NORMAL_COMPLETION);
979: }
1.1 augustss 980:
1.18 augustss 981: void
982: usbd_remove_device(dev, up)
983: usbd_device_handle dev;
984: struct usbd_port *up;
985: {
986: DPRINTF(("usbd_remove_device: %p\n", dev));
987:
988: if (dev->default_pipe)
989: usbd_kill_pipe(dev->default_pipe);
990: up->device = 0;
991: dev->bus->devices[dev->address] = 0;
1.1 augustss 992:
993: free(dev, M_USB);
994: }
995:
1.18 augustss 996: #if defined(__NetBSD__)
1.1 augustss 997: int
998: usbd_print(aux, pnp)
999: void *aux;
1000: const char *pnp;
1001: {
1002: struct usb_attach_arg *uaa = aux;
1003: char devinfo[1024];
1004:
1005: DPRINTFN(15, ("usbd_print dev=%p\n", uaa->device));
1006: if (pnp) {
1007: if (!uaa->usegeneric)
1008: return (QUIET);
1009: usbd_devinfo(uaa->device, 1, devinfo);
1.11 augustss 1010: printf("%s, %s", devinfo, pnp);
1.1 augustss 1011: }
1012: if (uaa->port != 0)
1.11 augustss 1013: printf(" port %d", uaa->port);
1014: if (uaa->configno != UHUB_UNK_CONFIGURATION)
1015: printf(" configuration %d", uaa->configno);
1016: if (uaa->ifaceno != UHUB_UNK_INTERFACE)
1017: printf(" interface %d", uaa->ifaceno);
1.32 augustss 1018: #if 0
1019: /*
1020: * It gets very crowded with these locators on the attach line.
1021: * They are not really needed since they are printed in the clear
1022: * by each driver.
1023: */
1024: if (uaa->vendor != UHUB_UNK_VENDOR)
1025: printf(" vendor 0x%04x", uaa->vendor);
1026: if (uaa->product != UHUB_UNK_PRODUCT)
1027: printf(" product 0x%04x", uaa->product);
1028: if (uaa->release != UHUB_UNK_RELEASE)
1029: printf(" release 0x%04x", uaa->release);
1030: #endif
1.1 augustss 1031: return (UNCONF);
1032: }
1033:
1034: int
1035: usbd_submatch(parent, cf, aux)
1036: struct device *parent;
1037: struct cfdata *cf;
1038: void *aux;
1039: {
1040: struct usb_attach_arg *uaa = aux;
1041:
1.11 augustss 1042: if ((uaa->port != 0 &&
1043: cf->uhubcf_port != UHUB_UNK_PORT &&
1044: cf->uhubcf_port != uaa->port) ||
1045: (uaa->configno != UHUB_UNK_CONFIGURATION &&
1046: cf->uhubcf_configuration != UHUB_UNK_CONFIGURATION &&
1047: cf->uhubcf_configuration != uaa->configno) ||
1048: (uaa->ifaceno != UHUB_UNK_INTERFACE &&
1049: cf->uhubcf_interface != UHUB_UNK_INTERFACE &&
1.32 augustss 1050: cf->uhubcf_interface != uaa->ifaceno) ||
1051: (uaa->vendor != UHUB_UNK_VENDOR &&
1052: cf->uhubcf_vendor != UHUB_UNK_VENDOR &&
1053: cf->uhubcf_vendor != uaa->vendor) ||
1054: (uaa->product != UHUB_UNK_PRODUCT &&
1055: cf->uhubcf_product != UHUB_UNK_PRODUCT &&
1056: cf->uhubcf_product != uaa->product) ||
1057: (uaa->release != UHUB_UNK_RELEASE &&
1058: cf->uhubcf_release != UHUB_UNK_RELEASE &&
1059: cf->uhubcf_release != uaa->release)
1060: )
1.1 augustss 1061: return 0;
1062: return ((*cf->cf_attach->ca_match)(parent, cf, aux));
1.13 augustss 1063: }
1.18 augustss 1064:
1065: #elif defined(__FreeBSD__)
1066: static void
1067: usbd_bus_print_child(device_t bus, device_t dev)
1068: {
1069: /* FIXME print the device address and the configuration used
1070: */
1071: }
1072: #endif
1.19 augustss 1073:
1074: usbd_status
1075: usb_insert_transfer(reqh)
1076: usbd_request_handle reqh;
1077: {
1078: usbd_pipe_handle pipe = reqh->pipe;
1079:
1080: SIMPLEQ_INSERT_TAIL(&pipe->queue, reqh, next);
1081: if (pipe->running)
1082: return (USBD_IN_PROGRESS);
1083: pipe->running = 1;
1084: return (USBD_NORMAL_COMPLETION);
1085: }
1086:
1087: void
1088: usb_start_next(pipe)
1089: usbd_pipe_handle pipe;
1090: {
1091: usbd_request_handle reqh;
1092: usbd_status r;
1093:
1.30 augustss 1094: DPRINTFN(10, ("usb_start_next: pipe=%p\n", pipe));
1095:
1.19 augustss 1096: #ifdef DIAGNOSTIC
1.31 augustss 1097: if (!pipe) {
1098: printf("usb_start_next: pipe == 0\n");
1099: return;
1100: }
1101: if (!pipe->methods || !pipe->methods->start) {
1102: printf("usb_start_next: no start method\n");
1103: return;
1104: }
1.19 augustss 1105: if (SIMPLEQ_FIRST(&pipe->queue) == 0) {
1106: printf("usb_start_next: empty\n");
1107: return;
1108: }
1109: #endif
1110:
1111: /* First remove remove old */
1112: SIMPLEQ_REMOVE_HEAD(&pipe->queue, SIMPLEQ_FIRST(&pipe->queue), next);
1113: reqh = SIMPLEQ_FIRST(&pipe->queue);
1114: DPRINTFN(5, ("usb_start_next: start reqh=%p\n", reqh));
1115: if (!reqh)
1116: pipe->running = 0;
1117: else {
1118: r = pipe->methods->start(reqh);
1119: if (r != USBD_IN_PROGRESS) {
1120: printf("usb_start_next: error=%d\n", r);
1121: pipe->running = 0;
1122: /* XXX do what? */
1123: }
1124: }
1125: }
1.13 augustss 1126:
1127: void
1128: usbd_fill_deviceinfo(dev, di)
1129: usbd_device_handle dev;
1130: struct usb_device_info *di;
1131: {
1132: struct usbd_port *p;
1133: int i, r, s;
1134:
1135: di->config = dev->config;
1136: usbd_devinfo_vp(dev, di->vendor, di->product);
1.32 augustss 1137: usbd_printBCD(di->release, UGETW(dev->ddesc.bcdDevice));
1.21 augustss 1138: di->vendorNo = UGETW(dev->ddesc.idVendor);
1139: di->productNo = UGETW(dev->ddesc.idProduct);
1.13 augustss 1140: di->class = dev->ddesc.bDeviceClass;
1141: di->power = dev->self_powered ? 0 : dev->power;
1142: di->lowspeed = dev->lowspeed;
1143: di->addr = dev->address;
1144: if (dev->hub) {
1145: for (i = 0;
1146: i < sizeof(di->ports) / sizeof(di->ports[0]) &&
1147: i < dev->hub->hubdesc.bNbrPorts;
1148: i++) {
1149: p = &dev->hub->ports[i];
1150: if (p->device)
1151: r = p->device->address;
1152: else {
1153: s = UGETW(p->status.wPortStatus);
1154: if (s & UPS_PORT_ENABLED)
1155: r = USB_PORT_ENABLED;
1156: else if (s & UPS_SUSPEND)
1157: r = USB_PORT_SUSPENDED;
1158: else if (s & UPS_PORT_POWER)
1159: r = USB_PORT_POWERED;
1160: else
1161: r = USB_PORT_DISABLED;
1162: }
1163: di->ports[i] = r;
1164: }
1165: di->nports = dev->hub->hubdesc.bNbrPorts;
1166: } else
1167: di->nports = 0;
1.34 ! augustss 1168: }
! 1169:
! 1170: void
! 1171: usb_free_device(dev)
! 1172: usbd_device_handle dev;
! 1173: {
! 1174: int ifcidx, nifc;
! 1175:
! 1176: if (dev->default_pipe)
! 1177: usbd_kill_pipe(dev->default_pipe);
! 1178: if (dev->ifaces) {
! 1179: nifc = dev->cdesc->bNumInterface;
! 1180: for (ifcidx = 0; ifcidx < nifc; ifcidx++)
! 1181: usbd_free_iface_data(dev, ifcidx);
! 1182: free(dev->ifaces, M_USB);
! 1183: }
! 1184: if (dev->cdesc)
! 1185: free(dev->cdesc, M_USB);
! 1186: if (dev->subdevs)
! 1187: free(dev->subdevs, M_USB);
! 1188: free(dev, M_USB);
1.1 augustss 1189: }
CVSweb <webmaster@jp.NetBSD.org>