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