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

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

CVSweb <webmaster@jp.NetBSD.org>