[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.73

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

CVSweb <webmaster@jp.NetBSD.org>