[BACK]Return to usbdi.c CVS log [TXT][DIR] Up to [local] / sys / dev / usb

Annotation of sys/dev/usb/usbdi.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: usbdi.c,v 1.33 2007/06/18 11:37:04 mbalmer Exp $ */
                      2: /*     $NetBSD: usbdi.c,v 1.103 2002/09/27 15:37:38 provos Exp $       */
                      3: /*     $FreeBSD: src/sys/dev/usb/usbdi.c,v 1.28 1999/11/17 22:33:49 n_hibma Exp $      */
                      4:
                      5: /*
                      6:  * Copyright (c) 1998 The NetBSD Foundation, Inc.
                      7:  * All rights reserved.
                      8:  *
                      9:  * This code is derived from software contributed to The NetBSD Foundation
                     10:  * by Lennart Augustsson (lennart@augustsson.net) at
                     11:  * Carlstedt Research & Technology.
                     12:  *
                     13:  * Redistribution and use in source and binary forms, with or without
                     14:  * modification, are permitted provided that the following conditions
                     15:  * are met:
                     16:  * 1. Redistributions of source code must retain the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer.
                     18:  * 2. Redistributions in binary form must reproduce the above copyright
                     19:  *    notice, this list of conditions and the following disclaimer in the
                     20:  *    documentation and/or other materials provided with the distribution.
                     21:  * 3. All advertising materials mentioning features or use of this software
                     22:  *    must display the following acknowledgement:
                     23:  *        This product includes software developed by the NetBSD
                     24:  *        Foundation, Inc. and its contributors.
                     25:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     26:  *    contributors may be used to endorse or promote products derived
                     27:  *    from this software without specific prior written permission.
                     28:  *
                     29:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     30:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     31:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     32:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     33:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     34:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     35:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     36:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     37:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     38:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     39:  * POSSIBILITY OF SUCH DAMAGE.
                     40:  */
                     41:
                     42: #include <sys/param.h>
                     43: #include <sys/systm.h>
                     44: #include <sys/kernel.h>
                     45: #include <sys/device.h>
                     46: #include <sys/malloc.h>
                     47: #include <sys/proc.h>
                     48:
                     49: #include <machine/bus.h>
                     50:
                     51: #include <dev/usb/usb.h>
                     52: #include <dev/usb/usbdi.h>
                     53: #include <dev/usb/usbdi_util.h>
                     54: #include <dev/usb/usbdivar.h>
                     55: #include <dev/usb/usb_mem.h>
                     56:
                     57: #ifdef USB_DEBUG
                     58: #define DPRINTF(x)     do { if (usbdebug) printf x; } while (0)
                     59: #define DPRINTFN(n,x)  do { if (usbdebug>(n)) printf x; } while (0)
                     60: extern int usbdebug;
                     61: #else
                     62: #define DPRINTF(x)
                     63: #define DPRINTFN(n,x)
                     64: #endif
                     65:
                     66: usbd_status usbd_ar_pipe(usbd_pipe_handle pipe);
                     67: void usbd_do_request_async_cb(usbd_xfer_handle, usbd_private_handle,
                     68:     usbd_status);
                     69: void usbd_start_next(usbd_pipe_handle pipe);
                     70: usbd_status usbd_open_pipe_ival(usbd_interface_handle, u_int8_t, u_int8_t,
                     71:     usbd_pipe_handle *, int);
                     72:
                     73: int usbd_nbuses = 0;
                     74:
                     75: void
                     76: usbd_init(void)
                     77: {
                     78:        usbd_nbuses++;
                     79: }
                     80:
                     81: void
                     82: usbd_finish(void)
                     83: {
                     84:        --usbd_nbuses;
                     85: }
                     86:
                     87: static __inline int
                     88: usbd_xfer_isread(usbd_xfer_handle xfer)
                     89: {
                     90:        if (xfer->rqflags & URQ_REQUEST)
                     91:                return (xfer->request.bmRequestType & UT_READ);
                     92:        else
                     93:                return (xfer->pipe->endpoint->edesc->bEndpointAddress &
                     94:                    UE_DIR_IN);
                     95: }
                     96:
                     97: #ifdef USB_DEBUG
                     98: void
                     99: usbd_dump_iface(struct usbd_interface *iface)
                    100: {
                    101:        printf("usbd_dump_iface: iface=%p\n", iface);
                    102:        if (iface == NULL)
                    103:                return;
                    104:        printf(" device=%p idesc=%p index=%d altindex=%d priv=%p\n",
                    105:            iface->device, iface->idesc, iface->index, iface->altindex,
                    106:            iface->priv);
                    107: }
                    108:
                    109: void
                    110: usbd_dump_device(struct usbd_device *dev)
                    111: {
                    112:        printf("usbd_dump_device: dev=%p\n", dev);
                    113:        if (dev == NULL)
                    114:                return;
                    115:        printf(" bus=%p default_pipe=%p\n", dev->bus, dev->default_pipe);
                    116:        printf(" address=%d config=%d depth=%d speed=%d self_powered=%d "
                    117:            "power=%d langid=%d\n", dev->address, dev->config, dev->depth,
                    118:            dev->speed, dev->self_powered, dev->power, dev->langid);
                    119: }
                    120:
                    121: void
                    122: usbd_dump_endpoint(struct usbd_endpoint *endp)
                    123: {
                    124:        printf("usbd_dump_endpoint: endp=%p\n", endp);
                    125:        if (endp == NULL)
                    126:                return;
                    127:        printf(" edesc=%p refcnt=%d\n", endp->edesc, endp->refcnt);
                    128:        if (endp->edesc)
                    129:                printf(" bEndpointAddress=0x%02x\n",
                    130:                    endp->edesc->bEndpointAddress);
                    131: }
                    132:
                    133: void
                    134: usbd_dump_queue(usbd_pipe_handle pipe)
                    135: {
                    136:        usbd_xfer_handle xfer;
                    137:
                    138:        printf("usbd_dump_queue: pipe=%p\n", pipe);
                    139:        SIMPLEQ_FOREACH(xfer, &pipe->queue, next) {
                    140:                printf("  xfer=%p\n", xfer);
                    141:        }
                    142: }
                    143:
                    144: void
                    145: usbd_dump_pipe(usbd_pipe_handle pipe)
                    146: {
                    147:        printf("usbd_dump_pipe: pipe=%p\n", pipe);
                    148:        if (pipe == NULL)
                    149:                return;
                    150:        usbd_dump_iface(pipe->iface);
                    151:        usbd_dump_device(pipe->device);
                    152:        usbd_dump_endpoint(pipe->endpoint);
                    153:        printf(" (usbd_dump_pipe:)\n refcnt=%d running=%d aborting=%d\n",
                    154:            pipe->refcnt, pipe->running, pipe->aborting);
                    155:        printf(" intrxfer=%p, repeat=%d, interval=%d\n", pipe->intrxfer,
                    156:            pipe->repeat, pipe->interval);
                    157: }
                    158: #endif
                    159:
                    160: usbd_status
                    161: usbd_open_pipe(usbd_interface_handle iface, u_int8_t address, u_int8_t flags,
                    162:     usbd_pipe_handle *pipe)
                    163: {
                    164:        return (usbd_open_pipe_ival(iface, address, flags, pipe,
                    165:            USBD_DEFAULT_INTERVAL));
                    166: }
                    167:
                    168: usbd_status
                    169: usbd_open_pipe_ival(usbd_interface_handle iface, u_int8_t address,
                    170:     u_int8_t flags, usbd_pipe_handle *pipe, int ival)
                    171: {
                    172:        usbd_pipe_handle p;
                    173:        struct usbd_endpoint *ep;
                    174:        usbd_status err;
                    175:        int i;
                    176:
                    177:        DPRINTFN(3,("usbd_open_pipe: iface=%p address=0x%x flags=0x%x\n",
                    178:            iface, address, flags));
                    179:
                    180:        for (i = 0; i < iface->idesc->bNumEndpoints; i++) {
                    181:                ep = &iface->endpoints[i];
                    182:                if (ep->edesc == NULL)
                    183:                        return (USBD_IOERROR);
                    184:                if (ep->edesc->bEndpointAddress == address)
                    185:                        goto found;
                    186:        }
                    187:        return (USBD_BAD_ADDRESS);
                    188:  found:
                    189:        if ((flags & USBD_EXCLUSIVE_USE) && ep->refcnt != 0)
                    190:                return (USBD_IN_USE);
                    191:        err = usbd_setup_pipe(iface->device, iface, ep, ival, &p);
                    192:        if (err)
                    193:                return (err);
                    194:        LIST_INSERT_HEAD(&iface->pipes, p, next);
                    195:        *pipe = p;
                    196:        return (USBD_NORMAL_COMPLETION);
                    197: }
                    198:
                    199: usbd_status
                    200: usbd_open_pipe_intr(usbd_interface_handle iface, u_int8_t address,
                    201:     u_int8_t flags, usbd_pipe_handle *pipe, usbd_private_handle priv,
                    202:     void *buffer, u_int32_t len, usbd_callback cb, int ival)
                    203: {
                    204:        usbd_status err;
                    205:        usbd_xfer_handle xfer;
                    206:        usbd_pipe_handle ipipe;
                    207:
                    208:        DPRINTFN(3,("usbd_open_pipe_intr: address=0x%x flags=0x%x len=%d\n",
                    209:            address, flags, len));
                    210:
                    211:        err = usbd_open_pipe_ival(iface, address, USBD_EXCLUSIVE_USE, &ipipe,
                    212:            ival);
                    213:        if (err)
                    214:                return (err);
                    215:        xfer = usbd_alloc_xfer(iface->device);
                    216:        if (xfer == NULL) {
                    217:                err = USBD_NOMEM;
                    218:                goto bad1;
                    219:        }
                    220:        usbd_setup_xfer(xfer, ipipe, priv, buffer, len, flags,
                    221:            USBD_NO_TIMEOUT, cb);
                    222:        ipipe->intrxfer = xfer;
                    223:        ipipe->repeat = 1;
                    224:        err = usbd_transfer(xfer);
                    225:        *pipe = ipipe;
                    226:        if (err != USBD_IN_PROGRESS)
                    227:                goto bad2;
                    228:        return (USBD_NORMAL_COMPLETION);
                    229:
                    230:  bad2:
                    231:        ipipe->intrxfer = NULL;
                    232:        ipipe->repeat = 0;
                    233:        usbd_free_xfer(xfer);
                    234:  bad1:
                    235:        usbd_close_pipe(ipipe);
                    236:        return (err);
                    237: }
                    238:
                    239: usbd_status
                    240: usbd_close_pipe(usbd_pipe_handle pipe)
                    241: {
                    242: #ifdef DIAGNOSTIC
                    243:        if (pipe == NULL) {
                    244:                printf("usbd_close_pipe: pipe==NULL\n");
                    245:                return (USBD_NORMAL_COMPLETION);
                    246:        }
                    247: #endif
                    248:
                    249:        if (--pipe->refcnt != 0)
                    250:                return (USBD_NORMAL_COMPLETION);
                    251:        if (! SIMPLEQ_EMPTY(&pipe->queue))
                    252:                return (USBD_PENDING_REQUESTS);
                    253:        LIST_REMOVE(pipe, next);
                    254:        pipe->endpoint->refcnt--;
                    255:        pipe->methods->close(pipe);
                    256:        if (pipe->intrxfer != NULL)
                    257:                usbd_free_xfer(pipe->intrxfer);
                    258:        free(pipe, M_USB);
                    259:        return (USBD_NORMAL_COMPLETION);
                    260: }
                    261:
                    262: usbd_status
                    263: usbd_transfer(usbd_xfer_handle xfer)
                    264: {
                    265:        usbd_pipe_handle pipe = xfer->pipe;
                    266:        usb_dma_t *dmap = &xfer->dmabuf;
                    267:        usbd_status err;
                    268:        u_int size;
                    269:        int s;
                    270:
                    271:        DPRINTFN(5,("usbd_transfer: xfer=%p, flags=%d, pipe=%p, running=%d\n",
                    272:            xfer, xfer->flags, pipe, pipe->running));
                    273: #ifdef USB_DEBUG
                    274:        if (usbdebug > 5)
                    275:                usbd_dump_queue(pipe);
                    276: #endif
                    277:        xfer->done = 0;
                    278:
                    279:        if (pipe->aborting)
                    280:                return (USBD_CANCELLED);
                    281:
                    282:        size = xfer->length;
                    283:        /* If there is no buffer, allocate one. */
                    284:        if (!(xfer->rqflags & URQ_DEV_DMABUF) && size != 0) {
                    285:                struct usbd_bus *bus = pipe->device->bus;
                    286:
                    287: #ifdef DIAGNOSTIC
                    288:                if (xfer->rqflags & URQ_AUTO_DMABUF)
                    289:                        printf("usbd_transfer: has old buffer!\n");
                    290: #endif
                    291:                err = bus->methods->allocm(bus, dmap, size);
                    292:                if (err)
                    293:                        return (err);
                    294:                xfer->rqflags |= URQ_AUTO_DMABUF;
                    295:        }
                    296:
                    297:        /* Copy data if going out. */
                    298:        if (!(xfer->flags & USBD_NO_COPY) && size != 0 &&
                    299:            !usbd_xfer_isread(xfer))
                    300:                memcpy(KERNADDR(dmap, 0), xfer->buffer, size);
                    301:
                    302:        err = pipe->methods->transfer(xfer);
                    303:
                    304:        if (err != USBD_IN_PROGRESS && err) {
                    305:                /* The transfer has not been queued, so free buffer. */
                    306:                if (xfer->rqflags & URQ_AUTO_DMABUF) {
                    307:                        struct usbd_bus *bus = pipe->device->bus;
                    308:
                    309:                        bus->methods->freem(bus, &xfer->dmabuf);
                    310:                        xfer->rqflags &= ~URQ_AUTO_DMABUF;
                    311:                }
                    312:        }
                    313:
                    314:        if (!(xfer->flags & USBD_SYNCHRONOUS))
                    315:                return (err);
                    316:
                    317:        /* Sync transfer, wait for completion. */
                    318:        if (err != USBD_IN_PROGRESS)
                    319:                return (err);
                    320:        s = splusb();
                    321:        while (!xfer->done) {
                    322:                if (pipe->device->bus->use_polling)
                    323:                        panic("usbd_transfer: not done");
                    324:                tsleep(xfer, PRIBIO, "usbsyn", 0);
                    325:        }
                    326:        splx(s);
                    327:        return (xfer->status);
                    328: }
                    329:
                    330: /* Like usbd_transfer(), but waits for completion. */
                    331: usbd_status
                    332: usbd_sync_transfer(usbd_xfer_handle xfer)
                    333: {
                    334:        xfer->flags |= USBD_SYNCHRONOUS;
                    335:        return (usbd_transfer(xfer));
                    336: }
                    337:
                    338: void *
                    339: usbd_alloc_buffer(usbd_xfer_handle xfer, u_int32_t size)
                    340: {
                    341:        struct usbd_bus *bus = xfer->device->bus;
                    342:        usbd_status err;
                    343:
                    344: #ifdef DIAGNOSTIC
                    345:        if (xfer->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF))
                    346:                printf("usbd_alloc_buffer: xfer already has a buffer\n");
                    347: #endif
                    348:        err = bus->methods->allocm(bus, &xfer->dmabuf, size);
                    349:        if (err)
                    350:                return (NULL);
                    351:        xfer->rqflags |= URQ_DEV_DMABUF;
                    352:        return (KERNADDR(&xfer->dmabuf, 0));
                    353: }
                    354:
                    355: void
                    356: usbd_free_buffer(usbd_xfer_handle xfer)
                    357: {
                    358: #ifdef DIAGNOSTIC
                    359:        if (!(xfer->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF))) {
                    360:                printf("usbd_free_buffer: no buffer\n");
                    361:                return;
                    362:        }
                    363: #endif
                    364:        xfer->rqflags &= ~(URQ_DEV_DMABUF | URQ_AUTO_DMABUF);
                    365:        xfer->device->bus->methods->freem(xfer->device->bus, &xfer->dmabuf);
                    366: }
                    367:
                    368: void *
                    369: usbd_get_buffer(usbd_xfer_handle xfer)
                    370: {
                    371:        if (!(xfer->rqflags & URQ_DEV_DMABUF))
                    372:                return (0);
                    373:        return (KERNADDR(&xfer->dmabuf, 0));
                    374: }
                    375:
                    376: usbd_xfer_handle
                    377: usbd_alloc_xfer(usbd_device_handle dev)
                    378: {
                    379:        usbd_xfer_handle xfer;
                    380:
                    381:        xfer = dev->bus->methods->allocx(dev->bus);
                    382:        if (xfer == NULL)
                    383:                return (NULL);
                    384:        xfer->device = dev;
                    385:        timeout_set(&xfer->timeout_handle, NULL, NULL);
                    386:        DPRINTFN(5,("usbd_alloc_xfer() = %p\n", xfer));
                    387:        return (xfer);
                    388: }
                    389:
                    390: usbd_status
                    391: usbd_free_xfer(usbd_xfer_handle xfer)
                    392: {
                    393:        DPRINTFN(5,("usbd_free_xfer: %p\n", xfer));
                    394:        if (xfer->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF))
                    395:                usbd_free_buffer(xfer);
                    396:        xfer->device->bus->methods->freex(xfer->device->bus, xfer);
                    397:        return (USBD_NORMAL_COMPLETION);
                    398: }
                    399:
                    400: void
                    401: usbd_setup_xfer(usbd_xfer_handle xfer, usbd_pipe_handle pipe,
                    402:     usbd_private_handle priv, void *buffer, u_int32_t length, u_int16_t flags,
                    403:     u_int32_t timeout, usbd_callback callback)
                    404: {
                    405:        xfer->pipe = pipe;
                    406:        xfer->priv = priv;
                    407:        xfer->buffer = buffer;
                    408:        xfer->length = length;
                    409:        xfer->actlen = 0;
                    410:        xfer->flags = flags;
                    411:        xfer->timeout = timeout;
                    412:        xfer->status = USBD_NOT_STARTED;
                    413:        xfer->callback = callback;
                    414:        xfer->rqflags &= ~URQ_REQUEST;
                    415:        xfer->nframes = 0;
                    416: }
                    417:
                    418: void
                    419: usbd_setup_default_xfer(usbd_xfer_handle xfer, usbd_device_handle dev,
                    420:     usbd_private_handle priv, u_int32_t timeout, usb_device_request_t *req,
                    421:     void *buffer, u_int32_t length, u_int16_t flags, usbd_callback callback)
                    422: {
                    423:        xfer->pipe = dev->default_pipe;
                    424:        xfer->priv = priv;
                    425:        xfer->buffer = buffer;
                    426:        xfer->length = length;
                    427:        xfer->actlen = 0;
                    428:        xfer->flags = flags;
                    429:        xfer->timeout = timeout;
                    430:        xfer->status = USBD_NOT_STARTED;
                    431:        xfer->callback = callback;
                    432:        xfer->request = *req;
                    433:        xfer->rqflags |= URQ_REQUEST;
                    434:        xfer->nframes = 0;
                    435: }
                    436:
                    437: void
                    438: usbd_setup_isoc_xfer(usbd_xfer_handle xfer, usbd_pipe_handle pipe,
                    439:     usbd_private_handle priv, u_int16_t *frlengths, u_int32_t nframes,
                    440:     u_int16_t flags, usbd_callback callback)
                    441: {
                    442:        xfer->pipe = pipe;
                    443:        xfer->priv = priv;
                    444:        xfer->buffer = 0;
                    445:        xfer->length = 0;
                    446:        xfer->actlen = 0;
                    447:        xfer->flags = flags;
                    448:        xfer->timeout = USBD_NO_TIMEOUT;
                    449:        xfer->status = USBD_NOT_STARTED;
                    450:        xfer->callback = callback;
                    451:        xfer->rqflags &= ~URQ_REQUEST;
                    452:        xfer->frlengths = frlengths;
                    453:        xfer->nframes = nframes;
                    454: }
                    455:
                    456: void
                    457: usbd_get_xfer_status(usbd_xfer_handle xfer, usbd_private_handle *priv,
                    458:     void **buffer, u_int32_t *count, usbd_status *status)
                    459: {
                    460:        if (priv != NULL)
                    461:                *priv = xfer->priv;
                    462:        if (buffer != NULL)
                    463:                *buffer = xfer->buffer;
                    464:        if (count != NULL)
                    465:                *count = xfer->actlen;
                    466:        if (status != NULL)
                    467:                *status = xfer->status;
                    468: }
                    469:
                    470: usb_config_descriptor_t *
                    471: usbd_get_config_descriptor(usbd_device_handle dev)
                    472: {
                    473: #ifdef DIAGNOSTIC
                    474:        if (dev == NULL) {
                    475:                printf("usbd_get_config_descriptor: dev == NULL\n");
                    476:                return (NULL);
                    477:        }
                    478: #endif
                    479:        return (dev->cdesc);
                    480: }
                    481:
                    482: usb_interface_descriptor_t *
                    483: usbd_get_interface_descriptor(usbd_interface_handle iface)
                    484: {
                    485: #ifdef DIAGNOSTIC
                    486:        if (iface == NULL) {
                    487:                printf("usbd_get_interface_descriptor: dev == NULL\n");
                    488:                return (NULL);
                    489:        }
                    490: #endif
                    491:        return (iface->idesc);
                    492: }
                    493:
                    494: usb_device_descriptor_t *
                    495: usbd_get_device_descriptor(usbd_device_handle dev)
                    496: {
                    497:        return (&dev->ddesc);
                    498: }
                    499:
                    500: usb_endpoint_descriptor_t *
                    501: usbd_interface2endpoint_descriptor(usbd_interface_handle iface, u_int8_t index)
                    502: {
                    503:        if (index >= iface->idesc->bNumEndpoints)
                    504:                return (0);
                    505:        return (iface->endpoints[index].edesc);
                    506: }
                    507:
                    508: usbd_status
                    509: usbd_abort_pipe(usbd_pipe_handle pipe)
                    510: {
                    511:        usbd_status err;
                    512:        int s;
                    513:
                    514: #ifdef DIAGNOSTIC
                    515:        if (pipe == NULL) {
                    516:                printf("usbd_abort_pipe: pipe==NULL\n");
                    517:                return (USBD_NORMAL_COMPLETION);
                    518:        }
                    519: #endif
                    520:        s = splusb();
                    521:        err = usbd_ar_pipe(pipe);
                    522:        splx(s);
                    523:        return (err);
                    524: }
                    525:
                    526: usbd_status
                    527: usbd_clear_endpoint_stall(usbd_pipe_handle pipe)
                    528: {
                    529:        usbd_device_handle dev = pipe->device;
                    530:        usb_device_request_t req;
                    531:        usbd_status err;
                    532:
                    533:        DPRINTFN(8, ("usbd_clear_endpoint_stall\n"));
                    534:
                    535:        /*
                    536:         * Clearing en endpoint stall resets the endpoint toggle, so
                    537:         * do the same to the HC toggle.
                    538:         */
                    539:        pipe->methods->cleartoggle(pipe);
                    540:
                    541:        req.bmRequestType = UT_WRITE_ENDPOINT;
                    542:        req.bRequest = UR_CLEAR_FEATURE;
                    543:        USETW(req.wValue, UF_ENDPOINT_HALT);
                    544:        USETW(req.wIndex, pipe->endpoint->edesc->bEndpointAddress);
                    545:        USETW(req.wLength, 0);
                    546:        err = usbd_do_request(dev, &req, 0);
                    547: #if 0
                    548: XXX should we do this?
                    549:        if (!err) {
                    550:                pipe->state = USBD_PIPE_ACTIVE;
                    551:                /* XXX activate pipe */
                    552:        }
                    553: #endif
                    554:        return (err);
                    555: }
                    556:
                    557: usbd_status
                    558: usbd_clear_endpoint_stall_async(usbd_pipe_handle pipe)
                    559: {
                    560:        usbd_device_handle dev = pipe->device;
                    561:        usb_device_request_t req;
                    562:        usbd_status err;
                    563:
                    564:        pipe->methods->cleartoggle(pipe);
                    565:
                    566:        req.bmRequestType = UT_WRITE_ENDPOINT;
                    567:        req.bRequest = UR_CLEAR_FEATURE;
                    568:        USETW(req.wValue, UF_ENDPOINT_HALT);
                    569:        USETW(req.wIndex, pipe->endpoint->edesc->bEndpointAddress);
                    570:        USETW(req.wLength, 0);
                    571:        err = usbd_do_request_async(dev, &req, 0);
                    572:        return (err);
                    573: }
                    574:
                    575: void
                    576: usbd_clear_endpoint_toggle(usbd_pipe_handle pipe)
                    577: {
                    578:        pipe->methods->cleartoggle(pipe);
                    579: }
                    580:
                    581: usbd_status
                    582: usbd_endpoint_count(usbd_interface_handle iface, u_int8_t *count)
                    583: {
                    584: #ifdef DIAGNOSTIC
                    585:        if (iface == NULL || iface->idesc == NULL) {
                    586:                printf("usbd_endpoint_count: NULL pointer\n");
                    587:                return (USBD_INVAL);
                    588:        }
                    589: #endif
                    590:        *count = iface->idesc->bNumEndpoints;
                    591:        return (USBD_NORMAL_COMPLETION);
                    592: }
                    593:
                    594: usbd_status
                    595: usbd_interface_count(usbd_device_handle dev, u_int8_t *count)
                    596: {
                    597:        if (dev->cdesc == NULL)
                    598:                return (USBD_NOT_CONFIGURED);
                    599:        *count = dev->cdesc->bNumInterface;
                    600:        return (USBD_NORMAL_COMPLETION);
                    601: }
                    602:
                    603: void
                    604: usbd_interface2device_handle(usbd_interface_handle iface,
                    605:     usbd_device_handle *dev)
                    606: {
                    607:        *dev = iface->device;
                    608: }
                    609:
                    610: usbd_status
                    611: usbd_device2interface_handle(usbd_device_handle dev, u_int8_t ifaceno,
                    612:     usbd_interface_handle *iface)
                    613: {
                    614:        if (dev->cdesc == NULL)
                    615:                return (USBD_NOT_CONFIGURED);
                    616:        if (ifaceno >= dev->cdesc->bNumInterface)
                    617:                return (USBD_INVAL);
                    618:        *iface = &dev->ifaces[ifaceno];
                    619:        return (USBD_NORMAL_COMPLETION);
                    620: }
                    621:
                    622: usbd_device_handle
                    623: usbd_pipe2device_handle(usbd_pipe_handle pipe)
                    624: {
                    625:        return (pipe->device);
                    626: }
                    627:
                    628: /* XXXX use altno */
                    629: usbd_status
                    630: usbd_set_interface(usbd_interface_handle iface, int altidx)
                    631: {
                    632:        usb_device_request_t req;
                    633:        usbd_status err;
                    634:        void *endpoints;
                    635:
                    636:        if (LIST_FIRST(&iface->pipes) != 0)
                    637:                return (USBD_IN_USE);
                    638:
                    639:        endpoints = iface->endpoints;
                    640:        err = usbd_fill_iface_data(iface->device, iface->index, altidx);
                    641:        if (err)
                    642:                return (err);
                    643:
                    644:        /* new setting works, we can free old endpoints */
                    645:        if (endpoints != NULL)
                    646:                free(endpoints, M_USB);
                    647:
                    648: #ifdef DIAGNOSTIC
                    649:        if (iface->idesc == NULL) {
                    650:                printf("usbd_set_interface: NULL pointer\n");
                    651:                return (USBD_INVAL);
                    652:        }
                    653: #endif
                    654:
                    655:        req.bmRequestType = UT_WRITE_INTERFACE;
                    656:        req.bRequest = UR_SET_INTERFACE;
                    657:        USETW(req.wValue, iface->idesc->bAlternateSetting);
                    658:        USETW(req.wIndex, iface->idesc->bInterfaceNumber);
                    659:        USETW(req.wLength, 0);
                    660:        return (usbd_do_request(iface->device, &req, 0));
                    661: }
                    662:
                    663: int
                    664: usbd_get_no_alts(usb_config_descriptor_t *cdesc, int ifaceno)
                    665: {
                    666:        char *p = (char *)cdesc;
                    667:        char *end = p + UGETW(cdesc->wTotalLength);
                    668:        usb_interface_descriptor_t *d;
                    669:        int n;
                    670:
                    671:        for (n = 0; p < end; p += d->bLength) {
                    672:                d = (usb_interface_descriptor_t *)p;
                    673:                if (p + d->bLength <= end &&
                    674:                    d->bDescriptorType == UDESC_INTERFACE &&
                    675:                    d->bInterfaceNumber == ifaceno)
                    676:                        n++;
                    677:        }
                    678:        return (n);
                    679: }
                    680:
                    681: int
                    682: usbd_get_interface_altindex(usbd_interface_handle iface)
                    683: {
                    684:        return (iface->altindex);
                    685: }
                    686:
                    687: usbd_status
                    688: usbd_get_interface(usbd_interface_handle iface, u_int8_t *aiface)
                    689: {
                    690:        usb_device_request_t req;
                    691:
                    692:        req.bmRequestType = UT_READ_INTERFACE;
                    693:        req.bRequest = UR_GET_INTERFACE;
                    694:        USETW(req.wValue, 0);
                    695:        USETW(req.wIndex, iface->idesc->bInterfaceNumber);
                    696:        USETW(req.wLength, 1);
                    697:        return (usbd_do_request(iface->device, &req, aiface));
                    698: }
                    699:
                    700: /*** Internal routines ***/
                    701:
                    702: /* Dequeue all pipe operations, called at splusb(). */
                    703: usbd_status
                    704: usbd_ar_pipe(usbd_pipe_handle pipe)
                    705: {
                    706:        usbd_xfer_handle xfer;
                    707:
                    708:        SPLUSBCHECK;
                    709:
                    710:        DPRINTFN(2,("usbd_ar_pipe: pipe=%p\n", pipe));
                    711: #ifdef USB_DEBUG
                    712:        if (usbdebug > 5)
                    713:                usbd_dump_queue(pipe);
                    714: #endif
                    715:        pipe->repeat = 0;
                    716:        pipe->aborting = 1;
                    717:        while ((xfer = SIMPLEQ_FIRST(&pipe->queue)) != NULL) {
                    718:                DPRINTFN(2,("usbd_ar_pipe: pipe=%p xfer=%p (methods=%p)\n",
                    719:                    pipe, xfer, pipe->methods));
                    720:                /* Make the HC abort it (and invoke the callback). */
                    721:                pipe->methods->abort(xfer);
                    722:                /* XXX only for non-0 usbd_clear_endpoint_stall(pipe); */
                    723:        }
                    724:        pipe->aborting = 0;
                    725:        return (USBD_NORMAL_COMPLETION);
                    726: }
                    727:
                    728: /* Called at splusb() */
                    729: void
                    730: usb_transfer_complete(usbd_xfer_handle xfer)
                    731: {
                    732:        usbd_pipe_handle pipe = xfer->pipe;
                    733:        usb_dma_t *dmap = &xfer->dmabuf;
                    734:        int repeat = pipe->repeat;
                    735:        int polling;
                    736:
                    737:        SPLUSBCHECK;
                    738:
                    739:        DPRINTFN(5, ("usb_transfer_complete: pipe=%p xfer=%p status=%d "
                    740:                     "actlen=%d\n", pipe, xfer, xfer->status, xfer->actlen));
                    741: #ifdef DIAGNOSTIC
                    742:        if (xfer->busy_free != XFER_ONQU) {
                    743:                printf("usb_transfer_complete: xfer=%p not busy 0x%08x\n",
                    744:                    xfer, xfer->busy_free);
                    745:                return;
                    746:        }
                    747: #endif
                    748:
                    749: #ifdef DIAGNOSTIC
                    750:        if (pipe == NULL) {
                    751:                printf("usbd_transfer_cb: pipe==0, xfer=%p\n", xfer);
                    752:                return;
                    753:        }
                    754: #endif
                    755:        polling = pipe->device->bus->use_polling;
                    756:        /* XXXX */
                    757:        if (polling)
                    758:                pipe->running = 0;
                    759:
                    760:        if (!(xfer->flags & USBD_NO_COPY) && xfer->actlen != 0 &&
                    761:            usbd_xfer_isread(xfer)) {
                    762: #ifdef DIAGNOSTIC
                    763:                if (xfer->actlen > xfer->length) {
                    764:                        printf("usb_transfer_complete: actlen > len %d > %d\n",
                    765:                            xfer->actlen, xfer->length);
                    766:                        xfer->actlen = xfer->length;
                    767:                }
                    768: #endif
                    769:                memcpy(xfer->buffer, KERNADDR(dmap, 0), xfer->actlen);
                    770:        }
                    771:
                    772:        /* if we allocated the buffer in usbd_transfer() we free it here. */
                    773:        if (xfer->rqflags & URQ_AUTO_DMABUF) {
                    774:                if (!repeat) {
                    775:                        struct usbd_bus *bus = pipe->device->bus;
                    776:                        bus->methods->freem(bus, dmap);
                    777:                        xfer->rqflags &= ~URQ_AUTO_DMABUF;
                    778:                }
                    779:        }
                    780:
                    781:        if (!repeat) {
                    782:                /* Remove request from queue. */
                    783: #ifdef DIAGNOSTIC
                    784:                if (xfer != SIMPLEQ_FIRST(&pipe->queue))
                    785:                        printf("usb_transfer_complete: bad dequeue %p != %p\n",
                    786:                            xfer, SIMPLEQ_FIRST(&pipe->queue));
                    787:                xfer->busy_free = XFER_BUSY;
                    788: #endif
                    789:                SIMPLEQ_REMOVE_HEAD(&pipe->queue, next);
                    790:        }
                    791:        DPRINTFN(5,("usb_transfer_complete: repeat=%d new head=%p\n", repeat,
                    792:            SIMPLEQ_FIRST(&pipe->queue)));
                    793:
                    794:        /* Count completed transfers. */
                    795:        ++pipe->device->bus->stats.uds_requests
                    796:                [pipe->endpoint->edesc->bmAttributes & UE_XFERTYPE];
                    797:
                    798:        xfer->done = 1;
                    799:        if (!xfer->status && xfer->actlen < xfer->length &&
                    800:            !(xfer->flags & USBD_SHORT_XFER_OK)) {
                    801:                DPRINTFN(-1,("usbd_transfer_cb: short transfer %d<%d\n",
                    802:                    xfer->actlen, xfer->length));
                    803:                xfer->status = USBD_SHORT_XFER;
                    804:        }
                    805:
                    806:        if (xfer->callback)
                    807:                xfer->callback(xfer, xfer->priv, xfer->status);
                    808:
                    809: #ifdef DIAGNOSTIC
                    810:        if (pipe->methods->done != NULL)
                    811:                pipe->methods->done(xfer);
                    812:        else
                    813:                printf("usb_transfer_complete: pipe->methods->done == NULL\n");
                    814: #else
                    815:        pipe->methods->done(xfer);
                    816: #endif
                    817:
                    818:        if ((xfer->flags & USBD_SYNCHRONOUS) && !polling)
                    819:                wakeup(xfer);
                    820:
                    821:        if (!repeat) {
                    822:                /* XXX should we stop the queue on all errors? */
                    823:                if ((xfer->status == USBD_CANCELLED ||
                    824:                     xfer->status == USBD_TIMEOUT) &&
                    825:                    pipe->iface != NULL)                /* not control pipe */
                    826:                        pipe->running = 0;
                    827:                else
                    828:                        usbd_start_next(pipe);
                    829:        }
                    830: }
                    831:
                    832: usbd_status
                    833: usb_insert_transfer(usbd_xfer_handle xfer)
                    834: {
                    835:        usbd_pipe_handle pipe = xfer->pipe;
                    836:        usbd_status err;
                    837:        int s;
                    838:
                    839:        DPRINTFN(5,("usb_insert_transfer: pipe=%p running=%d timeout=%d\n",
                    840:            pipe, pipe->running, xfer->timeout));
                    841: #ifdef DIAGNOSTIC
                    842:        if (xfer->busy_free != XFER_BUSY) {
                    843:                printf("usb_insert_transfer: xfer=%p not busy 0x%08x\n", xfer,
                    844:                    xfer->busy_free);
                    845:                return (USBD_INVAL);
                    846:        }
                    847:        xfer->busy_free = XFER_ONQU;
                    848: #endif
                    849:        s = splusb();
                    850:        SIMPLEQ_INSERT_TAIL(&pipe->queue, xfer, next);
                    851:        if (pipe->running)
                    852:                err = USBD_IN_PROGRESS;
                    853:        else {
                    854:                pipe->running = 1;
                    855:                err = USBD_NORMAL_COMPLETION;
                    856:        }
                    857:        splx(s);
                    858:        return (err);
                    859: }
                    860:
                    861: /* Called at splusb() */
                    862: void
                    863: usbd_start_next(usbd_pipe_handle pipe)
                    864: {
                    865:        usbd_xfer_handle xfer;
                    866:        usbd_status err;
                    867:
                    868:        SPLUSBCHECK;
                    869:
                    870: #ifdef DIAGNOSTIC
                    871:        if (pipe == NULL) {
                    872:                printf("usbd_start_next: pipe == NULL\n");
                    873:                return;
                    874:        }
                    875:        if (pipe->methods == NULL || pipe->methods->start == NULL) {
                    876:                printf("usbd_start_next: pipe=%p no start method\n", pipe);
                    877:                return;
                    878:        }
                    879: #endif
                    880:
                    881:        /* Get next request in queue. */
                    882:        xfer = SIMPLEQ_FIRST(&pipe->queue);
                    883:        DPRINTFN(5, ("usbd_start_next: pipe=%p, xfer=%p\n", pipe, xfer));
                    884:        if (xfer == NULL) {
                    885:                pipe->running = 0;
                    886:        } else {
                    887:                err = pipe->methods->start(xfer);
                    888:                if (err != USBD_IN_PROGRESS) {
                    889:                        printf("usbd_start_next: error=%d\n", err);
                    890:                        pipe->running = 0;
                    891:                        /* XXX do what? */
                    892:                }
                    893:        }
                    894: }
                    895:
                    896: usbd_status
                    897: usbd_do_request(usbd_device_handle dev, usb_device_request_t *req, void *data)
                    898: {
                    899:        return (usbd_do_request_flags(dev, req, data, 0, 0,
                    900:            USBD_DEFAULT_TIMEOUT));
                    901: }
                    902:
                    903: usbd_status
                    904: usbd_do_request_flags(usbd_device_handle dev, usb_device_request_t *req,
                    905:     void *data, u_int16_t flags, int *actlen, u_int32_t timo)
                    906: {
                    907:        return (usbd_do_request_flags_pipe(dev, dev->default_pipe, req, data,
                    908:            flags, actlen, timo));
                    909: }
                    910:
                    911: usbd_status
                    912: usbd_do_request_flags_pipe(usbd_device_handle dev, usbd_pipe_handle pipe,
                    913:     usb_device_request_t *req, void *data, u_int16_t flags, int *actlen,
                    914:     u_int32_t timeout)
                    915: {
                    916:        usbd_xfer_handle xfer;
                    917:        usbd_status err;
                    918:
                    919: #ifdef DIAGNOSTIC
                    920:        if (dev->bus->intr_context) {
                    921:                printf("usbd_do_request: not in process context\n");
                    922:                return (USBD_INVAL);
                    923:        }
                    924: #endif
                    925:
                    926:        xfer = usbd_alloc_xfer(dev);
                    927:        if (xfer == NULL)
                    928:                return (USBD_NOMEM);
                    929:        usbd_setup_default_xfer(xfer, dev, 0, timeout, req, data,
                    930:            UGETW(req->wLength), flags, 0);
                    931:        xfer->pipe = pipe;
                    932:        err = usbd_sync_transfer(xfer);
                    933: #if defined(USB_DEBUG) || defined(DIAGNOSTIC)
                    934:        if (xfer->actlen > xfer->length)
                    935:                DPRINTF(("usbd_do_request: overrun addr=%d type=0x%02x req=0x"
                    936:                    "%02x val=%d index=%d rlen=%d length=%d actlen=%d\n",
                    937:                    dev->address, xfer->request.bmRequestType,
                    938:                    xfer->request.bRequest, UGETW(xfer->request.wValue),
                    939:                    UGETW(xfer->request.wIndex), UGETW(xfer->request.wLength),
                    940:                    xfer->length, xfer->actlen));
                    941: #endif
                    942:        if (actlen != NULL)
                    943:                *actlen = xfer->actlen;
                    944:        if (err == USBD_STALLED) {
                    945:                /*
                    946:                 * The control endpoint has stalled.  Control endpoints
                    947:                 * should not halt, but some may do so anyway so clear
                    948:                 * any halt condition.
                    949:                 */
                    950:                usb_device_request_t treq;
                    951:                usb_status_t status;
                    952:                u_int16_t s;
                    953:                usbd_status nerr;
                    954:
                    955:                treq.bmRequestType = UT_READ_ENDPOINT;
                    956:                treq.bRequest = UR_GET_STATUS;
                    957:                USETW(treq.wValue, 0);
                    958:                USETW(treq.wIndex, 0);
                    959:                USETW(treq.wLength, sizeof(usb_status_t));
                    960:                usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT,
                    961:                    &treq, &status,sizeof(usb_status_t), 0, 0);
                    962:                nerr = usbd_sync_transfer(xfer);
                    963:                if (nerr)
                    964:                        goto bad;
                    965:                s = UGETW(status.wStatus);
                    966:                DPRINTF(("usbd_do_request: status = 0x%04x\n", s));
                    967:                if (!(s & UES_HALT))
                    968:                        goto bad;
                    969:                treq.bmRequestType = UT_WRITE_ENDPOINT;
                    970:                treq.bRequest = UR_CLEAR_FEATURE;
                    971:                USETW(treq.wValue, UF_ENDPOINT_HALT);
                    972:                USETW(treq.wIndex, 0);
                    973:                USETW(treq.wLength, 0);
                    974:                usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT,
                    975:                    &treq, &status, 0, 0, 0);
                    976:                nerr = usbd_sync_transfer(xfer);
                    977:                if (nerr)
                    978:                        goto bad;
                    979:        }
                    980:
                    981:  bad:
                    982:        usbd_free_xfer(xfer);
                    983:        return (err);
                    984: }
                    985:
                    986: void
                    987: usbd_do_request_async_cb(usbd_xfer_handle xfer, usbd_private_handle priv,
                    988:     usbd_status status)
                    989: {
                    990: #if defined(USB_DEBUG) || defined(DIAGNOSTIC)
                    991:        if (xfer->actlen > xfer->length)
                    992:                DPRINTF(("usbd_do_request: overrun addr=%d type=0x%02x req=0x"
                    993:                    "%02x val=%d index=%d rlen=%d length=%d actlen=%d\n",
                    994:                    xfer->pipe->device->address, xfer->request.bmRequestType,
                    995:                    xfer->request.bRequest, UGETW(xfer->request.wValue),
                    996:                    UGETW(xfer->request.wIndex), UGETW(xfer->request.wLength),
                    997:                    xfer->length, xfer->actlen));
                    998: #endif
                    999:        usbd_free_xfer(xfer);
                   1000: }
                   1001:
                   1002: /*
                   1003:  * Execute a request without waiting for completion.
                   1004:  * Can be used from interrupt context.
                   1005:  */
                   1006: usbd_status
                   1007: usbd_do_request_async(usbd_device_handle dev, usb_device_request_t *req,
                   1008:     void *data)
                   1009: {
                   1010:        usbd_xfer_handle xfer;
                   1011:        usbd_status err;
                   1012:
                   1013:        xfer = usbd_alloc_xfer(dev);
                   1014:        if (xfer == NULL)
                   1015:                return (USBD_NOMEM);
                   1016:        usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT, req,
                   1017:            data, UGETW(req->wLength), 0, usbd_do_request_async_cb);
                   1018:        err = usbd_transfer(xfer);
                   1019:        if (err != USBD_IN_PROGRESS) {
                   1020:                usbd_free_xfer(xfer);
                   1021:                return (err);
                   1022:        }
                   1023:        return (USBD_NORMAL_COMPLETION);
                   1024: }
                   1025:
                   1026: const struct usbd_quirks *
                   1027: usbd_get_quirks(usbd_device_handle dev)
                   1028: {
                   1029: #ifdef DIAGNOSTIC
                   1030:        if (dev == NULL) {
                   1031:                printf("usbd_get_quirks: dev == NULL\n");
                   1032:                return 0;
                   1033:        }
                   1034: #endif
                   1035:        return (dev->quirks);
                   1036: }
                   1037:
                   1038: /* XXX do periodic free() of free list */
                   1039:
                   1040: /*
                   1041:  * Called from keyboard driver when in polling mode.
                   1042:  */
                   1043: void
                   1044: usbd_dopoll(usbd_interface_handle iface)
                   1045: {
                   1046:        iface->device->bus->methods->do_poll(iface->device->bus);
                   1047: }
                   1048:
                   1049: void
                   1050: usbd_set_polling(usbd_device_handle dev, int on)
                   1051: {
                   1052:        if (on)
                   1053:                dev->bus->use_polling++;
                   1054:        else
                   1055:                dev->bus->use_polling--;
                   1056:        /* When polling we need to make sure there is nothing pending to do. */
                   1057:        if (dev->bus->use_polling)
                   1058:                dev->bus->methods->soft_intr(dev->bus);
                   1059: }
                   1060:
                   1061: usb_endpoint_descriptor_t *
                   1062: usbd_get_endpoint_descriptor(usbd_interface_handle iface, u_int8_t address)
                   1063: {
                   1064:        struct usbd_endpoint *ep;
                   1065:        int i;
                   1066:
                   1067:        for (i = 0; i < iface->idesc->bNumEndpoints; i++) {
                   1068:                ep = &iface->endpoints[i];
                   1069:                if (ep->edesc->bEndpointAddress == address)
                   1070:                        return (iface->endpoints[i].edesc);
                   1071:        }
                   1072:        return (0);
                   1073: }
                   1074:
                   1075: /*
                   1076:  * usbd_ratecheck() can limit the number of error messages that occurs.
                   1077:  * When a device is unplugged it may take up to 0.25s for the hub driver
                   1078:  * to notice it.  If the driver continuosly tries to do I/O operations
                   1079:  * this can generate a large number of messages.
                   1080:  */
                   1081: int
                   1082: usbd_ratecheck(struct timeval *last)
                   1083: {
                   1084:        static struct timeval errinterval = { 0, 250000 }; /* 0.25 s*/
                   1085:
                   1086:        return (ratecheck(last, &errinterval));
                   1087: }
                   1088:
                   1089: /*
                   1090:  * Search for a vendor/product pair in an array.  The item size is
                   1091:  * given as an argument.
                   1092:  */
                   1093: const struct usb_devno *
                   1094: usb_match_device(const struct usb_devno *tbl, u_int nentries, u_int sz,
                   1095:     u_int16_t vendor, u_int16_t product)
                   1096: {
                   1097:        while (nentries-- > 0) {
                   1098:                u_int16_t tproduct = tbl->ud_product;
                   1099:                if (tbl->ud_vendor == vendor &&
                   1100:                    (tproduct == product || tproduct == USB_PRODUCT_ANY))
                   1101:                        return (tbl);
                   1102:                tbl = (const struct usb_devno *)((const char *)tbl + sz);
                   1103:        }
                   1104:        return (NULL);
                   1105: }
                   1106:
                   1107: void
                   1108: usb_desc_iter_init(usbd_device_handle dev, usbd_desc_iter_t *iter)
                   1109: {
                   1110:        const usb_config_descriptor_t *cd = usbd_get_config_descriptor(dev);
                   1111:
                   1112:        iter->cur = (const uByte *)cd;
                   1113:        iter->end = (const uByte *)cd + UGETW(cd->wTotalLength);
                   1114: }
                   1115:
                   1116: const usb_descriptor_t *
                   1117: usb_desc_iter_next(usbd_desc_iter_t *iter)
                   1118: {
                   1119:        const usb_descriptor_t *desc;
                   1120:
                   1121:        if (iter->cur + sizeof(usb_descriptor_t) >= iter->end) {
                   1122:                if (iter->cur != iter->end)
                   1123:                        printf("usb_desc_iter_next: bad descriptor\n");
                   1124:                return NULL;
                   1125:        }
                   1126:        desc = (const usb_descriptor_t *)iter->cur;
                   1127:        if (desc->bLength == 0) {
                   1128:                printf("usb_desc_iter_next: descriptor length = 0\n");
                   1129:                return NULL;
                   1130:        }
                   1131:        iter->cur += desc->bLength;
                   1132:        if (iter->cur > iter->end) {
                   1133:                printf("usb_desc_iter_next: descriptor length too large\n");
                   1134:                return NULL;
                   1135:        }
                   1136:        return desc;
                   1137: }

CVSweb