[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     ! 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