root/dev/usb/usb_subr.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. usbd_errstr
  2. usbd_get_string_desc
  3. usbd_get_string
  4. usbd_trim_spaces
  5. usbd_devinfo_vp
  6. usbd_printBCD
  7. usbd_devinfo
  8. usbd_devinfo_alloc
  9. usbd_devinfo_free
  10. usb_delay_ms
  11. usbd_delay_ms
  12. usbd_reset_port
  13. usbd_find_idesc
  14. usbd_find_edesc
  15. usbd_fill_iface_data
  16. usbd_free_iface_data
  17. usbd_set_config
  18. usbd_set_config_no
  19. usbd_set_config_index
  20. usbd_setup_pipe
  21. usbd_kill_pipe
  22. usbd_getnewaddr
  23. usbd_probe_and_attach
  24. usbd_new_device
  25. usbd_reload_device_desc
  26. usbd_remove_device
  27. usbd_print
  28. usbd_submatch
  29. usbd_fill_deviceinfo
  30. usb_free_device
  31. usb_disconnect_port

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

/* [<][>][^][v][top][bottom][index][help] */