LCOV - code coverage report
Current view: top level - dev/usb - usb_subr.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 733 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 31 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13