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