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

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

CVSweb <webmaster@jp.NetBSD.org>