[BACK]Return to usbdi.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / usb

Annotation of src/sys/dev/usb/usbdi.c, Revision 1.77

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

CVSweb <webmaster@jp.NetBSD.org>