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

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

CVSweb <webmaster@jp.NetBSD.org>