[BACK]Return to usb_subr.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / usb

Annotation of src/sys/dev/usb/usb_subr.c, Revision 1.150.6.4

1.150.6.1  mjf         1: /*     $NetBSD$        */
1.56      augustss    2: /*     $FreeBSD: src/sys/dev/usb/usb_subr.c,v 1.18 1999/11/17 22:33:47 n_hibma Exp $   */
1.1       augustss    3:
                      4: /*
1.121     mycroft     5:  * Copyright (c) 1998, 2004 The NetBSD Foundation, Inc.
1.1       augustss    6:  * All rights reserved.
                      7:  *
1.9       augustss    8:  * This code is derived from software contributed to The NetBSD Foundation
1.76      augustss    9:  * by Lennart Augustsson (lennart@augustsson.net) at
1.9       augustss   10:  * Carlstedt Research & Technology.
1.1       augustss   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:  *
                     21:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     22:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     23:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     24:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     25:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     26:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     27:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     28:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     29:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     30:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     31:  * POSSIBILITY OF SUCH DAMAGE.
                     32:  */
1.91      lukem      33:
                     34: #include <sys/cdefs.h>
1.150.6.1  mjf        35: __KERNEL_RCSID(0, "$NetBSD$");
1.104     martin     36:
1.140     pavel      37: #include "opt_compat_netbsd.h"
1.104     martin     38: #include "opt_usbverbose.h"
1.1       augustss   39:
                     40: #include <sys/param.h>
                     41: #include <sys/systm.h>
                     42: #include <sys/kernel.h>
                     43: #include <sys/malloc.h>
                     44: #include <sys/device.h>
1.56      augustss   45: #include <sys/select.h>
1.1       augustss   46: #include <sys/proc.h>
1.46      augustss   47:
1.149     ad         48: #include <sys/bus.h>
1.1       augustss   49:
                     50: #include <dev/usb/usb.h>
                     51:
                     52: #include <dev/usb/usbdi.h>
                     53: #include <dev/usb/usbdi_util.h>
                     54: #include <dev/usb/usbdivar.h>
                     55: #include <dev/usb/usbdevs.h>
                     56: #include <dev/usb/usb_quirks.h>
                     57:
1.150.6.3  mjf        58: #include "locators.h"
                     59:
1.1       augustss   60: #ifdef USB_DEBUG
1.35      augustss   61: #define DPRINTF(x)     if (usbdebug) logprintf x
                     62: #define DPRINTFN(n,x)  if (usbdebug>(n)) logprintf x
1.1       augustss   63: extern int usbdebug;
                     64: #else
                     65: #define DPRINTF(x)
                     66: #define DPRINTFN(n,x)
                     67: #endif
                     68:
1.82      augustss   69: Static usbd_status usbd_set_config(usbd_device_handle, int);
1.124     augustss   70: Static void usbd_devinfo(usbd_device_handle, int, char *, size_t);
1.123     augustss   71: Static void usbd_devinfo_vp(usbd_device_handle dev,
1.139     pavel      72:                            char *v,
                     73:                            char *p, int usedev,
                     74:                            int useencoded );
1.78      augustss   75: Static int usbd_getnewaddr(usbd_bus_handle bus);
1.118     drochner   76: Static int usbd_print(void *, const char *);
1.144     drochner   77: Static int usbd_ifprint(void *, const char *);
1.78      augustss   78: Static void usbd_free_iface_data(usbd_device_handle dev, int ifcno);
                     79: Static void usbd_kill_pipe(usbd_pipe_handle);
1.150.6.2  mjf        80: usbd_status usbd_attach_roothub(device_t, usbd_device_handle);
1.78      augustss   81: Static usbd_status usbd_probe_and_attach(device_ptr_t parent,
                     82:                                 usbd_device_handle dev, int port, int addr);
1.1       augustss   83:
1.69      augustss   84: Static u_int32_t usb_cookie_no = 0;
1.27      augustss   85:
1.1       augustss   86: #ifdef USBVERBOSE
                     87: typedef u_int16_t usb_vendor_id_t;
                     88: typedef u_int16_t usb_product_id_t;
                     89:
                     90: /*
                     91:  * Descriptions of of known vendors and devices ("products").
                     92:  */
1.122     mycroft    93: struct usb_vendor {
                     94:        usb_vendor_id_t         vendor;
1.126     christos   95:        const char              *vendorname;
1.122     mycroft    96: };
                     97: struct usb_product {
1.1       augustss   98:        usb_vendor_id_t         vendor;
                     99:        usb_product_id_t        product;
1.126     christos  100:        const char              *productname;
1.1       augustss  101: };
                    102:
                    103: #include <dev/usb/usbdevs_data.h>
                    104: #endif /* USBVERBOSE */
                    105:
1.84      jdolecek  106: Static const char * const usbd_error_strs[] = {
1.12      augustss  107:        "NORMAL_COMPLETION",
                    108:        "IN_PROGRESS",
                    109:        "PENDING_REQUESTS",
                    110:        "NOT_STARTED",
                    111:        "INVAL",
                    112:        "NOMEM",
                    113:        "CANCELLED",
                    114:        "BAD_ADDRESS",
                    115:        "IN_USE",
                    116:        "NO_ADDR",
                    117:        "SET_ADDR_FAILED",
                    118:        "NO_POWER",
                    119:        "TOO_DEEP",
                    120:        "IOERROR",
                    121:        "NOT_CONFIGURED",
                    122:        "TIMEOUT",
                    123:        "SHORT_XFER",
                    124:        "STALLED",
1.33      augustss  125:        "INTERRUPTED",
1.12      augustss  126:        "XXX",
                    127: };
1.1       augustss  128:
1.42      thorpej   129: const char *
1.78      augustss  130: usbd_errstr(usbd_status err)
1.39      augustss  131: {
                    132:        static char buffer[5];
                    133:
1.42      thorpej   134:        if (err < USBD_ERROR_MAX) {
1.39      augustss  135:                return usbd_error_strs[err];
                    136:        } else {
                    137:                snprintf(buffer, sizeof buffer, "%d", err);
                    138:                return buffer;
                    139:        }
                    140: }
                    141:
1.13      augustss  142: usbd_status
1.78      augustss  143: usbd_get_string_desc(usbd_device_handle dev, int sindex, int langid,
1.114     mycroft   144:                     usb_string_descriptor_t *sdesc, int *sizep)
1.13      augustss  145: {
                    146:        usb_device_request_t req;
1.116     mycroft   147:        usbd_status err;
                    148:        int actlen;
1.13      augustss  149:
                    150:        req.bmRequestType = UT_READ_DEVICE;
                    151:        req.bRequest = UR_GET_DESCRIPTOR;
                    152:        USETW2(req.wValue, UDESC_STRING, sindex);
                    153:        USETW(req.wIndex, langid);
1.146     christos  154:        USETW(req.wLength, 2);  /* only size byte first */
1.116     mycroft   155:        err = usbd_do_request_flags(dev, &req, sdesc, USBD_SHORT_XFER_OK,
                    156:                &actlen, USBD_DEFAULT_TIMEOUT);
                    157:        if (err)
                    158:                return (err);
                    159:
1.146     christos  160:        if (actlen < 2)
                    161:                return (USBD_SHORT_XFER);
                    162:
                    163:        USETW(req.wLength, sdesc->bLength);     /* the whole string */
                    164:        err = usbd_do_request_flags(dev, &req, sdesc, USBD_SHORT_XFER_OK,
                    165:                &actlen, USBD_DEFAULT_TIMEOUT);
                    166:        if (err)
                    167:                return (err);
                    168:
1.116     mycroft   169:        if (actlen != sdesc->bLength) {
                    170:                DPRINTFN(-1, ("usbd_get_string_desc: expected %d, got %d\n",
                    171:                    sdesc->bLength, actlen));
                    172:        }
                    173:
                    174:        *sizep = actlen;
                    175:        return (USBD_NORMAL_COMPLETION);
1.13      augustss  176: }
                    177:
1.128     enami     178: static void
                    179: usbd_trim_spaces(char *p)
1.83      augustss  180: {
1.128     enami     181:        char *q, *e;
1.83      augustss  182:
1.128     enami     183:        q = e = p;
                    184:        while (*q == ' ')               /* skip leading spaces */
1.85      augustss  185:                q++;
1.128     enami     186:        while ((*p = *q++))             /* copy string */
                    187:                if (*p++ != ' ')        /* remember last non-space */
                    188:                        e = p;
                    189:        *e = '\0';                      /* kill trailing spaces */
1.83      augustss  190: }
                    191:
1.123     augustss  192: Static void
1.139     pavel     193: usbd_devinfo_vp(usbd_device_handle dev, char *v,
                    194:                char *p, int usedev, int useencoded)
1.1       augustss  195: {
                    196:        usb_device_descriptor_t *udd = &dev->ddesc;
1.2       is        197: #ifdef USBVERBOSE
1.122     mycroft   198:        int n;
1.2       is        199: #endif
1.1       augustss  200:
1.128     enami     201:        v[0] = p[0] = '\0';
                    202:        if (dev == NULL)
1.52      augustss  203:                return;
                    204:
1.82      augustss  205:        if (usedev) {
1.139     pavel     206:                if (usbd_get_string0(dev, udd->iManufacturer, v, useencoded) ==
1.128     enami     207:                    USBD_NORMAL_COMPLETION)
                    208:                        usbd_trim_spaces(v);
1.139     pavel     209:                if (usbd_get_string0(dev, udd->iProduct, p, useencoded) ==
1.128     enami     210:                    USBD_NORMAL_COMPLETION)
                    211:                        usbd_trim_spaces(p);
1.82      augustss  212:        }
1.128     enami     213:        /* There is no need for strlcpy & snprintf below. */
1.1       augustss  214: #ifdef USBVERBOSE
1.128     enami     215:        if (v[0] == '\0')
1.122     mycroft   216:                for (n = 0; n < usb_nvendors; n++)
1.128     enami     217:                        if (usb_vendors[n].vendor == UGETW(udd->idVendor)) {
                    218:                                strcpy(v, usb_vendors[n].vendorname);
                    219:                                break;
                    220:                        }
                    221:        if (p[0] == '\0')
1.122     mycroft   222:                for (n = 0; n < usb_nproducts; n++)
                    223:                        if (usb_products[n].vendor == UGETW(udd->idVendor) &&
1.128     enami     224:                            usb_products[n].product == UGETW(udd->idProduct)) {
                    225:                                strcpy(p, usb_products[n].productname);
                    226:                                break;
                    227:                        }
1.1       augustss  228: #endif
1.128     enami     229:        if (v[0] == '\0')
1.123     augustss  230:                sprintf(v, "vendor 0x%04x", UGETW(udd->idVendor));
1.128     enami     231:        if (p[0] == '\0')
1.123     augustss  232:                sprintf(p, "product 0x%04x", UGETW(udd->idProduct));
1.1       augustss  233: }
                    234:
                    235: int
1.113     itojun    236: usbd_printBCD(char *cp, size_t l, int bcd)
1.1       augustss  237: {
1.113     itojun    238:        return (snprintf(cp, l, "%x.%02x", bcd >> 8, bcd & 0xff));
1.1       augustss  239: }
                    240:
1.124     augustss  241: Static void
1.113     itojun    242: usbd_devinfo(usbd_device_handle dev, int showclass, char *cp, size_t l)
1.1       augustss  243: {
                    244:        usb_device_descriptor_t *udd = &dev->ddesc;
1.133     christos  245:        char *vendor, *product;
1.1       augustss  246:        int bcdDevice, bcdUSB;
1.113     itojun    247:        char *ep;
                    248:
1.133     christos  249:        vendor = malloc(USB_MAX_ENCODED_STRING_LEN * 2, M_USB, M_NOWAIT);
                    250:        if (vendor == NULL) {
                    251:                *cp = '\0';
                    252:                return;
                    253:        }
                    254:        product = &vendor[USB_MAX_ENCODED_STRING_LEN];
                    255:
1.113     itojun    256:        ep = cp + l;
1.1       augustss  257:
1.139     pavel     258:        usbd_devinfo_vp(dev, vendor, product, 1, 1);
1.113     itojun    259:        cp += snprintf(cp, ep - cp, "%s %s", vendor, product);
1.1       augustss  260:        if (showclass)
1.113     itojun    261:                cp += snprintf(cp, ep - cp, ", class %d/%d",
                    262:                    udd->bDeviceClass, udd->bDeviceSubClass);
1.1       augustss  263:        bcdUSB = UGETW(udd->bcdUSB);
                    264:        bcdDevice = UGETW(udd->bcdDevice);
1.113     itojun    265:        cp += snprintf(cp, ep - cp, ", rev ");
                    266:        cp += usbd_printBCD(cp, ep - cp, bcdUSB);
1.1       augustss  267:        *cp++ = '/';
1.113     itojun    268:        cp += usbd_printBCD(cp, ep - cp, bcdDevice);
                    269:        cp += snprintf(cp, ep - cp, ", addr %d", dev->address);
1.10      augustss  270:        *cp = 0;
1.133     christos  271:        free(vendor, M_USB);
1.1       augustss  272: }
                    273:
1.124     augustss  274: char *
                    275: usbd_devinfo_alloc(usbd_device_handle dev, int showclass)
                    276: {
                    277:        char *devinfop;
                    278:
                    279:        devinfop = malloc(DEVINFOSIZE, M_TEMP, M_WAITOK);
                    280:        usbd_devinfo(dev, showclass, devinfop, DEVINFOSIZE);
                    281:        return devinfop;
                    282: }
                    283:
                    284: void
                    285: usbd_devinfo_free(char *devinfop)
                    286: {
                    287:        free(devinfop, M_TEMP);
                    288: }
                    289:
1.1       augustss  290: /* Delay for a certain number of ms */
                    291: void
1.78      augustss  292: usb_delay_ms(usbd_bus_handle bus, u_int ms)
1.1       augustss  293: {
                    294:        /* Wait at least two clock ticks so we know the time has passed. */
1.64      augustss  295:        if (bus->use_polling || cold)
1.1       augustss  296:                delay((ms+1) * 1000);
                    297:        else
                    298:                tsleep(&ms, PRIBIO, "usbdly", (ms*hz+999)/1000 + 1);
                    299: }
                    300:
1.23      augustss  301: /* Delay given a device handle. */
                    302: void
1.78      augustss  303: usbd_delay_ms(usbd_device_handle dev, u_int ms)
1.23      augustss  304: {
                    305:        usb_delay_ms(dev->bus, ms);
                    306: }
                    307:
1.1       augustss  308: usbd_status
1.78      augustss  309: usbd_reset_port(usbd_device_handle dev, int port, usb_port_status_t *ps)
1.1       augustss  310: {
                    311:        usb_device_request_t req;
1.53      augustss  312:        usbd_status err;
1.1       augustss  313:        int n;
1.99      augustss  314:
1.1       augustss  315:        req.bmRequestType = UT_WRITE_CLASS_OTHER;
                    316:        req.bRequest = UR_SET_FEATURE;
                    317:        USETW(req.wValue, UHF_PORT_RESET);
                    318:        USETW(req.wIndex, port);
                    319:        USETW(req.wLength, 0);
1.53      augustss  320:        err = usbd_do_request(dev, &req, 0);
1.39      augustss  321:        DPRINTFN(1,("usbd_reset_port: port %d reset done, error=%s\n",
1.53      augustss  322:                    port, usbd_errstr(err)));
                    323:        if (err)
                    324:                return (err);
1.1       augustss  325:        n = 10;
                    326:        do {
                    327:                /* Wait for device to recover from reset. */
1.23      augustss  328:                usbd_delay_ms(dev, USB_PORT_RESET_DELAY);
1.53      augustss  329:                err = usbd_get_port_status(dev, port, ps);
                    330:                if (err) {
                    331:                        DPRINTF(("usbd_reset_port: get status failed %d\n",
                    332:                                 err));
                    333:                        return (err);
1.1       augustss  334:                }
1.92      augustss  335:                /* If the device disappeared, just give up. */
                    336:                if (!(UGETW(ps->wPortStatus) & UPS_CURRENT_CONNECT_STATUS))
                    337:                        return (USBD_NORMAL_COMPLETION);
1.1       augustss  338:        } while ((UGETW(ps->wPortChange) & UPS_C_PORT_RESET) == 0 && --n > 0);
1.73      augustss  339:        if (n == 0)
                    340:                return (USBD_TIMEOUT);
1.53      augustss  341:        err = usbd_clear_port_feature(dev, port, UHF_C_PORT_RESET);
1.1       augustss  342: #ifdef USB_DEBUG
1.53      augustss  343:        if (err)
                    344:                DPRINTF(("usbd_reset_port: clear port feature failed %d\n",
                    345:                         err));
1.1       augustss  346: #endif
1.18      augustss  347:
                    348:        /* Wait for the device to recover from reset. */
1.23      augustss  349:        usbd_delay_ms(dev, USB_PORT_RESET_RECOVERY);
1.53      augustss  350:        return (err);
1.1       augustss  351: }
                    352:
1.12      augustss  353: usb_interface_descriptor_t *
1.78      augustss  354: usbd_find_idesc(usb_config_descriptor_t *cd, int ifaceidx, int altidx)
1.12      augustss  355: {
                    356:        char *p = (char *)cd;
                    357:        char *end = p + UGETW(cd->wTotalLength);
                    358:        usb_interface_descriptor_t *d;
1.19      augustss  359:        int curidx, lastidx, curaidx = 0;
1.12      augustss  360:
1.19      augustss  361:        for (curidx = lastidx = -1; p < end; ) {
1.12      augustss  362:                d = (usb_interface_descriptor_t *)p;
1.18      augustss  363:                DPRINTFN(4,("usbd_find_idesc: idx=%d(%d) altidx=%d(%d) len=%d "
1.99      augustss  364:                            "type=%d\n",
1.18      augustss  365:                            ifaceidx, curidx, altidx, curaidx,
                    366:                            d->bLength, d->bDescriptorType));
1.12      augustss  367:                if (d->bLength == 0) /* bad descriptor */
                    368:                        break;
                    369:                p += d->bLength;
                    370:                if (p <= end && d->bDescriptorType == UDESC_INTERFACE) {
1.19      augustss  371:                        if (d->bInterfaceNumber != lastidx) {
                    372:                                lastidx = d->bInterfaceNumber;
1.12      augustss  373:                                curidx++;
                    374:                                curaidx = 0;
                    375:                        } else
                    376:                                curaidx++;
                    377:                        if (ifaceidx == curidx && altidx == curaidx)
                    378:                                return (d);
                    379:                }
                    380:        }
1.58      augustss  381:        return (NULL);
1.12      augustss  382: }
                    383:
                    384: usb_endpoint_descriptor_t *
1.99      augustss  385: usbd_find_edesc(usb_config_descriptor_t *cd, int ifaceidx, int altidx,
1.78      augustss  386:                int endptidx)
1.12      augustss  387: {
                    388:        char *p = (char *)cd;
                    389:        char *end = p + UGETW(cd->wTotalLength);
                    390:        usb_interface_descriptor_t *d;
                    391:        usb_endpoint_descriptor_t *e;
                    392:        int curidx;
                    393:
                    394:        d = usbd_find_idesc(cd, ifaceidx, altidx);
1.53      augustss  395:        if (d == NULL)
1.58      augustss  396:                return (NULL);
1.12      augustss  397:        if (endptidx >= d->bNumEndpoints) /* quick exit */
1.58      augustss  398:                return (NULL);
1.12      augustss  399:
                    400:        curidx = -1;
                    401:        for (p = (char *)d + d->bLength; p < end; ) {
                    402:                e = (usb_endpoint_descriptor_t *)p;
                    403:                if (e->bLength == 0) /* bad descriptor */
                    404:                        break;
                    405:                p += e->bLength;
                    406:                if (p <= end && e->bDescriptorType == UDESC_INTERFACE)
1.58      augustss  407:                        return (NULL);
1.12      augustss  408:                if (p <= end && e->bDescriptorType == UDESC_ENDPOINT) {
                    409:                        curidx++;
                    410:                        if (curidx == endptidx)
                    411:                                return (e);
                    412:                }
1.1       augustss  413:        }
1.58      augustss  414:        return (NULL);
1.1       augustss  415: }
                    416:
                    417: usbd_status
1.78      augustss  418: usbd_fill_iface_data(usbd_device_handle dev, int ifaceidx, int altidx)
1.1       augustss  419: {
1.12      augustss  420:        usbd_interface_handle ifc = &dev->ifaces[ifaceidx];
1.77      augustss  421:        usb_interface_descriptor_t *idesc;
1.1       augustss  422:        char *p, *end;
                    423:        int endpt, nendpt;
                    424:
1.18      augustss  425:        DPRINTFN(4,("usbd_fill_iface_data: ifaceidx=%d altidx=%d\n",
1.14      drochner  426:                    ifaceidx, altidx));
1.77      augustss  427:        idesc = usbd_find_idesc(dev->cdesc, ifaceidx, altidx);
                    428:        if (idesc == NULL)
                    429:                return (USBD_INVAL);
1.1       augustss  430:        ifc->device = dev;
1.77      augustss  431:        ifc->idesc = idesc;
1.13      augustss  432:        ifc->index = ifaceidx;
                    433:        ifc->altindex = altidx;
1.1       augustss  434:        nendpt = ifc->idesc->bNumEndpoints;
1.59      augustss  435:        DPRINTFN(4,("usbd_fill_iface_data: found idesc nendpt=%d\n", nendpt));
1.1       augustss  436:        if (nendpt != 0) {
                    437:                ifc->endpoints = malloc(nendpt * sizeof(struct usbd_endpoint),
                    438:                                        M_USB, M_NOWAIT);
1.58      augustss  439:                if (ifc->endpoints == NULL)
1.1       augustss  440:                        return (USBD_NOMEM);
                    441:        } else
1.58      augustss  442:                ifc->endpoints = NULL;
                    443:        ifc->priv = NULL;
1.1       augustss  444:        p = (char *)ifc->idesc + ifc->idesc->bLength;
                    445:        end = (char *)dev->cdesc + UGETW(dev->cdesc->wTotalLength);
1.19      augustss  446: #define ed ((usb_endpoint_descriptor_t *)p)
1.1       augustss  447:        for (endpt = 0; endpt < nendpt; endpt++) {
                    448:                DPRINTFN(10,("usbd_fill_iface_data: endpt=%d\n", endpt));
                    449:                for (; p < end; p += ed->bLength) {
1.14      drochner  450:                        DPRINTFN(10,("usbd_fill_iface_data: p=%p end=%p "
                    451:                                     "len=%d type=%d\n",
1.1       augustss  452:                                 p, end, ed->bLength, ed->bDescriptorType));
1.24      augustss  453:                        if (p + ed->bLength <= end && ed->bLength != 0 &&
1.1       augustss  454:                            ed->bDescriptorType == UDESC_ENDPOINT)
1.24      augustss  455:                                goto found;
1.59      augustss  456:                        if (ed->bLength == 0 ||
                    457:                            ed->bDescriptorType == UDESC_INTERFACE)
1.1       augustss  458:                                break;
                    459:                }
1.24      augustss  460:                /* passed end, or bad desc */
1.95      augustss  461:                printf("usbd_fill_iface_data: bad descriptor(s): %s\n",
                    462:                       ed->bLength == 0 ? "0 length" :
                    463:                       ed->bDescriptorType == UDESC_INTERFACE ? "iface desc":
                    464:                       "out of data");
1.24      augustss  465:                goto bad;
                    466:        found:
1.1       augustss  467:                ifc->endpoints[endpt].edesc = ed;
1.95      augustss  468:                if (dev->speed == USB_SPEED_HIGH) {
                    469:                        u_int mps;
                    470:                        /* Control and bulk endpoints have max packet limits. */
                    471:                        switch (UE_GET_XFERTYPE(ed->bmAttributes)) {
                    472:                        case UE_CONTROL:
                    473:                                mps = USB_2_MAX_CTRL_PACKET;
                    474:                                goto check;
                    475:                        case UE_BULK:
                    476:                                mps = USB_2_MAX_BULK_PACKET;
                    477:                        check:
                    478:                                if (UGETW(ed->wMaxPacketSize) != mps) {
                    479:                                        USETW(ed->wMaxPacketSize, mps);
                    480: #ifdef DIAGNOSTIC
                    481:                                        printf("usbd_fill_iface_data: bad max "
                    482:                                               "packet size\n");
                    483: #endif
                    484:                                }
                    485:                                break;
                    486:                        default:
                    487:                                break;
                    488:                        }
                    489:                }
1.1       augustss  490:                ifc->endpoints[endpt].refcnt = 0;
1.24      augustss  491:                p += ed->bLength;
1.1       augustss  492:        }
1.19      augustss  493: #undef ed
1.1       augustss  494:        LIST_INIT(&ifc->pipes);
                    495:        return (USBD_NORMAL_COMPLETION);
1.24      augustss  496:
1.1       augustss  497:  bad:
1.77      augustss  498:        if (ifc->endpoints != NULL) {
1.59      augustss  499:                free(ifc->endpoints, M_USB);
1.77      augustss  500:                ifc->endpoints = NULL;
                    501:        }
1.24      augustss  502:        return (USBD_INVAL);
1.1       augustss  503: }
                    504:
                    505: void
1.78      augustss  506: usbd_free_iface_data(usbd_device_handle dev, int ifcno)
1.1       augustss  507: {
                    508:        usbd_interface_handle ifc = &dev->ifaces[ifcno];
                    509:        if (ifc->endpoints)
                    510:                free(ifc->endpoints, M_USB);
                    511: }
                    512:
1.69      augustss  513: Static usbd_status
1.78      augustss  514: usbd_set_config(usbd_device_handle dev, int conf)
1.7       augustss  515: {
                    516:        usb_device_request_t req;
                    517:
                    518:        req.bmRequestType = UT_WRITE_DEVICE;
                    519:        req.bRequest = UR_SET_CONFIG;
                    520:        USETW(req.wValue, conf);
                    521:        USETW(req.wIndex, 0);
                    522:        USETW(req.wLength, 0);
                    523:        return (usbd_do_request(dev, &req, 0));
                    524: }
                    525:
1.1       augustss  526: usbd_status
1.78      augustss  527: usbd_set_config_no(usbd_device_handle dev, int no, int msg)
1.1       augustss  528: {
1.12      augustss  529:        int index;
                    530:        usb_config_descriptor_t cd;
1.53      augustss  531:        usbd_status err;
1.12      augustss  532:
1.75      augustss  533:        if (no == USB_UNCONFIG_NO)
                    534:                return (usbd_set_config_index(dev, USB_UNCONFIG_INDEX, msg));
                    535:
1.12      augustss  536:        DPRINTFN(5,("usbd_set_config_no: %d\n", no));
                    537:        /* Figure out what config index to use. */
                    538:        for (index = 0; index < dev->ddesc.bNumConfigurations; index++) {
1.53      augustss  539:                err = usbd_get_config_desc(dev, index, &cd);
                    540:                if (err)
                    541:                        return (err);
1.12      augustss  542:                if (cd.bConfigurationValue == no)
                    543:                        return (usbd_set_config_index(dev, index, msg));
                    544:        }
                    545:        return (USBD_INVAL);
                    546: }
                    547:
                    548: usbd_status
1.78      augustss  549: usbd_set_config_index(usbd_device_handle dev, int index, int msg)
1.12      augustss  550: {
1.1       augustss  551:        usb_config_descriptor_t cd, *cdp;
1.53      augustss  552:        usbd_status err;
1.103     augustss  553:        int i, ifcidx, nifc, len, selfpowered, power;
1.1       augustss  554:
1.12      augustss  555:        DPRINTFN(5,("usbd_set_config_index: dev=%p index=%d\n", dev, index));
1.1       augustss  556:
1.145     drochner  557:        if (index >= dev->ddesc.bNumConfigurations &&
1.150.6.4! mjf       558:            index != USB_UNCONFIG_INDEX) {
1.145     drochner  559:                /* panic? */
                    560:                printf("usbd_set_config_index: illegal index\n");
                    561:                return (USBD_INVAL);
                    562:        }
                    563:
1.1       augustss  564:        /* XXX check that all interfaces are idle */
1.75      augustss  565:        if (dev->config != USB_UNCONFIG_NO) {
1.12      augustss  566:                DPRINTF(("usbd_set_config_index: free old config\n"));
1.1       augustss  567:                /* Free all configuration data structures. */
                    568:                nifc = dev->cdesc->bNumInterface;
1.12      augustss  569:                for (ifcidx = 0; ifcidx < nifc; ifcidx++)
                    570:                        usbd_free_iface_data(dev, ifcidx);
1.1       augustss  571:                free(dev->ifaces, M_USB);
                    572:                free(dev->cdesc, M_USB);
1.57      augustss  573:                dev->ifaces = NULL;
                    574:                dev->cdesc = NULL;
1.75      augustss  575:                dev->config = USB_UNCONFIG_NO;
                    576:        }
                    577:
                    578:        if (index == USB_UNCONFIG_INDEX) {
                    579:                /* We are unconfiguring the device, so leave unallocated. */
                    580:                DPRINTF(("usbd_set_config_index: set config 0\n"));
                    581:                err = usbd_set_config(dev, USB_UNCONFIG_NO);
1.136     christos  582:                if (err) {
1.75      augustss  583:                        DPRINTF(("usbd_set_config_index: setting config=0 "
                    584:                                 "failed, error=%s\n", usbd_errstr(err)));
1.136     christos  585:                }
1.75      augustss  586:                return (err);
1.1       augustss  587:        }
                    588:
1.74      augustss  589:        /* Get the short descriptor. */
1.53      augustss  590:        err = usbd_get_config_desc(dev, index, &cd);
                    591:        if (err)
                    592:                return (err);
1.1       augustss  593:        len = UGETW(cd.wTotalLength);
                    594:        cdp = malloc(len, M_USB, M_NOWAIT);
1.53      augustss  595:        if (cdp == NULL)
1.1       augustss  596:                return (USBD_NOMEM);
1.103     augustss  597:
                    598:        /* Get the full descriptor.  Try a few times for slow devices. */
                    599:        for (i = 0; i < 3; i++) {
                    600:                err = usbd_get_desc(dev, UDESC_CONFIG, index, len, cdp);
                    601:                if (!err)
                    602:                        break;
                    603:                usbd_delay_ms(dev, 200);
                    604:        }
1.53      augustss  605:        if (err)
1.1       augustss  606:                goto bad;
1.103     augustss  607:
1.18      augustss  608:        if (cdp->bDescriptorType != UDESC_CONFIG) {
                    609:                DPRINTFN(-1,("usbd_set_config_index: bad desc %d\n",
                    610:                             cdp->bDescriptorType));
1.53      augustss  611:                err = USBD_INVAL;
1.18      augustss  612:                goto bad;
                    613:        }
1.74      augustss  614:
1.142     drochner  615:        /*
                    616:         * Figure out if the device is self or bus powered.
                    617:         */
                    618: #if 0 /* XXX various devices don't report the power state correctly */
1.1       augustss  619:        selfpowered = 0;
1.141     drochner  620:        err = usbd_get_device_status(dev, &ds);
                    621:        if (!err && (UGETW(ds.wStatus) & UDS_SELF_POWERED))
                    622:                selfpowered = 1;
1.142     drochner  623: #endif
                    624:        /*
                    625:         * Use the power state in the configuration we are going
                    626:         * to set. This doesn't necessarily reflect the actual
                    627:         * power state of the device; the driver can control this
                    628:         * by choosing the appropriate configuration.
                    629:         */
                    630:        selfpowered = !!(cdp->bmAttributes & UC_SELF_POWERED);
1.141     drochner  631:
1.81      augustss  632:        DPRINTF(("usbd_set_config_index: (addr %d) cno=%d attr=0x%02x, "
                    633:                 "selfpowered=%d, power=%d\n",
1.99      augustss  634:                 cdp->bConfigurationValue, dev->address, cdp->bmAttributes,
1.33      augustss  635:                 selfpowered, cdp->bMaxPower * 2));
1.74      augustss  636:
                    637:        /* Check if we have enough power. */
1.142     drochner  638: #if 0 /* this is a no-op, see above */
1.141     drochner  639:        if ((cdp->bmAttributes & UC_SELF_POWERED) && !selfpowered) {
                    640:                if (msg)
                    641:                        printf("%s: device addr %d (config %d): "
                    642:                                 "can't set self powered configuration\n",
                    643:                               USBDEVNAME(dev->bus->bdev), dev->address,
                    644:                               cdp->bConfigurationValue);
                    645:                err = USBD_NO_POWER;
                    646:                goto bad;
                    647:        }
1.142     drochner  648: #endif
1.1       augustss  649: #ifdef USB_DEBUG
1.53      augustss  650:        if (dev->powersrc == NULL) {
1.44      augustss  651:                DPRINTF(("usbd_set_config_index: No power source?\n"));
1.141     drochner  652:                err = USBD_IOERROR;
                    653:                goto bad;
1.1       augustss  654:        }
                    655: #endif
                    656:        power = cdp->bMaxPower * 2;
                    657:        if (power > dev->powersrc->power) {
1.81      augustss  658:                DPRINTF(("power exceeded %d %d\n", power,dev->powersrc->power));
1.1       augustss  659:                /* XXX print nicer message. */
1.7       augustss  660:                if (msg)
1.18      augustss  661:                        printf("%s: device addr %d (config %d) exceeds power "
                    662:                                 "budget, %d mA > %d mA\n",
1.150.6.1  mjf       663:                               device_xname(dev->bus->usbctl), dev->address,
1.99      augustss  664:                               cdp->bConfigurationValue,
1.7       augustss  665:                               power, dev->powersrc->power);
1.53      augustss  666:                err = USBD_NO_POWER;
1.1       augustss  667:                goto bad;
                    668:        }
                    669:        dev->power = power;
                    670:        dev->self_powered = selfpowered;
                    671:
1.74      augustss  672:        /* Set the actual configuration value. */
1.18      augustss  673:        DPRINTF(("usbd_set_config_index: set config %d\n",
                    674:                 cdp->bConfigurationValue));
1.53      augustss  675:        err = usbd_set_config(dev, cdp->bConfigurationValue);
                    676:        if (err) {
1.14      drochner  677:                DPRINTF(("usbd_set_config_index: setting config=%d failed, "
1.39      augustss  678:                         "error=%s\n",
1.53      augustss  679:                         cdp->bConfigurationValue, usbd_errstr(err)));
1.1       augustss  680:                goto bad;
                    681:        }
1.74      augustss  682:
                    683:        /* Allocate and fill interface data. */
1.1       augustss  684:        nifc = cdp->bNumInterface;
1.99      augustss  685:        dev->ifaces = malloc(nifc * sizeof(struct usbd_interface),
1.1       augustss  686:                             M_USB, M_NOWAIT);
1.58      augustss  687:        if (dev->ifaces == NULL) {
1.53      augustss  688:                err = USBD_NOMEM;
1.1       augustss  689:                goto bad;
                    690:        }
1.12      augustss  691:        DPRINTFN(5,("usbd_set_config_index: dev=%p cdesc=%p\n", dev, cdp));
1.1       augustss  692:        dev->cdesc = cdp;
                    693:        dev->config = cdp->bConfigurationValue;
1.12      augustss  694:        for (ifcidx = 0; ifcidx < nifc; ifcidx++) {
1.53      augustss  695:                err = usbd_fill_iface_data(dev, ifcidx, 0);
                    696:                if (err) {
1.12      augustss  697:                        while (--ifcidx >= 0)
                    698:                                usbd_free_iface_data(dev, ifcidx);
1.1       augustss  699:                        goto bad;
                    700:                }
                    701:        }
                    702:
                    703:        return (USBD_NORMAL_COMPLETION);
                    704:
                    705:  bad:
                    706:        free(cdp, M_USB);
1.53      augustss  707:        return (err);
1.1       augustss  708: }
                    709:
                    710: /* XXX add function for alternate settings */
                    711:
                    712: usbd_status
1.78      augustss  713: usbd_setup_pipe(usbd_device_handle dev, usbd_interface_handle iface,
                    714:                struct usbd_endpoint *ep, int ival, usbd_pipe_handle *pipe)
1.1       augustss  715: {
                    716:        usbd_pipe_handle p;
1.53      augustss  717:        usbd_status err;
1.1       augustss  718:
                    719:        DPRINTFN(1,("usbd_setup_pipe: dev=%p iface=%p ep=%p pipe=%p\n",
                    720:                    dev, iface, ep, pipe));
                    721:        p = malloc(dev->bus->pipe_size, M_USB, M_NOWAIT);
1.53      augustss  722:        if (p == NULL)
1.1       augustss  723:                return (USBD_NOMEM);
                    724:        p->device = dev;
                    725:        p->iface = iface;
                    726:        p->endpoint = ep;
                    727:        ep->refcnt++;
                    728:        p->refcnt = 1;
1.53      augustss  729:        p->intrxfer = 0;
1.1       augustss  730:        p->running = 0;
1.70      augustss  731:        p->aborting = 0;
1.34      augustss  732:        p->repeat = 0;
1.63      augustss  733:        p->interval = ival;
1.1       augustss  734:        SIMPLEQ_INIT(&p->queue);
1.53      augustss  735:        err = dev->bus->methods->open_pipe(p);
                    736:        if (err) {
1.39      augustss  737:                DPRINTFN(-1,("usbd_setup_pipe: endpoint=0x%x failed, error="
                    738:                         "%s\n",
1.53      augustss  739:                         ep->edesc->bEndpointAddress, usbd_errstr(err)));
1.1       augustss  740:                free(p, M_USB);
1.53      augustss  741:                return (err);
1.1       augustss  742:        }
                    743:        *pipe = p;
                    744:        return (USBD_NORMAL_COMPLETION);
                    745: }
                    746:
                    747: /* Abort the device control pipe. */
                    748: void
1.78      augustss  749: usbd_kill_pipe(usbd_pipe_handle pipe)
1.1       augustss  750: {
1.89      augustss  751:        usbd_abort_pipe(pipe);
1.1       augustss  752:        pipe->methods->close(pipe);
                    753:        pipe->endpoint->refcnt--;
                    754:        free(pipe, M_USB);
                    755: }
                    756:
                    757: int
1.78      augustss  758: usbd_getnewaddr(usbd_bus_handle bus)
1.1       augustss  759: {
1.18      augustss  760:        int addr;
1.1       augustss  761:
1.18      augustss  762:        for (addr = 1; addr < USB_MAX_DEVICES; addr++)
                    763:                if (bus->devices[addr] == 0)
                    764:                        return (addr);
1.1       augustss  765:        return (-1);
                    766: }
                    767:
1.150.6.2  mjf       768: usbd_status
                    769: usbd_attach_roothub(device_t parent, usbd_device_handle dev)
                    770: {
                    771:        struct usb_attach_arg uaa;
                    772:        usb_device_descriptor_t *dd = &dev->ddesc;
                    773:        device_t dv;
                    774:
                    775:        uaa.device = dev;
                    776:        uaa.usegeneric = 0;
                    777:        uaa.port = 0;
                    778:        uaa.vendor = UGETW(dd->idVendor);
                    779:        uaa.product = UGETW(dd->idProduct);
                    780:        uaa.release = UGETW(dd->bcdDevice);
                    781:        uaa.class = dd->bDeviceClass;
                    782:        uaa.subclass = dd->bDeviceSubClass;
                    783:        uaa.proto = dd->bDeviceProtocol;
                    784:
                    785:        dv = config_found_ia(parent, "usbroothubif", &uaa, 0);
                    786:        if (dv) {
                    787:                dev->subdevs = malloc(sizeof dv, M_USB, M_NOWAIT);
                    788:                if (dev->subdevs == NULL)
                    789:                        return (USBD_NOMEM);
                    790:                dev->subdevs[0] = dv;
                    791:                dev->subdevlen = 1;
                    792:        }
                    793:        return (USBD_NORMAL_COMPLETION);
                    794: }
1.18      augustss  795:
1.150.6.4! mjf       796: static usbd_status
        !           797: usbd_attachwholedevice(device_t parent, usbd_device_handle dev, int port,
        !           798:        int usegeneric)
1.18      augustss  799: {
                    800:        struct usb_attach_arg uaa;
                    801:        usb_device_descriptor_t *dd = &dev->ddesc;
1.150.6.4! mjf       802:        device_t dv;
1.150.6.3  mjf       803:        int dlocs[USBDEVIFCF_NLOCS];
1.18      augustss  804:
                    805:        uaa.device = dev;
1.150.6.4! mjf       806:        uaa.usegeneric = usegeneric;
1.18      augustss  807:        uaa.port = port;
1.32      augustss  808:        uaa.vendor = UGETW(dd->idVendor);
                    809:        uaa.product = UGETW(dd->idProduct);
                    810:        uaa.release = UGETW(dd->bcdDevice);
1.144     drochner  811:        uaa.class = dd->bDeviceClass;
                    812:        uaa.subclass = dd->bDeviceSubClass;
                    813:        uaa.proto = dd->bDeviceProtocol;
1.18      augustss  814:
1.150.6.3  mjf       815:        dlocs[USBDEVIFCF_PORT] = uaa.port;
                    816:        dlocs[USBDEVIFCF_VENDOR] = uaa.vendor;
                    817:        dlocs[USBDEVIFCF_PRODUCT] = uaa.product;
                    818:        dlocs[USBDEVIFCF_RELEASE] = uaa.release;
                    819:        /* the rest is historical ballast */
                    820:        dlocs[USBDEVIFCF_CONFIGURATION] = -1;
                    821:        dlocs[USBDEVIFCF_INTERFACE] = -1;
                    822:
                    823:        dv = config_found_sm_loc(parent, "usbdevif", dlocs, &uaa, usbd_print,
1.150.6.4! mjf       824:                                 config_stdsubmatch);
1.34      augustss  825:        if (dv) {
1.150.6.2  mjf       826:                dev->subdevs = malloc(sizeof dv, M_USB, M_NOWAIT);
1.57      augustss  827:                if (dev->subdevs == NULL)
1.34      augustss  828:                        return (USBD_NOMEM);
                    829:                dev->subdevs[0] = dv;
1.150.6.2  mjf       830:                dev->subdevlen = 1;
1.150.6.4! mjf       831:                dev->nifaces_claimed = 1; /* XXX */
1.34      augustss  832:        }
1.150.6.4! mjf       833:        return (USBD_NORMAL_COMPLETION);
        !           834: }
1.18      augustss  835:
1.150.6.4! mjf       836: static usbd_status
        !           837: usbd_attachinterfaces(device_t parent, usbd_device_handle dev,
        !           838:                      int port, const int *locators)
        !           839: {
        !           840:        struct usbif_attach_arg uiaa;
        !           841:        int ilocs[USBIFIFCF_NLOCS];
        !           842:        usb_device_descriptor_t *dd = &dev->ddesc;
        !           843:        int nifaces;
        !           844:        usbd_interface_handle *ifaces;
        !           845:        int i, j, loc;
        !           846:        device_t dv;
        !           847:
        !           848:        nifaces = dev->cdesc->bNumInterface;
        !           849:        ifaces = malloc(nifaces * sizeof(*ifaces), M_USB, M_NOWAIT|M_ZERO);
        !           850:        if (!ifaces)
        !           851:                return (USBD_NOMEM);
        !           852:        for (i = 0; i < nifaces; i++)
        !           853:                if (!dev->subdevs[i])
        !           854:                        ifaces[i] = &dev->ifaces[i];
1.18      augustss  855:
1.144     drochner  856:        uiaa.device = dev;
                    857:        uiaa.port = port;
                    858:        uiaa.vendor = UGETW(dd->idVendor);
                    859:        uiaa.product = UGETW(dd->idProduct);
                    860:        uiaa.release = UGETW(dd->bcdDevice);
1.150.6.4! mjf       861:        uiaa.configno = dev->cdesc->bConfigurationValue;
        !           862:        uiaa.ifaces = ifaces;
        !           863:        uiaa.nifaces = nifaces;
1.150.6.3  mjf       864:        ilocs[USBIFIFCF_PORT] = uiaa.port;
                    865:        ilocs[USBIFIFCF_VENDOR] = uiaa.vendor;
                    866:        ilocs[USBIFIFCF_PRODUCT] = uiaa.product;
                    867:        ilocs[USBIFIFCF_RELEASE] = uiaa.release;
1.150.6.4! mjf       868:        ilocs[USBIFIFCF_CONFIGURATION] = uiaa.configno;
        !           869:
        !           870:        for (i = 0; i < nifaces; i++) {
        !           871:                if (!ifaces[i])
        !           872:                        continue; /* interface already claimed */
        !           873:                uiaa.iface = ifaces[i];
        !           874:                uiaa.class = ifaces[i]->idesc->bInterfaceClass;
        !           875:                uiaa.subclass = ifaces[i]->idesc->bInterfaceSubClass;
        !           876:                uiaa.proto = ifaces[i]->idesc->bInterfaceProtocol;
        !           877:                uiaa.ifaceno = ifaces[i]->idesc->bInterfaceNumber;
        !           878:                ilocs[USBIFIFCF_INTERFACE] = uiaa.ifaceno;
        !           879:                if (locators != NULL) {
        !           880:                        loc = locators[USBIFIFCF_CONFIGURATION];
        !           881:                        if (loc != USBIFIFCF_CONFIGURATION_DEFAULT &&
        !           882:                            loc != uiaa.configno)
        !           883:                                continue;
        !           884:                        loc = locators[USBIFIFCF_INTERFACE];
        !           885:                        if (loc != USBIFIFCF_INTERFACE && loc != uiaa.ifaceno)
        !           886:                                continue;
        !           887:                }
        !           888:                dv = config_found_sm_loc(parent, "usbifif", ilocs, &uiaa,
        !           889:                                         usbd_ifprint, config_stdsubmatch);
        !           890:                if (!dv)
        !           891:                        continue;
        !           892:                ifaces[i] = 0; /* claim */
        !           893:                /* account for ifaces claimed by the driver behind our back */
        !           894:                for (j = 0; j < nifaces; j++) {
        !           895:                        if (!ifaces[j] && !dev->subdevs[j]) {
        !           896:                                dev->subdevs[j] = dv;
        !           897:                                dev->nifaces_claimed++;
        !           898:                        }
        !           899:                }
        !           900:        }
        !           901:
        !           902:        free(ifaces, M_USB);
        !           903:        return (USBD_NORMAL_COMPLETION);
        !           904: }
        !           905:
        !           906: usbd_status
        !           907: usbd_probe_and_attach(device_ptr_t parent, usbd_device_handle dev,
        !           908:                      int port, int addr)
        !           909: {
        !           910:        usb_device_descriptor_t *dd = &dev->ddesc;
        !           911:        int confi, nifaces;
        !           912:        usbd_status err;
        !           913:
        !           914:        /* First try with device specific drivers. */
        !           915:        DPRINTF(("usbd_probe_and_attach: trying device specific drivers\n"));
        !           916:        err = usbd_attachwholedevice(parent, dev, port, 0);
        !           917:        if (dev->nifaces_claimed || err)
        !           918:                return (err);
        !           919:        DPRINTF(("usbd_probe_and_attach: no device specific driver found\n"));
1.150.6.3  mjf       920:
1.60      augustss  921:        DPRINTF(("usbd_probe_and_attach: looping over %d configurations\n",
                    922:                 dd->bNumConfigurations));
1.18      augustss  923:        for (confi = 0; confi < dd->bNumConfigurations; confi++) {
                    924:                DPRINTFN(1,("usbd_probe_and_attach: trying config idx=%d\n",
                    925:                            confi));
1.53      augustss  926:                err = usbd_set_config_index(dev, confi, 1);
                    927:                if (err) {
1.18      augustss  928: #ifdef USB_DEBUG
                    929:                        DPRINTF(("%s: port %d, set config at addr %d failed, "
1.43      augustss  930:                                 "error=%s\n", USBDEVPTRNAME(parent), port,
1.53      augustss  931:                                 addr, usbd_errstr(err)));
1.18      augustss  932: #else
                    933:                        printf("%s: port %d, set config at addr %d failed\n",
1.43      augustss  934:                               USBDEVPTRNAME(parent), port, addr);
1.18      augustss  935: #endif
1.150.6.4! mjf       936:                        return (err);
1.18      augustss  937:                }
1.20      augustss  938:                nifaces = dev->cdesc->bNumInterface;
1.150.6.4! mjf       939:                dev->subdevs = malloc(nifaces * sizeof(device_t), M_USB,
1.150.6.2  mjf       940:                                      M_NOWAIT|M_ZERO);
1.150.6.4! mjf       941:                if (dev->subdevs == NULL)
1.34      augustss  942:                        return (USBD_NOMEM);
1.150.6.2  mjf       943:                dev->subdevlen = nifaces;
1.52      augustss  944:
1.150.6.4! mjf       945:                err = usbd_attachinterfaces(parent, dev, port, NULL);
        !           946:
        !           947:                if (!dev->nifaces_claimed) {
        !           948:                        free(dev->subdevs, M_USB);
        !           949:                        dev->subdevs = 0;
        !           950:                        dev->subdevlen = 0;
1.52      augustss  951:                }
1.150.6.4! mjf       952:                if (dev->nifaces_claimed || err)
        !           953:                        return (err);
1.18      augustss  954:        }
1.21      augustss  955:        /* No interfaces were attached in any of the configurations. */
1.34      augustss  956:
                    957:        if (dd->bNumConfigurations > 1) /* don't change if only 1 config */
1.18      augustss  958:                usbd_set_config_index(dev, 0, 0);
                    959:
                    960:        DPRINTF(("usbd_probe_and_attach: no interface drivers found\n"));
                    961:
                    962:        /* Finally try the generic driver. */
1.150.6.4! mjf       963:        err = usbd_attachwholedevice(parent, dev, port, 1);
1.18      augustss  964:
1.99      augustss  965:        /*
1.18      augustss  966:         * The generic attach failed, but leave the device as it is.
                    967:         * We just did not find any drivers, that's all.  The device is
                    968:         * fully operational and not harming anyone.
                    969:         */
                    970:        DPRINTF(("usbd_probe_and_attach: generic attach failed\n"));
1.150.6.4! mjf       971:        return (USBD_NORMAL_COMPLETION);
1.18      augustss  972: }
                    973:
1.150.6.4! mjf       974: /**
        !           975:  * Called from uhub_rescan().  usbd_new_device() for the target dev must be
        !           976:  * called before calling this.
        !           977:  */
        !           978: usbd_status
        !           979: usbd_reattach_device(device_ptr_t parent, usbd_device_handle dev,
        !           980:                     int port, const int *locators)
        !           981: {
        !           982:        int i, loc;
        !           983:
        !           984:        if (locators != NULL) {
        !           985:                loc = locators[USBIFIFCF_PORT];
        !           986:                if (loc != USBIFIFCF_PORT_DEFAULT && loc != port)
        !           987:                        return USBD_NORMAL_COMPLETION;
        !           988:                loc = locators[USBIFIFCF_VENDOR];
        !           989:                if (loc != USBIFIFCF_VENDOR_DEFAULT &&
        !           990:                    loc != UGETW(dev->ddesc.idVendor))
        !           991:                        return USBD_NORMAL_COMPLETION;
        !           992:                loc = locators[USBIFIFCF_PRODUCT];
        !           993:                if (loc != USBIFIFCF_PRODUCT_DEFAULT &&
        !           994:                    loc != UGETW(dev->ddesc.idProduct))
        !           995:                        return USBD_NORMAL_COMPLETION;
        !           996:                loc = locators[USBIFIFCF_RELEASE];
        !           997:                if (loc != USBIFIFCF_RELEASE_DEFAULT &&
        !           998:                    loc != UGETW(dev->ddesc.bcdDevice))
        !           999:                        return USBD_NORMAL_COMPLETION;
        !          1000:        }
        !          1001:        if (dev->subdevlen == 0) {
        !          1002:                /* XXX: check USBIFIFCF_CONFIGURATION and
        !          1003:                 * USBIFIFCF_INTERFACE too */
        !          1004:                return usbd_probe_and_attach(parent, dev, port, dev->address);
        !          1005:        } else if (dev->subdevlen != dev->cdesc->bNumInterface) {
        !          1006:                /* device-specific or generic driver is already attached. */
        !          1007:                return USBD_NORMAL_COMPLETION;
        !          1008:        }
        !          1009:        /* Does the device have unconfigured interfaces? */
        !          1010:        for (i = 0; i < dev->subdevlen; i++) {
        !          1011:                if (dev->subdevs[i] == NULL) {
        !          1012:                        break;
        !          1013:                }
        !          1014:        }
        !          1015:        if (i >= dev->subdevlen)
        !          1016:                return USBD_NORMAL_COMPLETION;
        !          1017:        return usbd_attachinterfaces(parent, dev, port, locators);
        !          1018: }
1.18      augustss 1019:
1.1       augustss 1020: /*
                   1021:  * Called when a new device has been put in the powered state,
                   1022:  * but not yet in the addressed state.
                   1023:  * Get initial descriptor, set the address, get full descriptor,
                   1024:  * and attach a driver.
                   1025:  */
                   1026: usbd_status
1.78      augustss 1027: usbd_new_device(device_ptr_t parent, usbd_bus_handle bus, int depth,
1.94      augustss 1028:                int speed, int port, struct usbd_port *up)
1.1       augustss 1029: {
1.120     augustss 1030:        usbd_device_handle dev, adev;
1.94      augustss 1031:        struct usbd_device *hub;
1.18      augustss 1032:        usb_device_descriptor_t *dd;
1.107     augustss 1033:        usb_port_status_t ps;
1.53      augustss 1034:        usbd_status err;
1.1       augustss 1035:        int addr;
1.18      augustss 1036:        int i;
1.120     augustss 1037:        int p;
1.1       augustss 1038:
1.94      augustss 1039:        DPRINTF(("usbd_new_device bus=%p port=%d depth=%d speed=%d\n",
                   1040:                 bus, port, depth, speed));
1.1       augustss 1041:        addr = usbd_getnewaddr(bus);
                   1042:        if (addr < 0) {
1.99      augustss 1043:                printf("%s: No free USB addresses, new device ignored.\n",
1.150.6.1  mjf      1044:                       device_xname(bus->usbctl));
1.1       augustss 1045:                return (USBD_NO_ADDR);
                   1046:        }
                   1047:
1.97      tsutsui  1048:        dev = malloc(sizeof *dev, M_USB, M_NOWAIT|M_ZERO);
1.53      augustss 1049:        if (dev == NULL)
1.1       augustss 1050:                return (USBD_NOMEM);
                   1051:
                   1052:        dev->bus = bus;
                   1053:
                   1054:        /* Set up default endpoint handle. */
                   1055:        dev->def_ep.edesc = &dev->def_ep_desc;
                   1056:
                   1057:        /* Set up default endpoint descriptor. */
                   1058:        dev->def_ep_desc.bLength = USB_ENDPOINT_DESCRIPTOR_SIZE;
                   1059:        dev->def_ep_desc.bDescriptorType = UDESC_ENDPOINT;
                   1060:        dev->def_ep_desc.bEndpointAddress = USB_CONTROL_ENDPOINT;
                   1061:        dev->def_ep_desc.bmAttributes = UE_CONTROL;
                   1062:        USETW(dev->def_ep_desc.wMaxPacketSize, USB_MAX_IPACKET);
                   1063:        dev->def_ep_desc.bInterval = 0;
                   1064:
                   1065:        dev->quirks = &usbd_no_quirk;
                   1066:        dev->address = USB_START_ADDR;
1.4       augustss 1067:        dev->ddesc.bMaxPacketSize = 0;
1.1       augustss 1068:        dev->depth = depth;
                   1069:        dev->powersrc = up;
1.94      augustss 1070:        dev->myhub = up->parent;
1.120     augustss 1071:
                   1072:        up->device = dev;
                   1073:
                   1074:        /* Locate port on upstream high speed hub */
                   1075:        for (adev = dev, hub = up->parent;
1.94      augustss 1076:             hub != NULL && hub->speed != USB_SPEED_HIGH;
1.120     augustss 1077:             adev = hub, hub = hub->myhub)
1.94      augustss 1078:                ;
1.120     augustss 1079:        if (hub) {
                   1080:                for (p = 0; p < hub->hub->hubdesc.bNbrPorts; p++) {
                   1081:                        if (hub->hub->ports[p].device == adev) {
                   1082:                                dev->myhsport = &hub->hub->ports[p];
                   1083:                                goto found;
                   1084:                        }
                   1085:                }
                   1086:                panic("usbd_new_device: cannot find HS port\n");
                   1087:        found:
                   1088:                DPRINTFN(1,("usbd_new_device: high speed port %d\n", p));
                   1089:        } else {
                   1090:                dev->myhsport = NULL;
                   1091:        }
1.94      augustss 1092:        dev->speed = speed;
1.22      augustss 1093:        dev->langid = USBD_NOLANG;
1.50      augustss 1094:        dev->cookie.cookie = ++usb_cookie_no;
1.1       augustss 1095:
1.67      soren    1096:        /* Establish the default pipe. */
1.63      augustss 1097:        err = usbd_setup_pipe(dev, 0, &dev->def_ep, USBD_DEFAULT_INTERVAL,
                   1098:                              &dev->default_pipe);
1.53      augustss 1099:        if (err) {
1.18      augustss 1100:                usbd_remove_device(dev, up);
1.53      augustss 1101:                return (err);
1.18      augustss 1102:        }
1.1       augustss 1103:
1.18      augustss 1104:        dd = &dev->ddesc;
1.6       augustss 1105:        /* Try a few times in case the device is slow (i.e. outside specs.) */
1.107     augustss 1106:        for (i = 0; i < 10; i++) {
1.6       augustss 1107:                /* Get the first 8 bytes of the device descriptor. */
1.53      augustss 1108:                err = usbd_get_desc(dev, UDESC_DEVICE, 0, USB_MAX_IPACKET, dd);
                   1109:                if (!err)
1.6       augustss 1110:                        break;
1.23      augustss 1111:                usbd_delay_ms(dev, 200);
1.107     augustss 1112:                if ((i & 3) == 3)
                   1113:                        usbd_reset_port(up->parent, port, &ps);
1.6       augustss 1114:        }
1.53      augustss 1115:        if (err) {
1.14      drochner 1116:                DPRINTFN(-1, ("usbd_new_device: addr=%d, getting first desc "
1.53      augustss 1117:                              "failed\n", addr));
1.18      augustss 1118:                usbd_remove_device(dev, up);
1.53      augustss 1119:                return (err);
1.95      augustss 1120:        }
                   1121:
                   1122:        if (speed == USB_SPEED_HIGH) {
                   1123:                /* Max packet size must be 64 (sec 5.5.3). */
                   1124:                if (dd->bMaxPacketSize != USB_2_MAX_CTRL_PACKET) {
                   1125: #ifdef DIAGNOSTIC
                   1126:                        printf("usbd_new_device: addr=%d bad max packet size\n",
                   1127:                               addr);
                   1128: #endif
                   1129:                        dd->bMaxPacketSize = USB_2_MAX_CTRL_PACKET;
                   1130:                }
1.18      augustss 1131:        }
                   1132:
1.39      augustss 1133:        DPRINTF(("usbd_new_device: adding unit addr=%d, rev=%02x, class=%d, "
1.99      augustss 1134:                 "subclass=%d, protocol=%d, maxpacket=%d, len=%d, speed=%d\n",
1.39      augustss 1135:                 addr,UGETW(dd->bcdUSB), dd->bDeviceClass, dd->bDeviceSubClass,
1.99      augustss 1136:                 dd->bDeviceProtocol, dd->bMaxPacketSize, dd->bLength,
1.94      augustss 1137:                 dev->speed));
1.39      augustss 1138:
1.18      augustss 1139:        if (dd->bDescriptorType != UDESC_DEVICE) {
                   1140:                /* Illegal device descriptor */
                   1141:                DPRINTFN(-1,("usbd_new_device: illegal descriptor %d\n",
                   1142:                             dd->bDescriptorType));
                   1143:                usbd_remove_device(dev, up);
                   1144:                return (USBD_INVAL);
1.1       augustss 1145:        }
                   1146:
1.39      augustss 1147:        if (dd->bLength < USB_DEVICE_DESCRIPTOR_SIZE) {
                   1148:                DPRINTFN(-1,("usbd_new_device: bad length %d\n", dd->bLength));
                   1149:                usbd_remove_device(dev, up);
                   1150:                return (USBD_INVAL);
                   1151:        }
1.4       augustss 1152:
1.18      augustss 1153:        USETW(dev->def_ep_desc.wMaxPacketSize, dd->bMaxPacketSize);
1.1       augustss 1154:
1.62      augustss 1155:        err = usbd_reload_device_desc(dev);
1.53      augustss 1156:        if (err) {
1.14      drochner 1157:                DPRINTFN(-1, ("usbd_new_device: addr=%d, getting full desc "
                   1158:                              "failed\n", addr));
1.18      augustss 1159:                usbd_remove_device(dev, up);
1.53      augustss 1160:                return (err);
1.1       augustss 1161:        }
                   1162:
1.150.6.3  mjf      1163:        /* Set the address */
                   1164:        DPRINTFN(5, ("usbd_new_device: setting device address=%d\n", addr));
                   1165:        err = usbd_set_address(dev, addr);
                   1166:        if (err) {
                   1167:                DPRINTFN(-1, ("usbd_new_device: set address %d failed\n", addr));
                   1168:                err = USBD_SET_ADDR_FAILED;
                   1169:                usbd_remove_device(dev, up);
                   1170:                return err;
                   1171:        }
                   1172:
                   1173:        /* Allow device time to set new address */
                   1174:        usbd_delay_ms(dev, USB_SET_ADDRESS_SETTLE);
                   1175:        dev->address = addr;    /* new device address now */
                   1176:        bus->devices[addr] = dev;
                   1177:
                   1178:        /* Re-establish the default pipe with the new address. */
                   1179:        usbd_kill_pipe(dev->default_pipe);
                   1180:        err = usbd_setup_pipe(dev, 0, &dev->def_ep, USBD_DEFAULT_INTERVAL,
                   1181:            &dev->default_pipe);
                   1182:        if (err) {
                   1183:                DPRINTFN(-1, ("usbd_new_device: setup default pipe failed\n"));
                   1184:                usbd_remove_device(dev, up);
                   1185:                return err;
                   1186:        }
                   1187:
1.1       augustss 1188:        /* Assume 100mA bus powered for now. Changed when configured. */
                   1189:        dev->power = USB_MIN_POWER;
                   1190:        dev->self_powered = 0;
                   1191:
1.99      augustss 1192:        DPRINTF(("usbd_new_device: new dev (addr %d), dev=%p, parent=%p\n",
1.1       augustss 1193:                 addr, dev, parent));
1.99      augustss 1194:
1.65      augustss 1195:        usbd_add_dev_event(USB_EVENT_DEVICE_ATTACH, dev);
1.1       augustss 1196:
1.150.6.2  mjf      1197:        if (port == 0) { /* root hub */
                   1198:                KASSERT(addr == 1);
                   1199:                usbd_attach_roothub(parent, dev);
                   1200:                return (USBD_NORMAL_COMPLETION);
                   1201:        }
                   1202:
1.53      augustss 1203:        err = usbd_probe_and_attach(parent, dev, port, addr);
                   1204:        if (err) {
1.18      augustss 1205:                usbd_remove_device(dev, up);
1.53      augustss 1206:                return (err);
1.18      augustss 1207:        }
1.65      augustss 1208:
1.18      augustss 1209:        return (USBD_NORMAL_COMPLETION);
1.62      augustss 1210: }
                   1211:
                   1212: usbd_status
1.78      augustss 1213: usbd_reload_device_desc(usbd_device_handle dev)
1.62      augustss 1214: {
                   1215:        usbd_status err;
                   1216:
                   1217:        /* Get the full device descriptor. */
                   1218:        err = usbd_get_device_desc(dev, &dev->ddesc);
                   1219:        if (err)
                   1220:                return (err);
                   1221:
                   1222:        /* Figure out what's wrong with this device. */
                   1223:        dev->quirks = usbd_find_quirk(&dev->ddesc);
                   1224:
                   1225:        return (USBD_NORMAL_COMPLETION);
1.18      augustss 1226: }
1.1       augustss 1227:
1.18      augustss 1228: void
1.78      augustss 1229: usbd_remove_device(usbd_device_handle dev, struct usbd_port *up)
1.18      augustss 1230: {
                   1231:        DPRINTF(("usbd_remove_device: %p\n", dev));
1.99      augustss 1232:
1.53      augustss 1233:        if (dev->default_pipe != NULL)
1.18      augustss 1234:                usbd_kill_pipe(dev->default_pipe);
1.120     augustss 1235:        up->device = NULL;
                   1236:        dev->bus->devices[dev->address] = NULL;
1.1       augustss 1237:
                   1238:        free(dev, M_USB);
                   1239: }
                   1240:
                   1241: int
1.78      augustss 1242: usbd_print(void *aux, const char *pnp)
1.1       augustss 1243: {
                   1244:        struct usb_attach_arg *uaa = aux;
                   1245:
                   1246:        DPRINTFN(15, ("usbd_print dev=%p\n", uaa->device));
                   1247:        if (pnp) {
1.134     christos 1248: #define USB_DEVINFO 1024
                   1249:                char *devinfo;
1.1       augustss 1250:                if (!uaa->usegeneric)
                   1251:                        return (QUIET);
1.134     christos 1252:                devinfo = malloc(USB_DEVINFO, M_TEMP, M_WAITOK);
                   1253:                usbd_devinfo(uaa->device, 1, devinfo, USB_DEVINFO);
1.101     thorpej  1254:                aprint_normal("%s, %s", devinfo, pnp);
1.134     christos 1255:                free(devinfo, M_TEMP);
1.1       augustss 1256:        }
1.150.6.2  mjf      1257:        aprint_normal(" port %d", uaa->port);
1.144     drochner 1258: #if 0
                   1259:        /*
                   1260:         * It gets very crowded with these locators on the attach line.
                   1261:         * They are not really needed since they are printed in the clear
                   1262:         * by each driver.
                   1263:         */
                   1264:        if (uaa->vendor != UHUB_UNK_VENDOR)
                   1265:                aprint_normal(" vendor 0x%04x", uaa->vendor);
                   1266:        if (uaa->product != UHUB_UNK_PRODUCT)
                   1267:                aprint_normal(" product 0x%04x", uaa->product);
                   1268:        if (uaa->release != UHUB_UNK_RELEASE)
                   1269:                aprint_normal(" release 0x%04x", uaa->release);
                   1270: #endif
                   1271:        return (UNCONF);
                   1272: }
                   1273:
                   1274: int
                   1275: usbd_ifprint(void *aux, const char *pnp)
                   1276: {
                   1277:        struct usbif_attach_arg *uaa = aux;
                   1278:
                   1279:        DPRINTFN(15, ("usbd_print dev=%p\n", uaa->device));
                   1280:        if (pnp)
                   1281:                return (QUIET);
1.150.6.2  mjf      1282:        aprint_normal(" port %d", uaa->port);
                   1283:        aprint_normal(" configuration %d", uaa->configno);
                   1284:        aprint_normal(" interface %d", uaa->ifaceno);
1.32      augustss 1285: #if 0
1.99      augustss 1286:        /*
1.32      augustss 1287:         * It gets very crowded with these locators on the attach line.
                   1288:         * They are not really needed since they are printed in the clear
                   1289:         * by each driver.
                   1290:         */
                   1291:        if (uaa->vendor != UHUB_UNK_VENDOR)
1.101     thorpej  1292:                aprint_normal(" vendor 0x%04x", uaa->vendor);
1.32      augustss 1293:        if (uaa->product != UHUB_UNK_PRODUCT)
1.101     thorpej  1294:                aprint_normal(" product 0x%04x", uaa->product);
1.32      augustss 1295:        if (uaa->release != UHUB_UNK_RELEASE)
1.101     thorpej  1296:                aprint_normal(" release 0x%04x", uaa->release);
1.32      augustss 1297: #endif
1.1       augustss 1298:        return (UNCONF);
                   1299: }
                   1300:
1.13      augustss 1301: void
1.82      augustss 1302: usbd_fill_deviceinfo(usbd_device_handle dev, struct usb_device_info *di,
                   1303:                     int usedev)
1.13      augustss 1304: {
                   1305:        struct usbd_port *p;
1.150.6.2  mjf      1306:        int i, j, err, s;
1.13      augustss 1307:
1.150.6.1  mjf      1308:        di->udi_bus = device_unit(dev->bus->usbctl);
1.98      christos 1309:        di->udi_addr = dev->address;
                   1310:        di->udi_cookie = dev->cookie;
1.139     pavel    1311:        usbd_devinfo_vp(dev, di->udi_vendor, di->udi_product, usedev, 1);
1.113     itojun   1312:        usbd_printBCD(di->udi_release, sizeof(di->udi_release),
                   1313:            UGETW(dev->ddesc.bcdDevice));
1.123     augustss 1314:        di->udi_serial[0] = 0;
                   1315:        if (usedev)
                   1316:                (void)usbd_get_string(dev, dev->ddesc.iSerialNumber,
                   1317:                                      di->udi_serial);
1.98      christos 1318:        di->udi_vendorNo = UGETW(dev->ddesc.idVendor);
                   1319:        di->udi_productNo = UGETW(dev->ddesc.idProduct);
                   1320:        di->udi_releaseNo = UGETW(dev->ddesc.bcdDevice);
                   1321:        di->udi_class = dev->ddesc.bDeviceClass;
                   1322:        di->udi_subclass = dev->ddesc.bDeviceSubClass;
                   1323:        di->udi_protocol = dev->ddesc.bDeviceProtocol;
                   1324:        di->udi_config = dev->config;
                   1325:        di->udi_power = dev->self_powered ? 0 : dev->power;
                   1326:        di->udi_speed = dev->speed;
1.65      augustss 1327:
1.150.6.2  mjf      1328:        if (dev->subdevlen > 0) {
                   1329:                for (i = 0, j = 0; i < dev->subdevlen &&
                   1330:                             j < USB_MAX_DEVNAMES; i++) {
                   1331:                        if (!dev->subdevs[i])
                   1332:                                continue;
                   1333:                        strncpy(di->udi_devnames[j], USBDEVPTRNAME(dev->subdevs[i]),
1.65      augustss 1334:                                USB_MAX_DEVNAMELEN);
1.150.6.2  mjf      1335:                        di->udi_devnames[j][USB_MAX_DEVNAMELEN-1] = '\0';
                   1336:                        j++;
1.65      augustss 1337:                 }
                   1338:         } else {
1.150.6.2  mjf      1339:                 j = 0;
1.65      augustss 1340:         }
1.150.6.2  mjf      1341:         for (/* j is set */; j < USB_MAX_DEVNAMES; j++)
                   1342:                 di->udi_devnames[j][0] = 0;                 /* empty */
1.65      augustss 1343:
1.13      augustss 1344:        if (dev->hub) {
1.99      augustss 1345:                for (i = 0;
1.98      christos 1346:                     i < sizeof(di->udi_ports) / sizeof(di->udi_ports[0]) &&
1.13      augustss 1347:                             i < dev->hub->hubdesc.bNbrPorts;
                   1348:                     i++) {
                   1349:                        p = &dev->hub->ports[i];
                   1350:                        if (p->device)
1.56      augustss 1351:                                err = p->device->address;
1.13      augustss 1352:                        else {
                   1353:                                s = UGETW(p->status.wPortStatus);
                   1354:                                if (s & UPS_PORT_ENABLED)
1.56      augustss 1355:                                        err = USB_PORT_ENABLED;
1.13      augustss 1356:                                else if (s & UPS_SUSPEND)
1.56      augustss 1357:                                        err = USB_PORT_SUSPENDED;
1.13      augustss 1358:                                else if (s & UPS_PORT_POWER)
1.56      augustss 1359:                                        err = USB_PORT_POWERED;
1.13      augustss 1360:                                else
1.56      augustss 1361:                                        err = USB_PORT_DISABLED;
1.13      augustss 1362:                        }
1.98      christos 1363:                        di->udi_ports[i] = err;
1.13      augustss 1364:                }
1.98      christos 1365:                di->udi_nports = dev->hub->hubdesc.bNbrPorts;
1.13      augustss 1366:        } else
1.98      christos 1367:                di->udi_nports = 0;
1.34      augustss 1368: }
                   1369:
1.139     pavel    1370: #ifdef COMPAT_30
                   1371: void
                   1372: usbd_fill_deviceinfo_old(usbd_device_handle dev, struct usb_device_info_old *di,
                   1373:                          int usedev)
                   1374: {
                   1375:        struct usbd_port *p;
1.150.6.2  mjf      1376:        int i, j, err, s;
1.139     pavel    1377:
1.150.6.1  mjf      1378:        di->udi_bus = device_unit(dev->bus->usbctl);
1.139     pavel    1379:        di->udi_addr = dev->address;
                   1380:        di->udi_cookie = dev->cookie;
                   1381:        usbd_devinfo_vp(dev, di->udi_vendor, di->udi_product, usedev, 0);
                   1382:        usbd_printBCD(di->udi_release, sizeof(di->udi_release),
                   1383:            UGETW(dev->ddesc.bcdDevice));
                   1384:        di->udi_vendorNo = UGETW(dev->ddesc.idVendor);
                   1385:        di->udi_productNo = UGETW(dev->ddesc.idProduct);
                   1386:        di->udi_releaseNo = UGETW(dev->ddesc.bcdDevice);
                   1387:        di->udi_class = dev->ddesc.bDeviceClass;
                   1388:        di->udi_subclass = dev->ddesc.bDeviceSubClass;
                   1389:        di->udi_protocol = dev->ddesc.bDeviceProtocol;
                   1390:        di->udi_config = dev->config;
                   1391:        di->udi_power = dev->self_powered ? 0 : dev->power;
                   1392:        di->udi_speed = dev->speed;
                   1393:
1.150.6.2  mjf      1394:        if (dev->subdevlen > 0) {
                   1395:                for (i = 0, j = 0; i < dev->subdevlen &&
                   1396:                             j < USB_MAX_DEVNAMES; i++) {
                   1397:                        if (!dev->subdevs[i])
                   1398:                                continue;
                   1399:                        strncpy(di->udi_devnames[j], USBDEVPTRNAME(dev->subdevs[i]),
1.139     pavel    1400:                                USB_MAX_DEVNAMELEN);
1.150.6.2  mjf      1401:                        di->udi_devnames[j][USB_MAX_DEVNAMELEN-1] = '\0';
                   1402:                        j++;
1.139     pavel    1403:                }
                   1404:        } else {
1.150.6.2  mjf      1405:                j = 0;
1.139     pavel    1406:        }
1.150.6.2  mjf      1407:        for (/* j is set */; j < USB_MAX_DEVNAMES; j++)
                   1408:                di->udi_devnames[j][0] = 0;              /* empty */
1.139     pavel    1409:
                   1410:        if (dev->hub) {
                   1411:                for (i = 0;
                   1412:                     i < sizeof(di->udi_ports) / sizeof(di->udi_ports[0]) &&
                   1413:                             i < dev->hub->hubdesc.bNbrPorts;
                   1414:                     i++) {
                   1415:                        p = &dev->hub->ports[i];
                   1416:                        if (p->device)
                   1417:                                err = p->device->address;
                   1418:                        else {
                   1419:                                s = UGETW(p->status.wPortStatus);
                   1420:                                if (s & UPS_PORT_ENABLED)
                   1421:                                        err = USB_PORT_ENABLED;
                   1422:                                else if (s & UPS_SUSPEND)
                   1423:                                        err = USB_PORT_SUSPENDED;
                   1424:                                else if (s & UPS_PORT_POWER)
                   1425:                                        err = USB_PORT_POWERED;
                   1426:                                else
                   1427:                                        err = USB_PORT_DISABLED;
                   1428:                        }
                   1429:                        di->udi_ports[i] = err;
                   1430:                }
                   1431:                di->udi_nports = dev->hub->hubdesc.bNbrPorts;
                   1432:        } else
                   1433:                di->udi_nports = 0;
                   1434: }
                   1435: #endif
                   1436:
                   1437:
1.34      augustss 1438: void
1.78      augustss 1439: usb_free_device(usbd_device_handle dev)
1.34      augustss 1440: {
                   1441:        int ifcidx, nifc;
                   1442:
1.53      augustss 1443:        if (dev->default_pipe != NULL)
1.34      augustss 1444:                usbd_kill_pipe(dev->default_pipe);
1.53      augustss 1445:        if (dev->ifaces != NULL) {
1.34      augustss 1446:                nifc = dev->cdesc->bNumInterface;
                   1447:                for (ifcidx = 0; ifcidx < nifc; ifcidx++)
                   1448:                        usbd_free_iface_data(dev, ifcidx);
                   1449:                free(dev->ifaces, M_USB);
                   1450:        }
1.53      augustss 1451:        if (dev->cdesc != NULL)
1.34      augustss 1452:                free(dev->cdesc, M_USB);
1.150.6.2  mjf      1453:        if (dev->subdevlen > 0) {
1.34      augustss 1454:                free(dev->subdevs, M_USB);
1.150.6.2  mjf      1455:                dev->subdevlen = 0;
                   1456:        }
1.34      augustss 1457:        free(dev, M_USB);
1.1       augustss 1458: }
1.47      augustss 1459:
                   1460: /*
                   1461:  * The general mechanism for detaching drivers works as follows: Each
                   1462:  * driver is responsible for maintaining a reference count on the
                   1463:  * number of outstanding references to its softc (e.g.  from
                   1464:  * processing hanging in a read or write).  The detach method of the
                   1465:  * driver decrements this counter and flags in the softc that the
                   1466:  * driver is dying and then wakes any sleepers.  It then sleeps on the
                   1467:  * softc.  Each place that can sleep must maintain the reference
                   1468:  * count.  When the reference count drops to -1 (0 is the normal value
                   1469:  * of the reference count) the a wakeup on the softc is performed
                   1470:  * signaling to the detach waiter that all references are gone.
                   1471:  */
                   1472:
                   1473: /*
                   1474:  * Called from process context when we discover that a port has
                   1475:  * been disconnected.
                   1476:  */
                   1477: void
1.78      augustss 1478: usb_disconnect_port(struct usbd_port *up, device_ptr_t parent)
1.47      augustss 1479: {
                   1480:        usbd_device_handle dev = up->device;
1.150.6.2  mjf      1481:        const char *hubname = USBDEVPTRNAME(parent);
1.47      augustss 1482:        int i;
                   1483:
1.99      augustss 1484:        DPRINTFN(3,("uhub_disconnect: up=%p dev=%p port=%d\n",
1.47      augustss 1485:                    up, dev, up->portno));
1.48      augustss 1486:
                   1487: #ifdef DIAGNOSTIC
1.57      augustss 1488:        if (dev == NULL) {
1.48      augustss 1489:                printf("usb_disconnect_port: no device\n");
                   1490:                return;
                   1491:        }
                   1492: #endif
1.47      augustss 1493:
1.150.6.2  mjf      1494:        if (dev->subdevlen > 0) {
1.57      augustss 1495:                DPRINTFN(3,("usb_disconnect_port: disconnect subdevs\n"));
1.150.6.2  mjf      1496:                for (i = 0; i < dev->subdevlen; i++) {
                   1497:                        if (!dev->subdevs[i])
                   1498:                                continue;
1.99      augustss 1499:                        printf("%s: at %s", USBDEVPTRNAME(dev->subdevs[i]),
1.51      augustss 1500:                               hubname);
                   1501:                        if (up->portno != 0)
                   1502:                                printf(" port %d", up->portno);
                   1503:                        printf(" (addr %d) disconnected\n", dev->address);
1.47      augustss 1504:                        config_detach(dev->subdevs[i], DETACH_FORCE);
                   1505:                }
1.150.6.4! mjf      1506:                KASSERT(!dev->nifaces_claimed);
1.47      augustss 1507:        }
                   1508:
1.65      augustss 1509:        usbd_add_dev_event(USB_EVENT_DEVICE_DETACH, dev);
1.57      augustss 1510:        dev->bus->devices[dev->address] = NULL;
                   1511:        up->device = NULL;
1.47      augustss 1512:        usb_free_device(dev);
                   1513: }

CVSweb <webmaster@jp.NetBSD.org>