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