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

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

CVSweb <webmaster@jp.NetBSD.org>