Annotation of src/sys/dev/usb/usb_subr.c, Revision 1.143.6.1
1.143.6.1! mjf 1: /* $NetBSD: usb_subr.c,v 1.148 2007/06/30 09:17:45 mlelstv 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: /*
1.121 mycroft 5: * Copyright (c) 1998, 2004 The NetBSD Foundation, Inc.
1.1 augustss 6: * All rights reserved.
7: *
1.9 augustss 8: * This code is derived from software contributed to The NetBSD Foundation
1.76 augustss 9: * by Lennart Augustsson (lennart@augustsson.net) at
1.9 augustss 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: */
1.91 lukem 40:
41: #include <sys/cdefs.h>
1.143.6.1! mjf 42: __KERNEL_RCSID(0, "$NetBSD: usb_subr.c,v 1.148 2007/06/30 09:17:45 mlelstv Exp $");
1.104 martin 43:
1.140 pavel 44: #include "opt_compat_netbsd.h"
1.104 martin 45: #include "opt_usbverbose.h"
1.1 augustss 46:
47: #include <sys/param.h>
48: #include <sys/systm.h>
49: #include <sys/kernel.h>
50: #include <sys/malloc.h>
1.37 augustss 51: #if defined(__NetBSD__) || defined(__OpenBSD__)
1.1 augustss 52: #include <sys/device.h>
1.56 augustss 53: #include <sys/select.h>
1.18 augustss 54: #elif defined(__FreeBSD__)
55: #include <sys/module.h>
56: #include <sys/bus.h>
57: #endif
1.1 augustss 58: #include <sys/proc.h>
1.46 augustss 59:
60: #include <machine/bus.h>
1.1 augustss 61:
62: #include <dev/usb/usb.h>
63:
64: #include <dev/usb/usbdi.h>
65: #include <dev/usb/usbdi_util.h>
66: #include <dev/usb/usbdivar.h>
67: #include <dev/usb/usbdevs.h>
68: #include <dev/usb/usb_quirks.h>
69:
1.27 augustss 70: #if defined(__FreeBSD__)
71: #include <machine/clock.h>
72: #define delay(d) DELAY(d)
73: #endif
74:
1.1 augustss 75: #ifdef USB_DEBUG
1.35 augustss 76: #define DPRINTF(x) if (usbdebug) logprintf x
77: #define DPRINTFN(n,x) if (usbdebug>(n)) logprintf x
1.1 augustss 78: extern int usbdebug;
79: #else
80: #define DPRINTF(x)
81: #define DPRINTFN(n,x)
82: #endif
83:
1.82 augustss 84: Static usbd_status usbd_set_config(usbd_device_handle, int);
1.124 augustss 85: Static void usbd_devinfo(usbd_device_handle, int, char *, size_t);
1.123 augustss 86: Static void usbd_devinfo_vp(usbd_device_handle dev,
1.139 pavel 87: char *v,
88: char *p, int usedev,
89: int useencoded );
1.78 augustss 90: Static int usbd_getnewaddr(usbd_bus_handle bus);
1.56 augustss 91: #if defined(__NetBSD__)
1.118 drochner 92: Static int usbd_print(void *, const char *);
1.143.6.1! mjf 93: Static int usbd_ifprint(void *, const char *);
1.118 drochner 94: Static int usbd_submatch(device_ptr_t, struct cfdata *,
1.129 drochner 95: const int *, void *);
1.143.6.1! mjf 96: Static int usbd_ifsubmatch(device_ptr_t, struct cfdata *,
! 97: const int *, void *);
1.37 augustss 98: #elif defined(__OpenBSD__)
1.78 augustss 99: Static int usbd_print(void *aux, const char *pnp);
100: Static int usbd_submatch(device_ptr_t, void *, void *);
1.18 augustss 101: #endif
1.78 augustss 102: Static void usbd_free_iface_data(usbd_device_handle dev, int ifcno);
103: Static void usbd_kill_pipe(usbd_pipe_handle);
104: Static usbd_status usbd_probe_and_attach(device_ptr_t parent,
105: usbd_device_handle dev, int port, int addr);
1.1 augustss 106:
1.69 augustss 107: Static u_int32_t usb_cookie_no = 0;
1.27 augustss 108:
1.1 augustss 109: #ifdef USBVERBOSE
110: typedef u_int16_t usb_vendor_id_t;
111: typedef u_int16_t usb_product_id_t;
112:
113: /*
114: * Descriptions of of known vendors and devices ("products").
115: */
1.122 mycroft 116: struct usb_vendor {
117: usb_vendor_id_t vendor;
1.126 christos 118: const char *vendorname;
1.122 mycroft 119: };
120: struct usb_product {
1.1 augustss 121: usb_vendor_id_t vendor;
122: usb_product_id_t product;
1.126 christos 123: const char *productname;
1.1 augustss 124: };
125:
126: #include <dev/usb/usbdevs_data.h>
127: #endif /* USBVERBOSE */
128:
1.84 jdolecek 129: Static const char * const usbd_error_strs[] = {
1.12 augustss 130: "NORMAL_COMPLETION",
131: "IN_PROGRESS",
132: "PENDING_REQUESTS",
133: "NOT_STARTED",
134: "INVAL",
135: "NOMEM",
136: "CANCELLED",
137: "BAD_ADDRESS",
138: "IN_USE",
139: "NO_ADDR",
140: "SET_ADDR_FAILED",
141: "NO_POWER",
142: "TOO_DEEP",
143: "IOERROR",
144: "NOT_CONFIGURED",
145: "TIMEOUT",
146: "SHORT_XFER",
147: "STALLED",
1.33 augustss 148: "INTERRUPTED",
1.12 augustss 149: "XXX",
150: };
1.1 augustss 151:
1.42 thorpej 152: const char *
1.78 augustss 153: usbd_errstr(usbd_status err)
1.39 augustss 154: {
155: static char buffer[5];
156:
1.42 thorpej 157: if (err < USBD_ERROR_MAX) {
1.39 augustss 158: return usbd_error_strs[err];
159: } else {
160: snprintf(buffer, sizeof buffer, "%d", err);
161: return buffer;
162: }
163: }
164:
1.13 augustss 165: usbd_status
1.78 augustss 166: usbd_get_string_desc(usbd_device_handle dev, int sindex, int langid,
1.114 mycroft 167: usb_string_descriptor_t *sdesc, int *sizep)
1.13 augustss 168: {
169: usb_device_request_t req;
1.116 mycroft 170: usbd_status err;
171: int actlen;
1.13 augustss 172:
173: req.bmRequestType = UT_READ_DEVICE;
174: req.bRequest = UR_GET_DESCRIPTOR;
175: USETW2(req.wValue, UDESC_STRING, sindex);
176: USETW(req.wIndex, langid);
1.143.6.1! mjf 177: USETW(req.wLength, 2); /* only size byte first */
1.116 mycroft 178: err = usbd_do_request_flags(dev, &req, sdesc, USBD_SHORT_XFER_OK,
179: &actlen, USBD_DEFAULT_TIMEOUT);
180: if (err)
181: return (err);
182:
1.143.6.1! mjf 183: if (actlen < 2)
! 184: return (USBD_SHORT_XFER);
! 185:
! 186: USETW(req.wLength, sdesc->bLength); /* the whole string */
! 187: err = usbd_do_request_flags(dev, &req, sdesc, USBD_SHORT_XFER_OK,
! 188: &actlen, USBD_DEFAULT_TIMEOUT);
! 189: if (err)
! 190: return (err);
! 191:
1.116 mycroft 192: if (actlen != sdesc->bLength) {
193: DPRINTFN(-1, ("usbd_get_string_desc: expected %d, got %d\n",
194: sdesc->bLength, actlen));
195: }
196:
197: *sizep = actlen;
198: return (USBD_NORMAL_COMPLETION);
1.13 augustss 199: }
200:
1.128 enami 201: static void
202: usbd_trim_spaces(char *p)
1.83 augustss 203: {
1.128 enami 204: char *q, *e;
1.83 augustss 205:
1.128 enami 206: q = e = p;
207: while (*q == ' ') /* skip leading spaces */
1.85 augustss 208: q++;
1.128 enami 209: while ((*p = *q++)) /* copy string */
210: if (*p++ != ' ') /* remember last non-space */
211: e = p;
212: *e = '\0'; /* kill trailing spaces */
1.83 augustss 213: }
214:
1.123 augustss 215: Static void
1.139 pavel 216: usbd_devinfo_vp(usbd_device_handle dev, char *v,
217: char *p, int usedev, int useencoded)
1.1 augustss 218: {
219: usb_device_descriptor_t *udd = &dev->ddesc;
1.2 is 220: #ifdef USBVERBOSE
1.122 mycroft 221: int n;
1.2 is 222: #endif
1.1 augustss 223:
1.128 enami 224: v[0] = p[0] = '\0';
225: if (dev == NULL)
1.52 augustss 226: return;
227:
1.82 augustss 228: if (usedev) {
1.139 pavel 229: if (usbd_get_string0(dev, udd->iManufacturer, v, useencoded) ==
1.128 enami 230: USBD_NORMAL_COMPLETION)
231: usbd_trim_spaces(v);
1.139 pavel 232: if (usbd_get_string0(dev, udd->iProduct, p, useencoded) ==
1.128 enami 233: USBD_NORMAL_COMPLETION)
234: usbd_trim_spaces(p);
1.82 augustss 235: }
1.128 enami 236: /* There is no need for strlcpy & snprintf below. */
1.1 augustss 237: #ifdef USBVERBOSE
1.128 enami 238: if (v[0] == '\0')
1.122 mycroft 239: for (n = 0; n < usb_nvendors; n++)
1.128 enami 240: if (usb_vendors[n].vendor == UGETW(udd->idVendor)) {
241: strcpy(v, usb_vendors[n].vendorname);
242: break;
243: }
244: if (p[0] == '\0')
1.122 mycroft 245: for (n = 0; n < usb_nproducts; n++)
246: if (usb_products[n].vendor == UGETW(udd->idVendor) &&
1.128 enami 247: usb_products[n].product == UGETW(udd->idProduct)) {
248: strcpy(p, usb_products[n].productname);
249: break;
250: }
1.1 augustss 251: #endif
1.128 enami 252: if (v[0] == '\0')
1.123 augustss 253: sprintf(v, "vendor 0x%04x", UGETW(udd->idVendor));
1.128 enami 254: if (p[0] == '\0')
1.123 augustss 255: sprintf(p, "product 0x%04x", UGETW(udd->idProduct));
1.1 augustss 256: }
257:
258: int
1.113 itojun 259: usbd_printBCD(char *cp, size_t l, int bcd)
1.1 augustss 260: {
1.113 itojun 261: return (snprintf(cp, l, "%x.%02x", bcd >> 8, bcd & 0xff));
1.1 augustss 262: }
263:
1.124 augustss 264: Static void
1.113 itojun 265: usbd_devinfo(usbd_device_handle dev, int showclass, char *cp, size_t l)
1.1 augustss 266: {
267: usb_device_descriptor_t *udd = &dev->ddesc;
1.133 christos 268: char *vendor, *product;
1.1 augustss 269: int bcdDevice, bcdUSB;
1.113 itojun 270: char *ep;
271:
1.133 christos 272: vendor = malloc(USB_MAX_ENCODED_STRING_LEN * 2, M_USB, M_NOWAIT);
273: if (vendor == NULL) {
274: *cp = '\0';
275: return;
276: }
277: product = &vendor[USB_MAX_ENCODED_STRING_LEN];
278:
1.113 itojun 279: ep = cp + l;
1.1 augustss 280:
1.139 pavel 281: usbd_devinfo_vp(dev, vendor, product, 1, 1);
1.113 itojun 282: cp += snprintf(cp, ep - cp, "%s %s", vendor, product);
1.1 augustss 283: if (showclass)
1.113 itojun 284: cp += snprintf(cp, ep - cp, ", class %d/%d",
285: udd->bDeviceClass, udd->bDeviceSubClass);
1.1 augustss 286: bcdUSB = UGETW(udd->bcdUSB);
287: bcdDevice = UGETW(udd->bcdDevice);
1.113 itojun 288: cp += snprintf(cp, ep - cp, ", rev ");
289: cp += usbd_printBCD(cp, ep - cp, bcdUSB);
1.1 augustss 290: *cp++ = '/';
1.113 itojun 291: cp += usbd_printBCD(cp, ep - cp, bcdDevice);
292: cp += snprintf(cp, ep - cp, ", addr %d", dev->address);
1.10 augustss 293: *cp = 0;
1.133 christos 294: free(vendor, M_USB);
1.1 augustss 295: }
296:
1.124 augustss 297: char *
298: usbd_devinfo_alloc(usbd_device_handle dev, int showclass)
299: {
300: char *devinfop;
301:
302: devinfop = malloc(DEVINFOSIZE, M_TEMP, M_WAITOK);
303: usbd_devinfo(dev, showclass, devinfop, DEVINFOSIZE);
304: return devinfop;
305: }
306:
307: void
308: usbd_devinfo_free(char *devinfop)
309: {
310: free(devinfop, M_TEMP);
311: }
312:
1.1 augustss 313: /* Delay for a certain number of ms */
314: void
1.78 augustss 315: usb_delay_ms(usbd_bus_handle bus, u_int ms)
1.1 augustss 316: {
317: /* Wait at least two clock ticks so we know the time has passed. */
1.64 augustss 318: if (bus->use_polling || cold)
1.1 augustss 319: delay((ms+1) * 1000);
320: else
321: tsleep(&ms, PRIBIO, "usbdly", (ms*hz+999)/1000 + 1);
322: }
323:
1.23 augustss 324: /* Delay given a device handle. */
325: void
1.78 augustss 326: usbd_delay_ms(usbd_device_handle dev, u_int ms)
1.23 augustss 327: {
328: usb_delay_ms(dev->bus, ms);
329: }
330:
1.1 augustss 331: usbd_status
1.78 augustss 332: usbd_reset_port(usbd_device_handle dev, int port, usb_port_status_t *ps)
1.1 augustss 333: {
334: usb_device_request_t req;
1.53 augustss 335: usbd_status err;
1.1 augustss 336: int n;
1.99 augustss 337:
1.1 augustss 338: req.bmRequestType = UT_WRITE_CLASS_OTHER;
339: req.bRequest = UR_SET_FEATURE;
340: USETW(req.wValue, UHF_PORT_RESET);
341: USETW(req.wIndex, port);
342: USETW(req.wLength, 0);
1.53 augustss 343: err = usbd_do_request(dev, &req, 0);
1.39 augustss 344: DPRINTFN(1,("usbd_reset_port: port %d reset done, error=%s\n",
1.53 augustss 345: port, usbd_errstr(err)));
346: if (err)
347: return (err);
1.1 augustss 348: n = 10;
349: do {
350: /* Wait for device to recover from reset. */
1.23 augustss 351: usbd_delay_ms(dev, USB_PORT_RESET_DELAY);
1.53 augustss 352: err = usbd_get_port_status(dev, port, ps);
353: if (err) {
354: DPRINTF(("usbd_reset_port: get status failed %d\n",
355: err));
356: return (err);
1.1 augustss 357: }
1.92 augustss 358: /* If the device disappeared, just give up. */
359: if (!(UGETW(ps->wPortStatus) & UPS_CURRENT_CONNECT_STATUS))
360: return (USBD_NORMAL_COMPLETION);
1.1 augustss 361: } while ((UGETW(ps->wPortChange) & UPS_C_PORT_RESET) == 0 && --n > 0);
1.73 augustss 362: if (n == 0)
363: return (USBD_TIMEOUT);
1.53 augustss 364: err = usbd_clear_port_feature(dev, port, UHF_C_PORT_RESET);
1.1 augustss 365: #ifdef USB_DEBUG
1.53 augustss 366: if (err)
367: DPRINTF(("usbd_reset_port: clear port feature failed %d\n",
368: err));
1.1 augustss 369: #endif
1.18 augustss 370:
371: /* Wait for the device to recover from reset. */
1.23 augustss 372: usbd_delay_ms(dev, USB_PORT_RESET_RECOVERY);
1.53 augustss 373: return (err);
1.1 augustss 374: }
375:
1.12 augustss 376: usb_interface_descriptor_t *
1.78 augustss 377: usbd_find_idesc(usb_config_descriptor_t *cd, int ifaceidx, int altidx)
1.12 augustss 378: {
379: char *p = (char *)cd;
380: char *end = p + UGETW(cd->wTotalLength);
381: usb_interface_descriptor_t *d;
1.19 augustss 382: int curidx, lastidx, curaidx = 0;
1.12 augustss 383:
1.19 augustss 384: for (curidx = lastidx = -1; p < end; ) {
1.12 augustss 385: d = (usb_interface_descriptor_t *)p;
1.18 augustss 386: DPRINTFN(4,("usbd_find_idesc: idx=%d(%d) altidx=%d(%d) len=%d "
1.99 augustss 387: "type=%d\n",
1.18 augustss 388: ifaceidx, curidx, altidx, curaidx,
389: d->bLength, d->bDescriptorType));
1.12 augustss 390: if (d->bLength == 0) /* bad descriptor */
391: break;
392: p += d->bLength;
393: if (p <= end && d->bDescriptorType == UDESC_INTERFACE) {
1.19 augustss 394: if (d->bInterfaceNumber != lastidx) {
395: lastidx = d->bInterfaceNumber;
1.12 augustss 396: curidx++;
397: curaidx = 0;
398: } else
399: curaidx++;
400: if (ifaceidx == curidx && altidx == curaidx)
401: return (d);
402: }
403: }
1.58 augustss 404: return (NULL);
1.12 augustss 405: }
406:
407: usb_endpoint_descriptor_t *
1.99 augustss 408: usbd_find_edesc(usb_config_descriptor_t *cd, int ifaceidx, int altidx,
1.78 augustss 409: int endptidx)
1.12 augustss 410: {
411: char *p = (char *)cd;
412: char *end = p + UGETW(cd->wTotalLength);
413: usb_interface_descriptor_t *d;
414: usb_endpoint_descriptor_t *e;
415: int curidx;
416:
417: d = usbd_find_idesc(cd, ifaceidx, altidx);
1.53 augustss 418: if (d == NULL)
1.58 augustss 419: return (NULL);
1.12 augustss 420: if (endptidx >= d->bNumEndpoints) /* quick exit */
1.58 augustss 421: return (NULL);
1.12 augustss 422:
423: curidx = -1;
424: for (p = (char *)d + d->bLength; p < end; ) {
425: e = (usb_endpoint_descriptor_t *)p;
426: if (e->bLength == 0) /* bad descriptor */
427: break;
428: p += e->bLength;
429: if (p <= end && e->bDescriptorType == UDESC_INTERFACE)
1.58 augustss 430: return (NULL);
1.12 augustss 431: if (p <= end && e->bDescriptorType == UDESC_ENDPOINT) {
432: curidx++;
433: if (curidx == endptidx)
434: return (e);
435: }
1.1 augustss 436: }
1.58 augustss 437: return (NULL);
1.1 augustss 438: }
439:
440: usbd_status
1.78 augustss 441: usbd_fill_iface_data(usbd_device_handle dev, int ifaceidx, int altidx)
1.1 augustss 442: {
1.12 augustss 443: usbd_interface_handle ifc = &dev->ifaces[ifaceidx];
1.77 augustss 444: usb_interface_descriptor_t *idesc;
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.77 augustss 450: idesc = usbd_find_idesc(dev->cdesc, ifaceidx, altidx);
451: if (idesc == NULL)
452: return (USBD_INVAL);
1.1 augustss 453: ifc->device = dev;
1.77 augustss 454: ifc->idesc = idesc;
1.13 augustss 455: ifc->index = ifaceidx;
456: ifc->altindex = altidx;
1.1 augustss 457: nendpt = ifc->idesc->bNumEndpoints;
1.59 augustss 458: DPRINTFN(4,("usbd_fill_iface_data: found idesc nendpt=%d\n", nendpt));
1.1 augustss 459: if (nendpt != 0) {
460: ifc->endpoints = malloc(nendpt * sizeof(struct usbd_endpoint),
461: M_USB, M_NOWAIT);
1.58 augustss 462: if (ifc->endpoints == NULL)
1.1 augustss 463: return (USBD_NOMEM);
464: } else
1.58 augustss 465: ifc->endpoints = NULL;
466: ifc->priv = NULL;
1.1 augustss 467: p = (char *)ifc->idesc + ifc->idesc->bLength;
468: end = (char *)dev->cdesc + UGETW(dev->cdesc->wTotalLength);
1.19 augustss 469: #define ed ((usb_endpoint_descriptor_t *)p)
1.1 augustss 470: for (endpt = 0; endpt < nendpt; endpt++) {
471: DPRINTFN(10,("usbd_fill_iface_data: endpt=%d\n", endpt));
472: for (; p < end; p += ed->bLength) {
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.95 augustss 484: printf("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;
1.95 augustss 491: if (dev->speed == USB_SPEED_HIGH) {
492: u_int mps;
493: /* Control and bulk endpoints have max packet limits. */
494: switch (UE_GET_XFERTYPE(ed->bmAttributes)) {
495: case UE_CONTROL:
496: mps = USB_2_MAX_CTRL_PACKET;
497: goto check;
498: case UE_BULK:
499: mps = USB_2_MAX_BULK_PACKET;
500: check:
501: if (UGETW(ed->wMaxPacketSize) != mps) {
502: USETW(ed->wMaxPacketSize, mps);
503: #ifdef DIAGNOSTIC
504: printf("usbd_fill_iface_data: bad max "
505: "packet size\n");
506: #endif
507: }
508: break;
509: default:
510: break;
511: }
512: }
1.1 augustss 513: ifc->endpoints[endpt].refcnt = 0;
1.24 augustss 514: p += ed->bLength;
1.1 augustss 515: }
1.19 augustss 516: #undef ed
1.1 augustss 517: LIST_INIT(&ifc->pipes);
518: return (USBD_NORMAL_COMPLETION);
1.24 augustss 519:
1.1 augustss 520: bad:
1.77 augustss 521: if (ifc->endpoints != NULL) {
1.59 augustss 522: free(ifc->endpoints, M_USB);
1.77 augustss 523: ifc->endpoints = NULL;
524: }
1.24 augustss 525: return (USBD_INVAL);
1.1 augustss 526: }
527:
528: void
1.78 augustss 529: usbd_free_iface_data(usbd_device_handle dev, int ifcno)
1.1 augustss 530: {
531: usbd_interface_handle ifc = &dev->ifaces[ifcno];
532: if (ifc->endpoints)
533: free(ifc->endpoints, M_USB);
534: }
535:
1.69 augustss 536: Static usbd_status
1.78 augustss 537: usbd_set_config(usbd_device_handle dev, int conf)
1.7 augustss 538: {
539: usb_device_request_t req;
540:
541: req.bmRequestType = UT_WRITE_DEVICE;
542: req.bRequest = UR_SET_CONFIG;
543: USETW(req.wValue, conf);
544: USETW(req.wIndex, 0);
545: USETW(req.wLength, 0);
546: return (usbd_do_request(dev, &req, 0));
547: }
548:
1.1 augustss 549: usbd_status
1.78 augustss 550: usbd_set_config_no(usbd_device_handle dev, int no, int msg)
1.1 augustss 551: {
1.12 augustss 552: int index;
553: usb_config_descriptor_t cd;
1.53 augustss 554: usbd_status err;
1.12 augustss 555:
1.75 augustss 556: if (no == USB_UNCONFIG_NO)
557: return (usbd_set_config_index(dev, USB_UNCONFIG_INDEX, msg));
558:
1.12 augustss 559: DPRINTFN(5,("usbd_set_config_no: %d\n", no));
560: /* Figure out what config index to use. */
561: for (index = 0; index < dev->ddesc.bNumConfigurations; index++) {
1.53 augustss 562: err = usbd_get_config_desc(dev, index, &cd);
563: if (err)
564: return (err);
1.12 augustss 565: if (cd.bConfigurationValue == no)
566: return (usbd_set_config_index(dev, index, msg));
567: }
568: return (USBD_INVAL);
569: }
570:
571: usbd_status
1.78 augustss 572: usbd_set_config_index(usbd_device_handle dev, int index, int msg)
1.12 augustss 573: {
1.1 augustss 574: usb_config_descriptor_t cd, *cdp;
1.53 augustss 575: usbd_status err;
1.103 augustss 576: int i, ifcidx, nifc, len, selfpowered, power;
1.1 augustss 577:
1.12 augustss 578: DPRINTFN(5,("usbd_set_config_index: dev=%p index=%d\n", dev, index));
1.1 augustss 579:
1.143.6.1! mjf 580: if (index >= dev->ddesc.bNumConfigurations &&
! 581: index != USB_UNCONFIG_NO) {
! 582: /* panic? */
! 583: printf("usbd_set_config_index: illegal index\n");
! 584: return (USBD_INVAL);
! 585: }
! 586:
1.1 augustss 587: /* XXX check that all interfaces are idle */
1.75 augustss 588: if (dev->config != USB_UNCONFIG_NO) {
1.12 augustss 589: DPRINTF(("usbd_set_config_index: free old config\n"));
1.1 augustss 590: /* Free all configuration data structures. */
591: nifc = dev->cdesc->bNumInterface;
1.12 augustss 592: for (ifcidx = 0; ifcidx < nifc; ifcidx++)
593: usbd_free_iface_data(dev, ifcidx);
1.1 augustss 594: free(dev->ifaces, M_USB);
595: free(dev->cdesc, M_USB);
1.57 augustss 596: dev->ifaces = NULL;
597: dev->cdesc = NULL;
1.75 augustss 598: dev->config = USB_UNCONFIG_NO;
599: }
600:
601: if (index == USB_UNCONFIG_INDEX) {
602: /* We are unconfiguring the device, so leave unallocated. */
603: DPRINTF(("usbd_set_config_index: set config 0\n"));
604: err = usbd_set_config(dev, USB_UNCONFIG_NO);
1.136 christos 605: if (err) {
1.75 augustss 606: DPRINTF(("usbd_set_config_index: setting config=0 "
607: "failed, error=%s\n", usbd_errstr(err)));
1.136 christos 608: }
1.75 augustss 609: return (err);
1.1 augustss 610: }
611:
1.74 augustss 612: /* Get the short descriptor. */
1.53 augustss 613: err = usbd_get_config_desc(dev, index, &cd);
614: if (err)
615: return (err);
1.1 augustss 616: len = UGETW(cd.wTotalLength);
617: cdp = malloc(len, M_USB, M_NOWAIT);
1.53 augustss 618: if (cdp == NULL)
1.1 augustss 619: return (USBD_NOMEM);
1.103 augustss 620:
621: /* Get the full descriptor. Try a few times for slow devices. */
622: for (i = 0; i < 3; i++) {
623: err = usbd_get_desc(dev, UDESC_CONFIG, index, len, cdp);
624: if (!err)
625: break;
626: usbd_delay_ms(dev, 200);
627: }
1.53 augustss 628: if (err)
1.1 augustss 629: goto bad;
1.103 augustss 630:
1.18 augustss 631: if (cdp->bDescriptorType != UDESC_CONFIG) {
632: DPRINTFN(-1,("usbd_set_config_index: bad desc %d\n",
633: cdp->bDescriptorType));
1.53 augustss 634: err = USBD_INVAL;
1.18 augustss 635: goto bad;
636: }
1.74 augustss 637:
1.142 drochner 638: /*
639: * Figure out if the device is self or bus powered.
640: */
641: #if 0 /* XXX various devices don't report the power state correctly */
1.1 augustss 642: selfpowered = 0;
1.141 drochner 643: err = usbd_get_device_status(dev, &ds);
644: if (!err && (UGETW(ds.wStatus) & UDS_SELF_POWERED))
645: selfpowered = 1;
1.142 drochner 646: #endif
647: /*
648: * Use the power state in the configuration we are going
649: * to set. This doesn't necessarily reflect the actual
650: * power state of the device; the driver can control this
651: * by choosing the appropriate configuration.
652: */
653: selfpowered = !!(cdp->bmAttributes & UC_SELF_POWERED);
1.141 drochner 654:
1.81 augustss 655: DPRINTF(("usbd_set_config_index: (addr %d) cno=%d attr=0x%02x, "
656: "selfpowered=%d, power=%d\n",
1.99 augustss 657: cdp->bConfigurationValue, dev->address, cdp->bmAttributes,
1.33 augustss 658: selfpowered, cdp->bMaxPower * 2));
1.74 augustss 659:
660: /* Check if we have enough power. */
1.142 drochner 661: #if 0 /* this is a no-op, see above */
1.141 drochner 662: if ((cdp->bmAttributes & UC_SELF_POWERED) && !selfpowered) {
663: if (msg)
664: printf("%s: device addr %d (config %d): "
665: "can't set self powered configuration\n",
666: USBDEVNAME(dev->bus->bdev), dev->address,
667: cdp->bConfigurationValue);
668: err = USBD_NO_POWER;
669: goto bad;
670: }
1.142 drochner 671: #endif
1.1 augustss 672: #ifdef USB_DEBUG
1.53 augustss 673: if (dev->powersrc == NULL) {
1.44 augustss 674: DPRINTF(("usbd_set_config_index: No power source?\n"));
1.141 drochner 675: err = USBD_IOERROR;
676: goto bad;
1.1 augustss 677: }
678: #endif
679: power = cdp->bMaxPower * 2;
680: if (power > dev->powersrc->power) {
1.81 augustss 681: DPRINTF(("power exceeded %d %d\n", power,dev->powersrc->power));
1.1 augustss 682: /* XXX print nicer message. */
1.7 augustss 683: if (msg)
1.18 augustss 684: printf("%s: device addr %d (config %d) exceeds power "
685: "budget, %d mA > %d mA\n",
1.99 augustss 686: USBDEVNAME(dev->bus->bdev), dev->address,
687: cdp->bConfigurationValue,
1.7 augustss 688: power, dev->powersrc->power);
1.53 augustss 689: err = USBD_NO_POWER;
1.1 augustss 690: goto bad;
691: }
692: dev->power = power;
693: dev->self_powered = selfpowered;
694:
1.74 augustss 695: /* Set the actual configuration value. */
1.18 augustss 696: DPRINTF(("usbd_set_config_index: set config %d\n",
697: cdp->bConfigurationValue));
1.53 augustss 698: err = usbd_set_config(dev, cdp->bConfigurationValue);
699: if (err) {
1.14 drochner 700: DPRINTF(("usbd_set_config_index: setting config=%d failed, "
1.39 augustss 701: "error=%s\n",
1.53 augustss 702: cdp->bConfigurationValue, usbd_errstr(err)));
1.1 augustss 703: goto bad;
704: }
1.74 augustss 705:
706: /* Allocate and fill interface data. */
1.1 augustss 707: nifc = cdp->bNumInterface;
1.99 augustss 708: dev->ifaces = malloc(nifc * sizeof(struct usbd_interface),
1.1 augustss 709: M_USB, M_NOWAIT);
1.58 augustss 710: if (dev->ifaces == NULL) {
1.53 augustss 711: err = USBD_NOMEM;
1.1 augustss 712: goto bad;
713: }
1.12 augustss 714: DPRINTFN(5,("usbd_set_config_index: dev=%p cdesc=%p\n", dev, cdp));
1.1 augustss 715: dev->cdesc = cdp;
716: dev->config = cdp->bConfigurationValue;
1.12 augustss 717: for (ifcidx = 0; ifcidx < nifc; ifcidx++) {
1.53 augustss 718: err = usbd_fill_iface_data(dev, ifcidx, 0);
719: if (err) {
1.12 augustss 720: while (--ifcidx >= 0)
721: usbd_free_iface_data(dev, ifcidx);
1.1 augustss 722: goto bad;
723: }
724: }
725:
726: return (USBD_NORMAL_COMPLETION);
727:
728: bad:
729: free(cdp, M_USB);
1.53 augustss 730: return (err);
1.1 augustss 731: }
732:
733: /* XXX add function for alternate settings */
734:
735: usbd_status
1.78 augustss 736: usbd_setup_pipe(usbd_device_handle dev, usbd_interface_handle iface,
737: struct usbd_endpoint *ep, int ival, usbd_pipe_handle *pipe)
1.1 augustss 738: {
739: usbd_pipe_handle p;
1.53 augustss 740: usbd_status err;
1.1 augustss 741:
742: DPRINTFN(1,("usbd_setup_pipe: dev=%p iface=%p ep=%p pipe=%p\n",
743: dev, iface, ep, pipe));
744: p = malloc(dev->bus->pipe_size, M_USB, M_NOWAIT);
1.53 augustss 745: if (p == NULL)
1.1 augustss 746: return (USBD_NOMEM);
747: p->device = dev;
748: p->iface = iface;
749: p->endpoint = ep;
750: ep->refcnt++;
751: p->refcnt = 1;
1.53 augustss 752: p->intrxfer = 0;
1.1 augustss 753: p->running = 0;
1.70 augustss 754: p->aborting = 0;
1.34 augustss 755: p->repeat = 0;
1.63 augustss 756: p->interval = ival;
1.1 augustss 757: SIMPLEQ_INIT(&p->queue);
1.53 augustss 758: err = dev->bus->methods->open_pipe(p);
759: if (err) {
1.39 augustss 760: DPRINTFN(-1,("usbd_setup_pipe: endpoint=0x%x failed, error="
761: "%s\n",
1.53 augustss 762: ep->edesc->bEndpointAddress, usbd_errstr(err)));
1.1 augustss 763: free(p, M_USB);
1.53 augustss 764: return (err);
1.1 augustss 765: }
766: *pipe = p;
767: return (USBD_NORMAL_COMPLETION);
768: }
769:
770: /* Abort the device control pipe. */
771: void
1.78 augustss 772: usbd_kill_pipe(usbd_pipe_handle pipe)
1.1 augustss 773: {
1.89 augustss 774: usbd_abort_pipe(pipe);
1.1 augustss 775: pipe->methods->close(pipe);
776: pipe->endpoint->refcnt--;
777: free(pipe, M_USB);
778: }
779:
780: int
1.78 augustss 781: usbd_getnewaddr(usbd_bus_handle bus)
1.1 augustss 782: {
1.18 augustss 783: int addr;
1.1 augustss 784:
1.18 augustss 785: for (addr = 1; addr < USB_MAX_DEVICES; addr++)
786: if (bus->devices[addr] == 0)
787: return (addr);
1.1 augustss 788: return (-1);
789: }
790:
1.18 augustss 791:
792: usbd_status
1.78 augustss 793: usbd_probe_and_attach(device_ptr_t parent, usbd_device_handle dev,
794: int port, int addr)
1.18 augustss 795: {
796: struct usb_attach_arg uaa;
1.143.6.1! mjf 797: struct usbif_attach_arg uiaa;
1.18 augustss 798: usb_device_descriptor_t *dd = &dev->ddesc;
1.53 augustss 799: int found, i, confi, nifaces;
800: usbd_status err;
1.43 augustss 801: device_ptr_t dv;
1.132 christos 802: usbd_interface_handle *ifaces;
1.18 augustss 803:
804: #if defined(__FreeBSD__)
1.99 augustss 805: /*
1.28 augustss 806: * XXX uaa is a static var. Not a problem as it _should_ be used only
807: * during probe and attach. Should be changed however.
808: */
1.43 augustss 809: device_t bdev;
1.52 augustss 810: bdev = device_add_child(parent, NULL, -1, &uaa);
1.26 augustss 811: if (!bdev) {
1.18 augustss 812: printf("%s: Device creation failed\n", USBDEVNAME(dev->bus->bdev));
813: return (USBD_INVAL);
814: }
1.52 augustss 815: device_quiet(bdev);
1.18 augustss 816: #endif
817:
818: uaa.device = dev;
819: uaa.usegeneric = 0;
820: uaa.port = port;
1.32 augustss 821: uaa.vendor = UGETW(dd->idVendor);
822: uaa.product = UGETW(dd->idProduct);
823: uaa.release = UGETW(dd->bcdDevice);
1.143.6.1! mjf 824: uaa.class = dd->bDeviceClass;
! 825: uaa.subclass = dd->bDeviceSubClass;
! 826: uaa.proto = dd->bDeviceProtocol;
1.18 augustss 827:
828: /* First try with device specific drivers. */
1.60 augustss 829: DPRINTF(("usbd_probe_and_attach: trying device specific drivers\n"));
1.34 augustss 830: dv = USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print, usbd_submatch);
831: if (dv) {
832: dev->subdevs = malloc(2 * sizeof dv, M_USB, M_NOWAIT);
1.57 augustss 833: if (dev->subdevs == NULL)
1.34 augustss 834: return (USBD_NOMEM);
835: dev->subdevs[0] = dv;
836: dev->subdevs[1] = 0;
1.18 augustss 837: return (USBD_NORMAL_COMPLETION);
1.34 augustss 838: }
1.18 augustss 839:
840: DPRINTF(("usbd_probe_and_attach: no device specific driver found\n"));
841:
1.143.6.1! mjf 842: uiaa.device = dev;
! 843: uiaa.port = port;
! 844: uiaa.vendor = UGETW(dd->idVendor);
! 845: uiaa.product = UGETW(dd->idProduct);
! 846: uiaa.release = UGETW(dd->bcdDevice);
! 847:
1.60 augustss 848: DPRINTF(("usbd_probe_and_attach: looping over %d configurations\n",
849: dd->bNumConfigurations));
1.18 augustss 850: /* Next try with interface drivers. */
851: for (confi = 0; confi < dd->bNumConfigurations; confi++) {
852: DPRINTFN(1,("usbd_probe_and_attach: trying config idx=%d\n",
853: confi));
1.53 augustss 854: err = usbd_set_config_index(dev, confi, 1);
855: if (err) {
1.18 augustss 856: #ifdef USB_DEBUG
857: DPRINTF(("%s: port %d, set config at addr %d failed, "
1.43 augustss 858: "error=%s\n", USBDEVPTRNAME(parent), port,
1.53 augustss 859: addr, usbd_errstr(err)));
1.18 augustss 860: #else
861: printf("%s: port %d, set config at addr %d failed\n",
1.43 augustss 862: USBDEVPTRNAME(parent), port, addr);
1.18 augustss 863: #endif
1.27 augustss 864: #if defined(__FreeBSD__)
1.52 augustss 865: device_delete_child(parent, bdev);
1.27 augustss 866: #endif
1.52 augustss 867:
1.53 augustss 868: return (err);
1.18 augustss 869: }
1.20 augustss 870: nifaces = dev->cdesc->bNumInterface;
1.143.6.1! mjf 871: uiaa.configno = dev->cdesc->bConfigurationValue;
1.132 christos 872: ifaces = malloc(nifaces * sizeof(*ifaces), M_USB, M_NOWAIT);
873: if (ifaces == NULL)
874: goto nomem;
1.20 augustss 875: for (i = 0; i < nifaces; i++)
876: ifaces[i] = &dev->ifaces[i];
1.143.6.1! mjf 877: uiaa.ifaces = ifaces;
! 878: uiaa.nifaces = nifaces;
1.34 augustss 879: dev->subdevs = malloc((nifaces+1) * sizeof dv, M_USB,M_NOWAIT);
1.57 augustss 880: if (dev->subdevs == NULL) {
1.132 christos 881: free(ifaces, M_USB);
882: nomem:
1.52 augustss 883: #if defined(__FreeBSD__)
884: device_delete_child(parent, bdev);
885: #endif
1.34 augustss 886: return (USBD_NOMEM);
1.52 augustss 887: }
888:
889: found = 0;
890: for (i = 0; i < nifaces; i++) {
1.53 augustss 891: if (ifaces[i] == NULL)
1.20 augustss 892: continue; /* interface already claimed */
1.143.6.1! mjf 893: uiaa.iface = ifaces[i];
! 894: uiaa.class = ifaces[i]->idesc->bInterfaceClass;
! 895: uiaa.subclass = ifaces[i]->idesc->bInterfaceSubClass;
! 896: uiaa.proto = ifaces[i]->idesc->bInterfaceProtocol;
! 897: uiaa.ifaceno = ifaces[i]->idesc->bInterfaceNumber;
! 898: dv = USB_DO_IFATTACH(dev, bdev, parent, &uiaa, usbd_ifprint,
! 899: usbd_ifsubmatch);
1.53 augustss 900: if (dv != NULL) {
1.34 augustss 901: dev->subdevs[found++] = dv;
902: dev->subdevs[found] = 0;
1.20 augustss 903: ifaces[i] = 0; /* consumed */
1.52 augustss 904:
905: #if defined(__FreeBSD__)
906: /* create another child for the next iface */
907: bdev = device_add_child(parent, NULL, -1,&uaa);
908: if (!bdev) {
909: printf("%s: Device creation failed\n",
910: USBDEVNAME(dev->bus->bdev));
1.132 christos 911: free(ifaces, M_USB);
1.52 augustss 912: return (USBD_NORMAL_COMPLETION);
913: }
914: device_quiet(bdev);
915: #endif
1.20 augustss 916: }
1.18 augustss 917: }
1.52 augustss 918: if (found != 0) {
919: #if defined(__FreeBSD__)
920: /* remove the last created child again; it is unused */
921: device_delete_child(parent, bdev);
922: #endif
1.132 christos 923: free(ifaces, M_USB);
1.18 augustss 924: return (USBD_NORMAL_COMPLETION);
1.52 augustss 925: }
1.132 christos 926: free(ifaces, M_USB);
1.34 augustss 927: free(dev->subdevs, M_USB);
928: dev->subdevs = 0;
1.18 augustss 929: }
1.21 augustss 930: /* No interfaces were attached in any of the configurations. */
1.34 augustss 931:
932: if (dd->bNumConfigurations > 1) /* don't change if only 1 config */
1.18 augustss 933: usbd_set_config_index(dev, 0, 0);
934:
935: DPRINTF(("usbd_probe_and_attach: no interface drivers found\n"));
936:
937: /* Finally try the generic driver. */
938: uaa.usegeneric = 1;
1.34 augustss 939: dv = USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print, usbd_submatch);
1.53 augustss 940: if (dv != NULL) {
1.34 augustss 941: dev->subdevs = malloc(2 * sizeof dv, M_USB, M_NOWAIT);
942: if (dev->subdevs == 0)
943: return (USBD_NOMEM);
944: dev->subdevs[0] = dv;
945: dev->subdevs[1] = 0;
1.18 augustss 946: return (USBD_NORMAL_COMPLETION);
1.34 augustss 947: }
1.18 augustss 948:
1.99 augustss 949: /*
1.18 augustss 950: * The generic attach failed, but leave the device as it is.
951: * We just did not find any drivers, that's all. The device is
952: * fully operational and not harming anyone.
953: */
954: DPRINTF(("usbd_probe_and_attach: generic attach failed\n"));
1.27 augustss 955: #if defined(__FreeBSD__)
1.52 augustss 956: device_delete_child(parent, bdev);
1.27 augustss 957: #endif
958: return (USBD_NORMAL_COMPLETION);
1.18 augustss 959: }
960:
961:
1.1 augustss 962: /*
963: * Called when a new device has been put in the powered state,
964: * but not yet in the addressed state.
965: * Get initial descriptor, set the address, get full descriptor,
966: * and attach a driver.
967: */
968: usbd_status
1.78 augustss 969: usbd_new_device(device_ptr_t parent, usbd_bus_handle bus, int depth,
1.94 augustss 970: int speed, int port, struct usbd_port *up)
1.1 augustss 971: {
1.120 augustss 972: usbd_device_handle dev, adev;
1.94 augustss 973: struct usbd_device *hub;
1.18 augustss 974: usb_device_descriptor_t *dd;
1.107 augustss 975: usb_port_status_t ps;
1.53 augustss 976: usbd_status err;
1.1 augustss 977: int addr;
1.18 augustss 978: int i;
1.120 augustss 979: int p;
1.1 augustss 980:
1.94 augustss 981: DPRINTF(("usbd_new_device bus=%p port=%d depth=%d speed=%d\n",
982: bus, port, depth, speed));
1.1 augustss 983: addr = usbd_getnewaddr(bus);
984: if (addr < 0) {
1.99 augustss 985: printf("%s: No free USB addresses, new device ignored.\n",
1.18 augustss 986: USBDEVNAME(bus->bdev));
1.1 augustss 987: return (USBD_NO_ADDR);
988: }
989:
1.97 tsutsui 990: dev = malloc(sizeof *dev, M_USB, M_NOWAIT|M_ZERO);
1.53 augustss 991: if (dev == NULL)
1.1 augustss 992: return (USBD_NOMEM);
993:
994: dev->bus = bus;
995:
996: /* Set up default endpoint handle. */
997: dev->def_ep.edesc = &dev->def_ep_desc;
998:
999: /* Set up default endpoint descriptor. */
1000: dev->def_ep_desc.bLength = USB_ENDPOINT_DESCRIPTOR_SIZE;
1001: dev->def_ep_desc.bDescriptorType = UDESC_ENDPOINT;
1002: dev->def_ep_desc.bEndpointAddress = USB_CONTROL_ENDPOINT;
1003: dev->def_ep_desc.bmAttributes = UE_CONTROL;
1004: USETW(dev->def_ep_desc.wMaxPacketSize, USB_MAX_IPACKET);
1005: dev->def_ep_desc.bInterval = 0;
1006:
1007: dev->quirks = &usbd_no_quirk;
1008: dev->address = USB_START_ADDR;
1.4 augustss 1009: dev->ddesc.bMaxPacketSize = 0;
1.1 augustss 1010: dev->depth = depth;
1011: dev->powersrc = up;
1.94 augustss 1012: dev->myhub = up->parent;
1.120 augustss 1013:
1014: up->device = dev;
1015:
1016: /* Locate port on upstream high speed hub */
1017: for (adev = dev, hub = up->parent;
1.94 augustss 1018: hub != NULL && hub->speed != USB_SPEED_HIGH;
1.120 augustss 1019: adev = hub, hub = hub->myhub)
1.94 augustss 1020: ;
1.120 augustss 1021: if (hub) {
1022: for (p = 0; p < hub->hub->hubdesc.bNbrPorts; p++) {
1023: if (hub->hub->ports[p].device == adev) {
1024: dev->myhsport = &hub->hub->ports[p];
1025: goto found;
1026: }
1027: }
1028: panic("usbd_new_device: cannot find HS port\n");
1029: found:
1030: DPRINTFN(1,("usbd_new_device: high speed port %d\n", p));
1031: } else {
1032: dev->myhsport = NULL;
1033: }
1.94 augustss 1034: dev->speed = speed;
1.22 augustss 1035: dev->langid = USBD_NOLANG;
1.50 augustss 1036: dev->cookie.cookie = ++usb_cookie_no;
1.1 augustss 1037:
1.67 soren 1038: /* Establish the default pipe. */
1.63 augustss 1039: err = usbd_setup_pipe(dev, 0, &dev->def_ep, USBD_DEFAULT_INTERVAL,
1040: &dev->default_pipe);
1.53 augustss 1041: if (err) {
1.18 augustss 1042: usbd_remove_device(dev, up);
1.53 augustss 1043: return (err);
1.18 augustss 1044: }
1.1 augustss 1045:
1.111 augustss 1046: /* Set the address. Do this early; some devices need that. */
1.143.6.1! mjf 1047: /* Try a few times in case the device is slow (i.e. outside specs) */
1.111 augustss 1048: DPRINTFN(5,("usbd_new_device: setting device address=%d\n", addr));
1.143.6.1! mjf 1049: for (i = 0; i < 15; i++) {
! 1050: err = usbd_set_address(dev, addr);
! 1051: if (!err)
! 1052: break;
! 1053: usbd_delay_ms(dev, 200);
! 1054: if ((i & 3) == 3) {
! 1055: DPRINTFN(-1,("usbd_new_device: set address %d "
! 1056: "failed - trying a port reset\n", addr));
! 1057: usbd_reset_port(up->parent, port, &ps);
! 1058: }
! 1059: }
1.111 augustss 1060: if (err) {
1061: DPRINTFN(-1,("usb_new_device: set address %d failed\n", addr));
1062: err = USBD_SET_ADDR_FAILED;
1063: usbd_remove_device(dev, up);
1064: return (err);
1065: }
1066: /* Allow device time to set new address */
1067: usbd_delay_ms(dev, USB_SET_ADDRESS_SETTLE);
1068: dev->address = addr; /* New device address now */
1069: bus->devices[addr] = dev;
1070:
1.18 augustss 1071: dd = &dev->ddesc;
1.6 augustss 1072: /* Try a few times in case the device is slow (i.e. outside specs.) */
1.107 augustss 1073: for (i = 0; i < 10; i++) {
1.6 augustss 1074: /* Get the first 8 bytes of the device descriptor. */
1.53 augustss 1075: err = usbd_get_desc(dev, UDESC_DEVICE, 0, USB_MAX_IPACKET, dd);
1076: if (!err)
1.6 augustss 1077: break;
1.23 augustss 1078: usbd_delay_ms(dev, 200);
1.107 augustss 1079: if ((i & 3) == 3)
1080: usbd_reset_port(up->parent, port, &ps);
1.6 augustss 1081: }
1.53 augustss 1082: if (err) {
1.14 drochner 1083: DPRINTFN(-1, ("usbd_new_device: addr=%d, getting first desc "
1.53 augustss 1084: "failed\n", addr));
1.18 augustss 1085: usbd_remove_device(dev, up);
1.53 augustss 1086: return (err);
1.95 augustss 1087: }
1088:
1089: if (speed == USB_SPEED_HIGH) {
1090: /* Max packet size must be 64 (sec 5.5.3). */
1091: if (dd->bMaxPacketSize != USB_2_MAX_CTRL_PACKET) {
1092: #ifdef DIAGNOSTIC
1093: printf("usbd_new_device: addr=%d bad max packet size\n",
1094: addr);
1095: #endif
1096: dd->bMaxPacketSize = USB_2_MAX_CTRL_PACKET;
1097: }
1.18 augustss 1098: }
1099:
1.39 augustss 1100: DPRINTF(("usbd_new_device: adding unit addr=%d, rev=%02x, class=%d, "
1.99 augustss 1101: "subclass=%d, protocol=%d, maxpacket=%d, len=%d, speed=%d\n",
1.39 augustss 1102: addr,UGETW(dd->bcdUSB), dd->bDeviceClass, dd->bDeviceSubClass,
1.99 augustss 1103: dd->bDeviceProtocol, dd->bMaxPacketSize, dd->bLength,
1.94 augustss 1104: dev->speed));
1.39 augustss 1105:
1.18 augustss 1106: if (dd->bDescriptorType != UDESC_DEVICE) {
1107: /* Illegal device descriptor */
1108: DPRINTFN(-1,("usbd_new_device: illegal descriptor %d\n",
1109: dd->bDescriptorType));
1110: usbd_remove_device(dev, up);
1111: return (USBD_INVAL);
1.1 augustss 1112: }
1113:
1.39 augustss 1114: if (dd->bLength < USB_DEVICE_DESCRIPTOR_SIZE) {
1115: DPRINTFN(-1,("usbd_new_device: bad length %d\n", dd->bLength));
1116: usbd_remove_device(dev, up);
1117: return (USBD_INVAL);
1118: }
1.4 augustss 1119:
1.18 augustss 1120: USETW(dev->def_ep_desc.wMaxPacketSize, dd->bMaxPacketSize);
1.1 augustss 1121:
1.62 augustss 1122: err = usbd_reload_device_desc(dev);
1.53 augustss 1123: if (err) {
1.14 drochner 1124: DPRINTFN(-1, ("usbd_new_device: addr=%d, getting full desc "
1125: "failed\n", addr));
1.18 augustss 1126: usbd_remove_device(dev, up);
1.53 augustss 1127: return (err);
1.1 augustss 1128: }
1129:
1130: /* Assume 100mA bus powered for now. Changed when configured. */
1131: dev->power = USB_MIN_POWER;
1132: dev->self_powered = 0;
1133:
1.99 augustss 1134: DPRINTF(("usbd_new_device: new dev (addr %d), dev=%p, parent=%p\n",
1.1 augustss 1135: addr, dev, parent));
1.99 augustss 1136:
1.65 augustss 1137: usbd_add_dev_event(USB_EVENT_DEVICE_ATTACH, dev);
1.1 augustss 1138:
1.53 augustss 1139: err = usbd_probe_and_attach(parent, dev, port, addr);
1140: if (err) {
1.18 augustss 1141: usbd_remove_device(dev, up);
1.53 augustss 1142: return (err);
1.18 augustss 1143: }
1.65 augustss 1144:
1.18 augustss 1145: return (USBD_NORMAL_COMPLETION);
1.62 augustss 1146: }
1147:
1148: usbd_status
1.78 augustss 1149: usbd_reload_device_desc(usbd_device_handle dev)
1.62 augustss 1150: {
1151: usbd_status err;
1152:
1153: /* Get the full device descriptor. */
1154: err = usbd_get_device_desc(dev, &dev->ddesc);
1155: if (err)
1156: return (err);
1157:
1158: /* Figure out what's wrong with this device. */
1159: dev->quirks = usbd_find_quirk(&dev->ddesc);
1160:
1161: return (USBD_NORMAL_COMPLETION);
1.18 augustss 1162: }
1.1 augustss 1163:
1.18 augustss 1164: void
1.78 augustss 1165: usbd_remove_device(usbd_device_handle dev, struct usbd_port *up)
1.18 augustss 1166: {
1167: DPRINTF(("usbd_remove_device: %p\n", dev));
1.99 augustss 1168:
1.53 augustss 1169: if (dev->default_pipe != NULL)
1.18 augustss 1170: usbd_kill_pipe(dev->default_pipe);
1.120 augustss 1171: up->device = NULL;
1172: dev->bus->devices[dev->address] = NULL;
1.1 augustss 1173:
1174: free(dev, M_USB);
1175: }
1176:
1.37 augustss 1177: #if defined(__NetBSD__) || defined(__OpenBSD__)
1.1 augustss 1178: int
1.78 augustss 1179: usbd_print(void *aux, const char *pnp)
1.1 augustss 1180: {
1181: struct usb_attach_arg *uaa = aux;
1182:
1183: DPRINTFN(15, ("usbd_print dev=%p\n", uaa->device));
1184: if (pnp) {
1.134 christos 1185: #define USB_DEVINFO 1024
1186: char *devinfo;
1.1 augustss 1187: if (!uaa->usegeneric)
1188: return (QUIET);
1.134 christos 1189: devinfo = malloc(USB_DEVINFO, M_TEMP, M_WAITOK);
1190: usbd_devinfo(uaa->device, 1, devinfo, USB_DEVINFO);
1.101 thorpej 1191: aprint_normal("%s, %s", devinfo, pnp);
1.134 christos 1192: free(devinfo, M_TEMP);
1.1 augustss 1193: }
1194: if (uaa->port != 0)
1.101 thorpej 1195: aprint_normal(" port %d", uaa->port);
1.143.6.1! mjf 1196: #if 0
! 1197: /*
! 1198: * It gets very crowded with these locators on the attach line.
! 1199: * They are not really needed since they are printed in the clear
! 1200: * by each driver.
! 1201: */
! 1202: if (uaa->vendor != UHUB_UNK_VENDOR)
! 1203: aprint_normal(" vendor 0x%04x", uaa->vendor);
! 1204: if (uaa->product != UHUB_UNK_PRODUCT)
! 1205: aprint_normal(" product 0x%04x", uaa->product);
! 1206: if (uaa->release != UHUB_UNK_RELEASE)
! 1207: aprint_normal(" release 0x%04x", uaa->release);
! 1208: #endif
! 1209: return (UNCONF);
! 1210: }
! 1211:
! 1212: int
! 1213: usbd_ifprint(void *aux, const char *pnp)
! 1214: {
! 1215: struct usbif_attach_arg *uaa = aux;
! 1216:
! 1217: DPRINTFN(15, ("usbd_print dev=%p\n", uaa->device));
! 1218: if (pnp)
! 1219: return (QUIET);
! 1220: if (uaa->port != 0)
! 1221: aprint_normal(" port %d", uaa->port);
1.11 augustss 1222: if (uaa->configno != UHUB_UNK_CONFIGURATION)
1.101 thorpej 1223: aprint_normal(" configuration %d", uaa->configno);
1.11 augustss 1224: if (uaa->ifaceno != UHUB_UNK_INTERFACE)
1.101 thorpej 1225: aprint_normal(" interface %d", uaa->ifaceno);
1.32 augustss 1226: #if 0
1.99 augustss 1227: /*
1.32 augustss 1228: * It gets very crowded with these locators on the attach line.
1229: * They are not really needed since they are printed in the clear
1230: * by each driver.
1231: */
1232: if (uaa->vendor != UHUB_UNK_VENDOR)
1.101 thorpej 1233: aprint_normal(" vendor 0x%04x", uaa->vendor);
1.32 augustss 1234: if (uaa->product != UHUB_UNK_PRODUCT)
1.101 thorpej 1235: aprint_normal(" product 0x%04x", uaa->product);
1.32 augustss 1236: if (uaa->release != UHUB_UNK_RELEASE)
1.101 thorpej 1237: aprint_normal(" release 0x%04x", uaa->release);
1.32 augustss 1238: #endif
1.1 augustss 1239: return (UNCONF);
1240: }
1241:
1.37 augustss 1242: #if defined(__NetBSD__)
1.1 augustss 1243: int
1.118 drochner 1244: usbd_submatch(struct device *parent, struct cfdata *cf,
1.138 christos 1245: const int *ldesc, void *aux)
1.1 augustss 1246: {
1.37 augustss 1247: #elif defined(__OpenBSD__)
1248: int
1.78 augustss 1249: usbd_submatch(struct device *parent, void *match, void *aux)
1.37 augustss 1250: {
1251: struct cfdata *cf = match;
1252: #endif
1.1 augustss 1253: struct usb_attach_arg *uaa = aux;
1254:
1.143.6.1! mjf 1255: DPRINTFN(5,("usbd_submatch port=%d,%d "
! 1256: "vendor=%d,%d product=%d,%d release=%d,%d\n",
! 1257: uaa->port, cf->uhubcf_port,
! 1258: uaa->vendor, cf->uhubcf_vendor,
! 1259: uaa->product, cf->uhubcf_product,
! 1260: uaa->release, cf->uhubcf_release));
! 1261: if (uaa->port != 0 && /* root hub has port 0, it should match */
! 1262: ((cf->uhubcf_port != UHUB_UNK_PORT &&
! 1263: cf->uhubcf_port != uaa->port) ||
! 1264: (uaa->vendor != UHUB_UNK_VENDOR &&
! 1265: cf->uhubcf_vendor != UHUB_UNK_VENDOR &&
! 1266: cf->uhubcf_vendor != uaa->vendor) ||
! 1267: (uaa->product != UHUB_UNK_PRODUCT &&
! 1268: cf->uhubcf_product != UHUB_UNK_PRODUCT &&
! 1269: cf->uhubcf_product != uaa->product) ||
! 1270: (uaa->release != UHUB_UNK_RELEASE &&
! 1271: cf->uhubcf_release != UHUB_UNK_RELEASE &&
! 1272: cf->uhubcf_release != uaa->release)
! 1273: )
! 1274: )
! 1275: return 0;
! 1276: return (config_match(parent, cf, aux));
! 1277: }
! 1278:
! 1279: int
! 1280: usbd_ifsubmatch(struct device *parent, struct cfdata *cf,
! 1281: const int *ldesc, void *aux)
! 1282: {
! 1283: struct usbif_attach_arg *uaa = aux;
! 1284:
1.72 augustss 1285: DPRINTFN(5,("usbd_submatch port=%d,%d configno=%d,%d "
1286: "ifaceno=%d,%d vendor=%d,%d product=%d,%d release=%d,%d\n",
1287: uaa->port, cf->uhubcf_port,
1288: uaa->configno, cf->uhubcf_configuration,
1289: uaa->ifaceno, cf->uhubcf_interface,
1290: uaa->vendor, cf->uhubcf_vendor,
1291: uaa->product, cf->uhubcf_product,
1292: uaa->release, cf->uhubcf_release));
1293: if (uaa->port != 0 && /* root hub has port 0, it should match */
1.117 drochner 1294: ((cf->uhubcf_port != UHUB_UNK_PORT &&
1.72 augustss 1295: cf->uhubcf_port != uaa->port) ||
1296: (uaa->configno != UHUB_UNK_CONFIGURATION &&
1297: cf->uhubcf_configuration != UHUB_UNK_CONFIGURATION &&
1298: cf->uhubcf_configuration != uaa->configno) ||
1299: (uaa->ifaceno != UHUB_UNK_INTERFACE &&
1300: cf->uhubcf_interface != UHUB_UNK_INTERFACE &&
1301: cf->uhubcf_interface != uaa->ifaceno) ||
1302: (uaa->vendor != UHUB_UNK_VENDOR &&
1303: cf->uhubcf_vendor != UHUB_UNK_VENDOR &&
1304: cf->uhubcf_vendor != uaa->vendor) ||
1305: (uaa->product != UHUB_UNK_PRODUCT &&
1306: cf->uhubcf_product != UHUB_UNK_PRODUCT &&
1307: cf->uhubcf_product != uaa->product) ||
1308: (uaa->release != UHUB_UNK_RELEASE &&
1309: cf->uhubcf_release != UHUB_UNK_RELEASE &&
1310: cf->uhubcf_release != uaa->release)
1311: )
1.32 augustss 1312: )
1.1 augustss 1313: return 0;
1.100 thorpej 1314: return (config_match(parent, cf, aux));
1.13 augustss 1315: }
1.18 augustss 1316:
1317: #endif
1.13 augustss 1318:
1319: void
1.82 augustss 1320: usbd_fill_deviceinfo(usbd_device_handle dev, struct usb_device_info *di,
1321: int usedev)
1.13 augustss 1322: {
1323: struct usbd_port *p;
1.56 augustss 1324: int i, err, s;
1.13 augustss 1325:
1.98 christos 1326: di->udi_bus = USBDEVUNIT(dev->bus->bdev);
1327: di->udi_addr = dev->address;
1328: di->udi_cookie = dev->cookie;
1.139 pavel 1329: usbd_devinfo_vp(dev, di->udi_vendor, di->udi_product, usedev, 1);
1.113 itojun 1330: usbd_printBCD(di->udi_release, sizeof(di->udi_release),
1331: UGETW(dev->ddesc.bcdDevice));
1.123 augustss 1332: di->udi_serial[0] = 0;
1333: if (usedev)
1334: (void)usbd_get_string(dev, dev->ddesc.iSerialNumber,
1335: di->udi_serial);
1.98 christos 1336: di->udi_vendorNo = UGETW(dev->ddesc.idVendor);
1337: di->udi_productNo = UGETW(dev->ddesc.idProduct);
1338: di->udi_releaseNo = UGETW(dev->ddesc.bcdDevice);
1339: di->udi_class = dev->ddesc.bDeviceClass;
1340: di->udi_subclass = dev->ddesc.bDeviceSubClass;
1341: di->udi_protocol = dev->ddesc.bDeviceProtocol;
1342: di->udi_config = dev->config;
1343: di->udi_power = dev->self_powered ? 0 : dev->power;
1344: di->udi_speed = dev->speed;
1.65 augustss 1345:
1346: if (dev->subdevs != NULL) {
1347: for (i = 0; dev->subdevs[i] &&
1348: i < USB_MAX_DEVNAMES; i++) {
1.98 christos 1349: strncpy(di->udi_devnames[i], USBDEVPTRNAME(dev->subdevs[i]),
1.65 augustss 1350: USB_MAX_DEVNAMELEN);
1.98 christos 1351: di->udi_devnames[i][USB_MAX_DEVNAMELEN-1] = '\0';
1.65 augustss 1352: }
1353: } else {
1354: i = 0;
1355: }
1356: for (/*i is set */; i < USB_MAX_DEVNAMES; i++)
1.98 christos 1357: di->udi_devnames[i][0] = 0; /* empty */
1.65 augustss 1358:
1.13 augustss 1359: if (dev->hub) {
1.99 augustss 1360: for (i = 0;
1.98 christos 1361: i < sizeof(di->udi_ports) / sizeof(di->udi_ports[0]) &&
1.13 augustss 1362: i < dev->hub->hubdesc.bNbrPorts;
1363: i++) {
1364: p = &dev->hub->ports[i];
1365: if (p->device)
1.56 augustss 1366: err = p->device->address;
1.13 augustss 1367: else {
1368: s = UGETW(p->status.wPortStatus);
1369: if (s & UPS_PORT_ENABLED)
1.56 augustss 1370: err = USB_PORT_ENABLED;
1.13 augustss 1371: else if (s & UPS_SUSPEND)
1.56 augustss 1372: err = USB_PORT_SUSPENDED;
1.13 augustss 1373: else if (s & UPS_PORT_POWER)
1.56 augustss 1374: err = USB_PORT_POWERED;
1.13 augustss 1375: else
1.56 augustss 1376: err = USB_PORT_DISABLED;
1.13 augustss 1377: }
1.98 christos 1378: di->udi_ports[i] = err;
1.13 augustss 1379: }
1.98 christos 1380: di->udi_nports = dev->hub->hubdesc.bNbrPorts;
1.13 augustss 1381: } else
1.98 christos 1382: di->udi_nports = 0;
1.34 augustss 1383: }
1384:
1.139 pavel 1385: #ifdef COMPAT_30
1386: void
1387: usbd_fill_deviceinfo_old(usbd_device_handle dev, struct usb_device_info_old *di,
1388: int usedev)
1389: {
1390: struct usbd_port *p;
1391: int i, err, s;
1392:
1393: di->udi_bus = USBDEVUNIT(dev->bus->bdev);
1394: di->udi_addr = dev->address;
1395: di->udi_cookie = dev->cookie;
1396: usbd_devinfo_vp(dev, di->udi_vendor, di->udi_product, usedev, 0);
1397: usbd_printBCD(di->udi_release, sizeof(di->udi_release),
1398: UGETW(dev->ddesc.bcdDevice));
1399: di->udi_vendorNo = UGETW(dev->ddesc.idVendor);
1400: di->udi_productNo = UGETW(dev->ddesc.idProduct);
1401: di->udi_releaseNo = UGETW(dev->ddesc.bcdDevice);
1402: di->udi_class = dev->ddesc.bDeviceClass;
1403: di->udi_subclass = dev->ddesc.bDeviceSubClass;
1404: di->udi_protocol = dev->ddesc.bDeviceProtocol;
1405: di->udi_config = dev->config;
1406: di->udi_power = dev->self_powered ? 0 : dev->power;
1407: di->udi_speed = dev->speed;
1408:
1409: if (dev->subdevs != NULL) {
1410: for (i = 0; dev->subdevs[i] &&
1411: i < USB_MAX_DEVNAMES; i++) {
1412: strncpy(di->udi_devnames[i], USBDEVPTRNAME(dev->subdevs[i]),
1413: USB_MAX_DEVNAMELEN);
1414: di->udi_devnames[i][USB_MAX_DEVNAMELEN-1] = '\0';
1415: }
1416: } else {
1417: i = 0;
1418: }
1419: for (/*i is set */; i < USB_MAX_DEVNAMES; i++)
1420: di->udi_devnames[i][0] = 0; /* empty */
1421:
1422: if (dev->hub) {
1423: for (i = 0;
1424: i < sizeof(di->udi_ports) / sizeof(di->udi_ports[0]) &&
1425: i < dev->hub->hubdesc.bNbrPorts;
1426: i++) {
1427: p = &dev->hub->ports[i];
1428: if (p->device)
1429: err = p->device->address;
1430: else {
1431: s = UGETW(p->status.wPortStatus);
1432: if (s & UPS_PORT_ENABLED)
1433: err = USB_PORT_ENABLED;
1434: else if (s & UPS_SUSPEND)
1435: err = USB_PORT_SUSPENDED;
1436: else if (s & UPS_PORT_POWER)
1437: err = USB_PORT_POWERED;
1438: else
1439: err = USB_PORT_DISABLED;
1440: }
1441: di->udi_ports[i] = err;
1442: }
1443: di->udi_nports = dev->hub->hubdesc.bNbrPorts;
1444: } else
1445: di->udi_nports = 0;
1446: }
1447: #endif
1448:
1449:
1.34 augustss 1450: void
1.78 augustss 1451: usb_free_device(usbd_device_handle dev)
1.34 augustss 1452: {
1453: int ifcidx, nifc;
1454:
1.53 augustss 1455: if (dev->default_pipe != NULL)
1.34 augustss 1456: usbd_kill_pipe(dev->default_pipe);
1.53 augustss 1457: if (dev->ifaces != NULL) {
1.34 augustss 1458: nifc = dev->cdesc->bNumInterface;
1459: for (ifcidx = 0; ifcidx < nifc; ifcidx++)
1460: usbd_free_iface_data(dev, ifcidx);
1461: free(dev->ifaces, M_USB);
1462: }
1.53 augustss 1463: if (dev->cdesc != NULL)
1.34 augustss 1464: free(dev->cdesc, M_USB);
1.53 augustss 1465: if (dev->subdevs != NULL)
1.34 augustss 1466: free(dev->subdevs, M_USB);
1467: free(dev, M_USB);
1.1 augustss 1468: }
1.47 augustss 1469:
1470: /*
1471: * The general mechanism for detaching drivers works as follows: Each
1472: * driver is responsible for maintaining a reference count on the
1473: * number of outstanding references to its softc (e.g. from
1474: * processing hanging in a read or write). The detach method of the
1475: * driver decrements this counter and flags in the softc that the
1476: * driver is dying and then wakes any sleepers. It then sleeps on the
1477: * softc. Each place that can sleep must maintain the reference
1478: * count. When the reference count drops to -1 (0 is the normal value
1479: * of the reference count) the a wakeup on the softc is performed
1480: * signaling to the detach waiter that all references are gone.
1481: */
1482:
1483: /*
1484: * Called from process context when we discover that a port has
1485: * been disconnected.
1486: */
1487: void
1.78 augustss 1488: usb_disconnect_port(struct usbd_port *up, device_ptr_t parent)
1.47 augustss 1489: {
1490: usbd_device_handle dev = up->device;
1.51 augustss 1491: char *hubname = USBDEVPTRNAME(parent);
1.47 augustss 1492: int i;
1493:
1.99 augustss 1494: DPRINTFN(3,("uhub_disconnect: up=%p dev=%p port=%d\n",
1.47 augustss 1495: up, dev, up->portno));
1.48 augustss 1496:
1497: #ifdef DIAGNOSTIC
1.57 augustss 1498: if (dev == NULL) {
1.48 augustss 1499: printf("usb_disconnect_port: no device\n");
1500: return;
1501: }
1502: #endif
1.47 augustss 1503:
1.55 augustss 1504: if (dev->subdevs != NULL) {
1.57 augustss 1505: DPRINTFN(3,("usb_disconnect_port: disconnect subdevs\n"));
1.47 augustss 1506: for (i = 0; dev->subdevs[i]; i++) {
1.99 augustss 1507: printf("%s: at %s", USBDEVPTRNAME(dev->subdevs[i]),
1.51 augustss 1508: hubname);
1509: if (up->portno != 0)
1510: printf(" port %d", up->portno);
1511: printf(" (addr %d) disconnected\n", dev->address);
1.47 augustss 1512: config_detach(dev->subdevs[i], DETACH_FORCE);
1.110 drochner 1513: dev->subdevs[i] = 0;
1.47 augustss 1514: }
1515: }
1516:
1.65 augustss 1517: usbd_add_dev_event(USB_EVENT_DEVICE_DETACH, dev);
1.57 augustss 1518: dev->bus->devices[dev->address] = NULL;
1519: up->device = NULL;
1.47 augustss 1520: usb_free_device(dev);
1521: }
1522:
1.54 augustss 1523: #ifdef __OpenBSD__
1.79 augustss 1524: void *usb_realloc(void *p, u_int size, int pool, int flags)
1.54 augustss 1525: {
1526: void *q;
1527:
1528: q = malloc(size, pool, flags);
1529: if (q == NULL)
1530: return (NULL);
1531: bcopy(p, q, size);
1532: free(p, pool);
1533: return (q);
1534: }
1535: #endif
CVSweb <webmaster@jp.NetBSD.org>