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

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

CVSweb <webmaster@jp.NetBSD.org>