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