The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/usb/usb_subr.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: cc0c11571167e57d90347a8f51cbaa53


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.