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

1.162.2.9! skrll       1: /*     $NetBSD: usbdi.c,v 1.162.2.8 2014/12/03 22:33:56 skrll Exp $    */
1.1       augustss    2:
                      3: /*
1.137     mrg         4:  * Copyright (c) 1998, 2012 The NetBSD Foundation, Inc.
1.1       augustss    5:  * All rights reserved.
                      6:  *
1.11      augustss    7:  * This code is derived from software contributed to The NetBSD Foundation
1.72      augustss    8:  * by Lennart Augustsson (lennart@augustsson.net) at
1.137     mrg         9:  * Carlstedt Research & Technology and Matthew R. Green (mrg@eterna.com.au).
1.1       augustss   10:  *
                     11:  * Redistribution and use in source and binary forms, with or without
                     12:  * modification, are permitted provided that the following conditions
                     13:  * are met:
                     14:  * 1. Redistributions of source code must retain the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer.
                     16:  * 2. Redistributions in binary form must reproduce the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer in the
                     18:  *    documentation and/or other materials provided with the distribution.
                     19:  *
                     20:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     21:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     22:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     23:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     24:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     25:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     26:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     27:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     28:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     29:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     30:  * POSSIBILITY OF SUCH DAMAGE.
                     31:  */
1.84      lukem      32:
                     33: #include <sys/cdefs.h>
1.162.2.9! skrll      34: __KERNEL_RCSID(0, "$NetBSD: usbdi.c,v 1.162.2.8 2014/12/03 22:33:56 skrll Exp $");
1.115     pavel      35:
1.141     christos   36: #ifdef _KERNEL_OPT
1.162     skrll      37: #include "opt_usb.h"
1.115     pavel      38: #include "opt_compat_netbsd.h"
1.141     christos   39: #endif
1.1       augustss   40:
1.162.2.5  skrll      41: #include "usb_dma.h"
                     42:
1.1       augustss   43: #include <sys/param.h>
                     44: #include <sys/systm.h>
                     45: #include <sys/kernel.h>
1.15      augustss   46: #include <sys/device.h>
1.162.2.5  skrll      47: #include <sys/kmem.h>
1.1       augustss   48: #include <sys/proc.h>
1.121     ad         49: #include <sys/bus.h>
1.136     mrg        50: #include <sys/cpu.h>
1.36      augustss   51:
1.1       augustss   52: #include <dev/usb/usb.h>
                     53: #include <dev/usb/usbdi.h>
                     54: #include <dev/usb/usbdi_util.h>
                     55: #include <dev/usb/usbdivar.h>
1.36      augustss   56: #include <dev/usb/usb_mem.h>
1.105     augustss   57: #include <dev/usb/usb_quirks.h>
1.162     skrll      58: #include <dev/usb/usbhist.h>
1.1       augustss   59:
1.119     drochner   60: /* UTF-8 encoding stuff */
                     61: #include <fs/unicode.h>
                     62:
1.1       augustss   63: extern int usbdebug;
                     64:
1.159     skrll      65: Static usbd_status usbd_ar_pipe(usbd_pipe_handle);
                     66: Static void usbd_start_next(usbd_pipe_handle);
1.69      augustss   67: Static usbd_status usbd_open_pipe_ival
1.162.2.1  skrll      68:        (usbd_interface_handle, uint8_t, uint8_t, usbd_pipe_handle *, int);
1.1       augustss   69:
1.110     perry      70: static inline int
1.74      augustss   71: usbd_xfer_isread(usbd_xfer_handle xfer)
1.37      augustss   72: {
1.162.2.6  skrll      73:        if (xfer->ux_rqflags & URQ_REQUEST)
1.162.2.9! skrll      74:                return xfer->ux_request.bmRequestType & UT_READ;
1.37      augustss   75:        else
1.162.2.6  skrll      76:                return (xfer->ux_pipe->up_endpoint->ue_edesc->bEndpointAddress &
1.37      augustss   77:                        UE_DIR_IN);
                     78: }
                     79:
1.162     skrll      80: #if defined(USB_DEBUG)
1.82      augustss   81: void
                     82: usbd_dump_iface(struct usbd_interface *iface)
                     83: {
1.162     skrll      84:        USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
                     85:
                     86:        USBHIST_LOG(usbdebug, "iface %p\n", iface, 0, 0, 0);
1.82      augustss   87:        if (iface == NULL)
                     88:                return;
1.162     skrll      89:        USBHIST_LOG(usbdebug, "     device = %p idesc = %p index = %d",
1.162.2.6  skrll      90:            iface->ui_dev, iface->ui_idesc, iface->ui_index, 0);
1.162     skrll      91:        USBHIST_LOG(usbdebug, "     altindex=%d priv=%p",
1.162.2.6  skrll      92:            iface->ui_altindex, iface->ui_priv, 0, 0);
1.82      augustss   93: }
                     94:
                     95: void
                     96: usbd_dump_device(struct usbd_device *dev)
                     97: {
1.162     skrll      98:        USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
                     99:
                    100:        USBHIST_LOG(usbdebug, "dev = %p", dev, 0, 0, 0);
1.82      augustss  101:        if (dev == NULL)
                    102:                return;
1.162     skrll     103:        USBHIST_LOG(usbdebug, "     bus = %p default_pipe = %p",
1.162.2.6  skrll     104:            dev->ud_bus, dev->ud_pipe0, 0, 0);
1.162     skrll     105:        USBHIST_LOG(usbdebug, "     address = %d config = %d depth = %d ",
1.162.2.6  skrll     106:            dev->ud_addr, dev->ud_config, dev->ud_depth, 0);
1.162     skrll     107:        USBHIST_LOG(usbdebug, "     speed = %d self_powered = %d "
                    108:            "power = %d langid = %d",
1.162.2.6  skrll     109:            dev->ud_speed, dev->ud_selfpowered, dev->ud_power, dev->ud_langid);
1.82      augustss  110: }
                    111:
                    112: void
                    113: usbd_dump_endpoint(struct usbd_endpoint *endp)
                    114: {
1.162     skrll     115:        USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
                    116:
                    117:        USBHIST_LOG(usbdebug, "endp = %p", endp, 0, 0, 0);
1.82      augustss  118:        if (endp == NULL)
                    119:                return;
1.162     skrll     120:        USBHIST_LOG(usbdebug, "    edesc = %p refcnt = %d",
1.162.2.6  skrll     121:            endp->ue_edesc, endp->ue_refcnt, 0, 0);
                    122:        if (endp->ue_edesc)
1.162     skrll     123:                USBHIST_LOG(usbdebug, "     bEndpointAddress=0x%02x",
1.162.2.6  skrll     124:                    endp->ue_edesc->bEndpointAddress, 0, 0, 0);
1.82      augustss  125: }
                    126:
1.28      augustss  127: void
1.74      augustss  128: usbd_dump_queue(usbd_pipe_handle pipe)
1.28      augustss  129: {
1.48      augustss  130:        usbd_xfer_handle xfer;
1.28      augustss  131:
1.162     skrll     132:        USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
                    133:
                    134:        USBHIST_LOG(usbdebug, "pipe = %p", pipe, 0, 0, 0);
1.162.2.6  skrll     135:        SIMPLEQ_FOREACH(xfer, &pipe->up_queue, ux_next) {
1.162     skrll     136:                USBHIST_LOG(usbdebug, "     xfer = %p", xfer, 0, 0, 0);
1.28      augustss  137:        }
1.82      augustss  138: }
                    139:
                    140: void
                    141: usbd_dump_pipe(usbd_pipe_handle pipe)
                    142: {
1.162     skrll     143:        USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
                    144:
                    145:        USBHIST_LOG(usbdebug, "pipe = %p", pipe, 0, 0, 0);
1.82      augustss  146:        if (pipe == NULL)
                    147:                return;
1.162.2.6  skrll     148:        usbd_dump_iface(pipe->up_iface);
                    149:        usbd_dump_device(pipe->up_dev);
                    150:        usbd_dump_endpoint(pipe->up_endpoint);
1.162     skrll     151:        USBHIST_LOG(usbdebug, "(usbd_dump_pipe)", 0, 0, 0, 0);
                    152:        USBHIST_LOG(usbdebug, "     refcnt = %d running = %d aborting = %d",
1.162.2.6  skrll     153:            pipe->up_refcnt, pipe->up_running, pipe->up_aborting, 0);
1.162     skrll     154:        USBHIST_LOG(usbdebug, "     intrxfer = %p, repeat = %d, interval = %d",
1.162.2.6  skrll     155:            pipe->up_intrxfer, pipe->up_repeat, pipe->up_interval, 0);
1.28      augustss  156: }
                    157: #endif
                    158:
1.102     augustss  159: usbd_status
1.162.2.1  skrll     160: usbd_open_pipe(usbd_interface_handle iface, uint8_t address,
                    161:               uint8_t flags, usbd_pipe_handle *pipe)
1.102     augustss  162: {
                    163:        return (usbd_open_pipe_ival(iface, address, flags, pipe,
1.60      augustss  164:                                    USBD_DEFAULT_INTERVAL));
                    165: }
                    166:
1.102     augustss  167: usbd_status
1.162.2.1  skrll     168: usbd_open_pipe_ival(usbd_interface_handle iface, uint8_t address,
                    169:                    uint8_t flags, usbd_pipe_handle *pipe, int ival)
1.102     augustss  170: {
1.1       augustss  171:        usbd_pipe_handle p;
                    172:        struct usbd_endpoint *ep;
1.48      augustss  173:        usbd_status err;
1.12      augustss  174:        int i;
1.1       augustss  175:
1.162     skrll     176:        USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
                    177:
                    178:        USBHIST_LOG(usbdebug, "iface = %p address = 0x%x flags = 0x%x",
                    179:            iface, address, flags, 0);
1.53      augustss  180:
1.162.2.6  skrll     181:        for (i = 0; i < iface->ui_idesc->bNumEndpoints; i++) {
                    182:                ep = &iface->ui_endpoints[i];
                    183:                if (ep->ue_edesc == NULL)
1.162.2.9! skrll     184:                        return USBD_IOERROR;
1.162.2.6  skrll     185:                if (ep->ue_edesc->bEndpointAddress == address)
1.1       augustss  186:                        goto found;
                    187:        }
1.162.2.9! skrll     188:        return USBD_BAD_ADDRESS;
1.1       augustss  189:  found:
1.162.2.6  skrll     190:        if ((flags & USBD_EXCLUSIVE_USE) && ep->ue_refcnt != 0)
1.162.2.9! skrll     191:                return USBD_IN_USE;
1.162.2.6  skrll     192:        err = usbd_setup_pipe_flags(iface->ui_dev, iface, ep, ival, &p, flags);
1.48      augustss  193:        if (err)
1.162.2.9! skrll     194:                return err;
1.162.2.6  skrll     195:        LIST_INSERT_HEAD(&iface->ui_pipes, p, up_next);
1.1       augustss  196:        *pipe = p;
1.162.2.9! skrll     197:        return USBD_NORMAL_COMPLETION;
1.1       augustss  198: }
                    199:
1.102     augustss  200: usbd_status
1.162.2.1  skrll     201: usbd_open_pipe_intr(usbd_interface_handle iface, uint8_t address,
                    202:                    uint8_t flags, usbd_pipe_handle *pipe,
                    203:                    usbd_private_handle priv, void *buffer, uint32_t len,
1.74      augustss  204:                    usbd_callback cb, int ival)
1.1       augustss  205: {
1.48      augustss  206:        usbd_status err;
                    207:        usbd_xfer_handle xfer;
1.1       augustss  208:        usbd_pipe_handle ipipe;
                    209:
1.162     skrll     210:        USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
                    211:
                    212:        USBHIST_LOG(usbdebug, "address = 0x%x flags = 0x%x len = %d",
                    213:            address, flags, len, 0);
1.53      augustss  214:
1.150     jmcneill  215:        err = usbd_open_pipe_ival(iface, address,
                    216:                                  USBD_EXCLUSIVE_USE | (flags & USBD_MPSAFE),
1.60      augustss  217:                                  &ipipe, ival);
1.48      augustss  218:        if (err)
1.162.2.9! skrll     219:                return err;
1.162.2.6  skrll     220:        xfer = usbd_alloc_xfer(iface->ui_dev);
1.48      augustss  221:        if (xfer == NULL) {
                    222:                err = USBD_NOMEM;
1.1       augustss  223:                goto bad1;
1.36      augustss  224:        }
1.60      augustss  225:        usbd_setup_xfer(xfer, ipipe, priv, buffer, len, flags,
                    226:            USBD_NO_TIMEOUT, cb);
1.162.2.6  skrll     227:        ipipe->up_intrxfer = xfer;
                    228:        ipipe->up_repeat = 1;
1.48      augustss  229:        err = usbd_transfer(xfer);
1.1       augustss  230:        *pipe = ipipe;
1.48      augustss  231:        if (err != USBD_IN_PROGRESS)
1.36      augustss  232:                goto bad2;
1.162.2.9! skrll     233:        return USBD_NORMAL_COMPLETION;
1.1       augustss  234:
1.36      augustss  235:  bad2:
1.162.2.6  skrll     236:        ipipe->up_intrxfer = NULL;
                    237:        ipipe->up_repeat = 0;
1.50      augustss  238:        usbd_free_xfer(xfer);
1.36      augustss  239:  bad1:
1.1       augustss  240:        usbd_close_pipe(ipipe);
1.162.2.9! skrll     241:        return err;
1.9       augustss  242: }
                    243:
1.1       augustss  244: usbd_status
1.74      augustss  245: usbd_close_pipe(usbd_pipe_handle pipe)
1.1       augustss  246: {
1.138     mrg       247:
1.162     skrll     248:        USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
                    249:
1.26      augustss  250: #ifdef DIAGNOSTIC
1.48      augustss  251:        if (pipe == NULL) {
1.162     skrll     252:                USBHIST_LOG(usbdebug, "pipe == NULL", 0, 0, 0, 0);
1.162.2.9! skrll     253:                return USBD_NORMAL_COMPLETION;
1.26      augustss  254:        }
                    255: #endif
                    256:
1.138     mrg       257:        usbd_lock_pipe(pipe);
1.162.2.6  skrll     258:        if (--pipe->up_refcnt != 0) {
1.138     mrg       259:                usbd_unlock_pipe(pipe);
1.162.2.9! skrll     260:                return USBD_NORMAL_COMPLETION;
1.138     mrg       261:        }
1.162.2.6  skrll     262:        if (! SIMPLEQ_EMPTY(&pipe->up_queue)) {
1.138     mrg       263:                usbd_unlock_pipe(pipe);
1.162.2.9! skrll     264:                return USBD_PENDING_REQUESTS;
1.138     mrg       265:        }
1.162.2.6  skrll     266:        LIST_REMOVE(pipe, up_next);
                    267:        pipe->up_endpoint->ue_refcnt--;
                    268:        pipe->up_methods->upm_close(pipe);
1.138     mrg       269:        usbd_unlock_pipe(pipe);
1.162.2.6  skrll     270:        if (pipe->up_intrxfer != NULL)
                    271:                usbd_free_xfer(pipe->up_intrxfer);
1.162.2.7  skrll     272:        kmem_free(pipe, pipe->up_dev->ud_bus->ub_pipesize);
1.162.2.9! skrll     273:        return USBD_NORMAL_COMPLETION;
1.1       augustss  274: }
                    275:
1.31      augustss  276: usbd_status
1.74      augustss  277: usbd_transfer(usbd_xfer_handle xfer)
1.1       augustss  278: {
1.162.2.6  skrll     279:        usbd_pipe_handle pipe = xfer->ux_pipe;
1.48      augustss  280:        usbd_status err;
1.120     kiyohara  281:        unsigned int size, flags;
1.16      augustss  282:
1.162     skrll     283:        USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
                    284:
                    285:        USBHIST_LOG(usbdebug,
                    286:            "xfer = %p, flags = %#x, pipe = %p, running = %d",
1.162.2.6  skrll     287:            xfer, xfer->ux_flags, pipe, pipe->up_running);
1.134     jmcneill  288:
1.28      augustss  289: #ifdef USB_DEBUG
                    290:        if (usbdebug > 5)
                    291:                usbd_dump_queue(pipe);
                    292: #endif
1.162.2.6  skrll     293:        xfer->ux_done = 0;
1.31      augustss  294:
1.162.2.6  skrll     295:        if (pipe->up_aborting) {
1.162     skrll     296:                USBHIST_LOG(usbdebug, "<- done xfer %p, aborting", xfer, 0, 0,
                    297:                    0);
1.162.2.9! skrll     298:                return USBD_CANCELLED;
1.162     skrll     299:        }
1.71      augustss  300:
1.162.2.6  skrll     301:        struct usbd_bus *bus = pipe->up_dev->ud_bus;
1.162.2.5  skrll     302:
1.162.2.6  skrll     303:        size = xfer->ux_length;
                    304:        flags = xfer->ux_flags;
1.162.2.5  skrll     305:
                    306:        /*
                    307:         * isoc transfers are always size == 0, whereas other transfers can
                    308:         * require a URQ_AUTO_BUFFER buffer.
                    309:         *
                    310:         * URQ_AUTO_BUFFER will be removed at some point, i.e. the transfer
                    311:         * should provide the buffer.
                    312:         */
                    313:        if (size != 0) {
1.162.2.6  skrll     314:                if (xfer->ux_buf == NULL) {
                    315:                        xfer->ux_buf = usbd_alloc_buffer(xfer, size);
                    316:                        if (xfer->ux_buf == NULL)
1.162.2.5  skrll     317:                                return USBD_NOMEM;
1.37      augustss  318:
                    319: #ifdef DIAGNOSTIC
1.162.2.6  skrll     320:                        if (xfer->ux_rqflags & URQ_AUTO_BUFFER)
1.162.2.5  skrll     321:                                printf("usbd_transfer: has old buffer!\n");
1.37      augustss  322: #endif
1.162.2.6  skrll     323:                        xfer->ux_rqflags |= URQ_AUTO_BUFFER;
1.162     skrll     324:                }
1.38      augustss  325:        }
1.162.2.6  skrll     326:        if (bus->ub_usedma) {
1.162.2.5  skrll     327:                /*
                    328:                 * Copy data if not using the xfer buffer.  isoc transfers
                    329:                 * always use DMA buffer, i.e. buffer == NULL
                    330:                 */
1.162.2.6  skrll     331:                if (xfer->ux_buffer == NULL) {
                    332:                        xfer->ux_buffer = xfer->ux_buf;
                    333:                } else if (xfer->ux_buffer != xfer->ux_buf) {
                    334:                        memcpy(xfer->ux_buf, xfer->ux_buffer, size);
1.162.2.5  skrll     335:                }
                    336:        } else {
1.162.2.6  skrll     337:                xfer->ux_buffer = xfer->ux_buf;
1.162.2.5  skrll     338:        }
1.37      augustss  339:
1.120     kiyohara  340:        /* xfer is not valid after the transfer method unless synchronous */
1.162.2.6  skrll     341:        err = pipe->up_methods->upm_transfer(xfer);
1.162     skrll     342:        USBHIST_LOG(usbdebug, "<- done transfer %p, err = %d", xfer, err, 0, 0);
1.37      augustss  343:
1.51      augustss  344:        if (err != USBD_IN_PROGRESS && err) {
1.37      augustss  345:                /* The transfer has not been queued, so free buffer. */
1.162.2.6  skrll     346:                if (xfer->ux_rqflags & URQ_AUTO_BUFFER) {
1.162.2.5  skrll     347:                        usbd_free_buffer(xfer);
1.162.2.6  skrll     348:                        xfer->ux_rqflags &= ~URQ_AUTO_BUFFER;
1.37      augustss  349:                }
                    350:        }
                    351:
1.162     skrll     352:        if (!(flags & USBD_SYNCHRONOUS)) {
                    353:                USBHIST_LOG(usbdebug, "<- done xfer %p, not sync", xfer, 0, 0,
                    354:                    0);
1.162.2.9! skrll     355:                return err;
1.162     skrll     356:        }
1.31      augustss  357:
                    358:        /* Sync transfer, wait for completion. */
1.162     skrll     359:        if (err != USBD_IN_PROGRESS) {
                    360:                USBHIST_LOG(usbdebug, "<- done xfer %p, not in progress", xfer,
                    361:                    0, 0, 0);
1.162.2.9! skrll     362:                return err;
1.162     skrll     363:        }
1.138     mrg       364:        usbd_lock_pipe(pipe);
1.162.2.6  skrll     365:        while (!xfer->ux_done) {
                    366:                if (pipe->up_dev->ud_bus->ub_usepolling)
1.103     provos    367:                        panic("usbd_transfer: not done");
1.162     skrll     368:                USBHIST_LOG(usbdebug, "<- sleeping on xfer %p", xfer, 0, 0, 0);
1.138     mrg       369:
1.144     christos  370:                err = 0;
1.138     mrg       371:                if ((flags & USBD_SYNCHRONOUS_SIG) != 0) {
1.162.2.6  skrll     372:                        err = cv_wait_sig(&xfer->ux_cv, pipe->up_dev->ud_bus->ub_lock);
1.138     mrg       373:                } else {
1.162.2.6  skrll     374:                        cv_wait(&xfer->ux_cv, pipe->up_dev->ud_bus->ub_lock);
1.138     mrg       375:                }
1.154     aymeric   376:                if (err) {
1.162.2.6  skrll     377:                        if (!xfer->ux_done)
                    378:                                pipe->up_methods->upm_abort(xfer);
1.144     christos  379:                        break;
1.154     aymeric   380:                }
1.31      augustss  381:        }
1.138     mrg       382:        usbd_unlock_pipe(pipe);
1.162.2.9! skrll     383:        return xfer->ux_status;
1.31      augustss  384: }
                    385:
                    386: /* Like usbd_transfer(), but waits for completion. */
                    387: usbd_status
1.74      augustss  388: usbd_sync_transfer(usbd_xfer_handle xfer)
1.31      augustss  389: {
1.162.2.6  skrll     390:        xfer->ux_flags |= USBD_SYNCHRONOUS;
1.162.2.9! skrll     391:        return usbd_transfer(xfer);
1.16      augustss  392: }
                    393:
1.138     mrg       394: /* Like usbd_transfer(), but waits for completion and listens for signals. */
                    395: usbd_status
                    396: usbd_sync_transfer_sig(usbd_xfer_handle xfer)
                    397: {
1.162.2.6  skrll     398:        xfer->ux_flags |= USBD_SYNCHRONOUS | USBD_SYNCHRONOUS_SIG;
1.162.2.9! skrll     399:        return usbd_transfer(xfer);
1.138     mrg       400: }
                    401:
1.36      augustss  402: void *
1.162.2.1  skrll     403: usbd_alloc_buffer(usbd_xfer_handle xfer, uint32_t size)
1.36      augustss  404: {
1.162.2.5  skrll     405:
1.162.2.6  skrll     406:        KASSERT(xfer->ux_buf == NULL);
1.162.2.5  skrll     407:        KASSERT(size != 0);
1.162.2.6  skrll     408:        KASSERT(!(xfer->ux_rqflags & URQ_AUTO_BUFFER));
1.162.2.5  skrll     409:
1.162.2.6  skrll     410:        xfer->ux_bufsize = 0;
1.162.2.5  skrll     411: #if NUSB_DMA > 0
1.162.2.6  skrll     412:        struct usbd_bus *bus = xfer->ux_dev->ud_bus;
1.37      augustss  413:
1.162.2.6  skrll     414:        if (bus->ub_usedma) {
                    415:                usb_dma_t *dmap = &xfer->ux_dmabuf;
1.162.2.5  skrll     416:
1.162.2.6  skrll     417:                int err = usb_allocmem_flags(bus, size, 0, dmap, bus->ub_dmaflags);
1.162.2.5  skrll     418:                if (err) {
                    419:                        return NULL;
                    420:                }
1.162.2.6  skrll     421:                xfer->ux_buf = KERNADDR(&xfer->ux_dmabuf, 0);
                    422:                xfer->ux_bufsize = size;
1.162.2.5  skrll     423:
1.162.2.6  skrll     424:                return xfer->ux_buf;
1.162.2.5  skrll     425:        }
1.92      augustss  426: #endif
1.162.2.6  skrll     427:        KASSERT(xfer->ux_dev->ud_bus->ub_usedma == false);
                    428:        xfer->ux_buf = kmem_alloc(size, KM_SLEEP);
1.162.2.5  skrll     429:
1.162.2.6  skrll     430:        if (xfer->ux_buf != NULL) {
                    431:                xfer->ux_bufsize = size;
1.162.2.5  skrll     432:        }
                    433:
1.162.2.6  skrll     434:        return xfer->ux_buf;
1.36      augustss  435: }
                    436:
                    437: void
1.74      augustss  438: usbd_free_buffer(usbd_xfer_handle xfer)
1.36      augustss  439: {
1.162.2.6  skrll     440:        KASSERT(xfer->ux_buf != NULL);
                    441:        KASSERT(xfer->ux_bufsize != 0);
1.162.2.5  skrll     442:
1.162.2.6  skrll     443:        void *buf = xfer->ux_buf;
                    444:        uint32_t size = xfer->ux_bufsize;
1.162.2.5  skrll     445:
1.162.2.6  skrll     446:        xfer->ux_rqflags &= ~URQ_AUTO_BUFFER;
                    447:        xfer->ux_buf = NULL;
                    448:        xfer->ux_bufsize = 0;
1.162.2.5  skrll     449:
                    450: #if NUSB_DMA > 0
1.162.2.6  skrll     451:        struct usbd_bus *bus = xfer->ux_dev->ud_bus;
1.162.2.5  skrll     452:
1.162.2.6  skrll     453:        if (bus->ub_usedma) {
                    454:                usb_dma_t *dmap = &xfer->ux_dmabuf;
1.162.2.5  skrll     455:
                    456:                usb_freemem(bus, dmap);
1.37      augustss  457:                return;
                    458:        }
                    459: #endif
1.162.2.6  skrll     460:        KASSERT(xfer->ux_dev->ud_bus->ub_usedma == false);
1.162.2.5  skrll     461:
                    462:        kmem_free(buf, size);
1.36      augustss  463: }
                    464:
1.38      augustss  465: void *
1.74      augustss  466: usbd_get_buffer(usbd_xfer_handle xfer)
1.38      augustss  467: {
1.162.2.5  skrll     468:
1.162.2.6  skrll     469:        return xfer->ux_buf;
1.38      augustss  470: }
                    471:
1.102     augustss  472: usbd_xfer_handle
1.74      augustss  473: usbd_alloc_xfer(usbd_device_handle dev)
1.1       augustss  474: {
1.48      augustss  475:        usbd_xfer_handle xfer;
1.1       augustss  476:
1.162     skrll     477:        USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
                    478:
1.162.2.3  skrll     479:        ASSERT_SLEEPABLE();
                    480:
1.162.2.6  skrll     481:        xfer = dev->ud_bus->ub_methods->ubm_allocx(dev->ud_bus);
1.48      augustss  482:        if (xfer == NULL)
1.162.2.9! skrll     483:                return NULL;
1.162.2.6  skrll     484:        xfer->ux_dev = dev;
                    485:        callout_init(&xfer->ux_callout, CALLOUT_MPSAFE);
                    486:        cv_init(&xfer->ux_cv, "usbxfer");
                    487:        cv_init(&xfer->ux_hccv, "usbhcxfer");
1.162     skrll     488:
                    489:        USBHIST_LOG(usbdebug, "returns %p", xfer, 0, 0, 0);
                    490:
1.162.2.9! skrll     491:        return xfer;
1.1       augustss  492: }
                    493:
1.102     augustss  494: usbd_status
1.74      augustss  495: usbd_free_xfer(usbd_xfer_handle xfer)
1.1       augustss  496: {
1.162     skrll     497:        USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
                    498:
                    499:        USBHIST_LOG(usbdebug, "%p", xfer, 0, 0, 0);
1.162.2.6  skrll     500:        if (xfer->ux_buf) {
1.48      augustss  501:                usbd_free_buffer(xfer);
1.162.2.5  skrll     502:        }
1.123     drochner  503: #if defined(DIAGNOSTIC)
1.162.2.6  skrll     504:        if (callout_pending(&xfer->ux_callout)) {
                    505:                callout_stop(&xfer->ux_callout);
1.140     skrll     506:                printf("usbd_free_xfer: timeout_handle pending\n");
1.68      augustss  507:        }
1.66      thorpej   508: #endif
1.162.2.6  skrll     509:        cv_destroy(&xfer->ux_cv);
                    510:        cv_destroy(&xfer->ux_hccv);
                    511:        xfer->ux_dev->ud_bus->ub_methods->ubm_freex(xfer->ux_dev->ud_bus, xfer);
1.162.2.9! skrll     512:        return USBD_NORMAL_COMPLETION;
1.1       augustss  513: }
                    514:
1.36      augustss  515: void
1.74      augustss  516: usbd_setup_xfer(usbd_xfer_handle xfer, usbd_pipe_handle pipe,
1.162.2.1  skrll     517:                usbd_private_handle priv, void *buffer, uint32_t length,
                    518:                uint16_t flags, uint32_t timeout,
1.74      augustss  519:                usbd_callback callback)
1.1       augustss  520: {
1.162.2.6  skrll     521:        xfer->ux_pipe = pipe;
                    522:        xfer->ux_priv = priv;
                    523:        xfer->ux_buffer = buffer;
                    524:        xfer->ux_length = length;
                    525:        xfer->ux_actlen = 0;
                    526:        xfer->ux_flags = flags;
                    527:        xfer->ux_timeout = timeout;
                    528:        xfer->ux_status = USBD_NOT_STARTED;
                    529:        xfer->ux_callback = callback;
                    530:        xfer->ux_rqflags &= ~URQ_REQUEST;
                    531:        xfer->ux_nframes = 0;
1.1       augustss  532: }
                    533:
1.36      augustss  534: void
1.74      augustss  535: usbd_setup_default_xfer(usbd_xfer_handle xfer, usbd_device_handle dev,
1.162.2.1  skrll     536:                        usbd_private_handle priv, uint32_t timeout,
1.74      augustss  537:                        usb_device_request_t *req, void *buffer,
1.162.2.1  skrll     538:                        uint32_t length, uint16_t flags,
1.74      augustss  539:                        usbd_callback callback)
1.1       augustss  540: {
1.162.2.6  skrll     541:        xfer->ux_pipe = dev->ud_pipe0;
                    542:        xfer->ux_priv = priv;
                    543:        xfer->ux_buffer = buffer;
                    544:        xfer->ux_length = length;
                    545:        xfer->ux_actlen = 0;
                    546:        xfer->ux_flags = flags;
                    547:        xfer->ux_timeout = timeout;
                    548:        xfer->ux_status = USBD_NOT_STARTED;
                    549:        xfer->ux_callback = callback;
                    550:        xfer->ux_request = *req;
                    551:        xfer->ux_rqflags |= URQ_REQUEST;
                    552:        xfer->ux_nframes = 0;
1.36      augustss  553: }
                    554:
                    555: void
1.74      augustss  556: usbd_setup_isoc_xfer(usbd_xfer_handle xfer, usbd_pipe_handle pipe,
1.162.2.1  skrll     557:                     usbd_private_handle priv, uint16_t *frlengths,
                    558:                     uint32_t nframes, uint16_t flags, usbd_callback callback)
1.36      augustss  559: {
1.162.2.6  skrll     560:        xfer->ux_pipe = pipe;
                    561:        xfer->ux_priv = priv;
                    562:        xfer->ux_buffer = 0;
                    563:        xfer->ux_length = 0;
                    564:        xfer->ux_actlen = 0;
                    565:        xfer->ux_flags = flags;
                    566:        xfer->ux_timeout = USBD_NO_TIMEOUT;
                    567:        xfer->ux_status = USBD_NOT_STARTED;
                    568:        xfer->ux_callback = callback;
                    569:        xfer->ux_rqflags &= ~URQ_REQUEST;
                    570:        xfer->ux_frlengths = frlengths;
                    571:        xfer->ux_nframes = nframes;
1.1       augustss  572: }
                    573:
1.31      augustss  574: void
1.74      augustss  575: usbd_get_xfer_status(usbd_xfer_handle xfer, usbd_private_handle *priv,
1.162.2.1  skrll     576:                     void **buffer, uint32_t *count, usbd_status *status)
1.1       augustss  577: {
1.48      augustss  578:        if (priv != NULL)
1.162.2.6  skrll     579:                *priv = xfer->ux_priv;
1.48      augustss  580:        if (buffer != NULL)
1.162.2.6  skrll     581:                *buffer = xfer->ux_buffer;
1.48      augustss  582:        if (count != NULL)
1.162.2.6  skrll     583:                *count = xfer->ux_actlen;
1.48      augustss  584:        if (status != NULL)
1.162.2.6  skrll     585:                *status = xfer->ux_status;
1.1       augustss  586: }
                    587:
                    588: usb_config_descriptor_t *
1.74      augustss  589: usbd_get_config_descriptor(usbd_device_handle dev)
1.1       augustss  590: {
1.53      augustss  591: #ifdef DIAGNOSTIC
                    592:        if (dev == NULL) {
                    593:                printf("usbd_get_config_descriptor: dev == NULL\n");
1.162.2.9! skrll     594:                return NULL;
1.53      augustss  595:        }
                    596: #endif
1.162.2.9! skrll     597:        return dev->ud_cdesc;
1.1       augustss  598: }
                    599:
                    600: usb_interface_descriptor_t *
1.74      augustss  601: usbd_get_interface_descriptor(usbd_interface_handle iface)
1.1       augustss  602: {
1.53      augustss  603: #ifdef DIAGNOSTIC
                    604:        if (iface == NULL) {
                    605:                printf("usbd_get_interface_descriptor: dev == NULL\n");
1.162.2.9! skrll     606:                return NULL;
1.53      augustss  607:        }
                    608: #endif
1.162.2.9! skrll     609:        return iface->ui_idesc;
1.1       augustss  610: }
                    611:
                    612: usb_device_descriptor_t *
1.74      augustss  613: usbd_get_device_descriptor(usbd_device_handle dev)
1.1       augustss  614: {
1.162.2.9! skrll     615:        return &dev->ud_ddesc;
1.1       augustss  616: }
                    617:
                    618: usb_endpoint_descriptor_t *
1.162.2.1  skrll     619: usbd_interface2endpoint_descriptor(usbd_interface_handle iface, uint8_t index)
1.1       augustss  620: {
1.162.2.6  skrll     621:        if (index >= iface->ui_idesc->bNumEndpoints)
1.162.2.9! skrll     622:                return NULL;
        !           623:        return iface->ui_endpoints[index].ue_edesc;
1.1       augustss  624: }
                    625:
1.125     jmorse    626: /* Some drivers may wish to abort requests on the default pipe, *
                    627:  * but there is no mechanism for getting a handle on it.        */
                    628: usbd_status
                    629: usbd_abort_default_pipe(struct usbd_device *device)
                    630: {
                    631:
1.162.2.6  skrll     632:        return usbd_abort_pipe(device->ud_pipe0);
1.125     jmorse    633: }
                    634:
1.102     augustss  635: usbd_status
1.74      augustss  636: usbd_abort_pipe(usbd_pipe_handle pipe)
1.1       augustss  637: {
1.48      augustss  638:        usbd_status err;
1.1       augustss  639:
1.26      augustss  640: #ifdef DIAGNOSTIC
1.48      augustss  641:        if (pipe == NULL) {
1.126     uebayasi  642:                printf("usbd_abort_pipe: pipe==NULL\n");
1.162.2.9! skrll     643:                return USBD_NORMAL_COMPLETION;
1.26      augustss  644:        }
                    645: #endif
1.138     mrg       646:        usbd_lock_pipe(pipe);
1.48      augustss  647:        err = usbd_ar_pipe(pipe);
1.138     mrg       648:        usbd_unlock_pipe(pipe);
1.162.2.9! skrll     649:        return err;
1.1       augustss  650: }
1.102     augustss  651:
                    652: usbd_status
1.74      augustss  653: usbd_clear_endpoint_stall(usbd_pipe_handle pipe)
1.1       augustss  654: {
1.162.2.6  skrll     655:        usbd_device_handle dev = pipe->up_dev;
1.1       augustss  656:        usb_device_request_t req;
1.48      augustss  657:        usbd_status err;
1.1       augustss  658:
1.162     skrll     659:        USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
1.33      augustss  660:
1.102     augustss  661:        /*
1.87      augustss  662:         * Clearing en endpoint stall resets the endpoint toggle, so
1.33      augustss  663:         * do the same to the HC toggle.
                    664:         */
1.162.2.6  skrll     665:        pipe->up_methods->upm_cleartoggle(pipe);
1.33      augustss  666:
1.1       augustss  667:        req.bmRequestType = UT_WRITE_ENDPOINT;
                    668:        req.bRequest = UR_CLEAR_FEATURE;
1.15      augustss  669:        USETW(req.wValue, UF_ENDPOINT_HALT);
1.162.2.6  skrll     670:        USETW(req.wIndex, pipe->up_endpoint->ue_edesc->bEndpointAddress);
1.1       augustss  671:        USETW(req.wLength, 0);
1.48      augustss  672:        err = usbd_do_request(dev, &req, 0);
1.1       augustss  673: #if 0
                    674: XXX should we do this?
1.51      augustss  675:        if (!err) {
1.1       augustss  676:                pipe->state = USBD_PIPE_ACTIVE;
                    677:                /* XXX activate pipe */
                    678:        }
                    679: #endif
1.162.2.9! skrll     680:        return err;
1.1       augustss  681: }
                    682:
1.139     mrg       683: void
1.156     skrll     684: usbd_clear_endpoint_stall_task(void *arg)
1.7       augustss  685: {
1.139     mrg       686:        usbd_pipe_handle pipe = arg;
1.162.2.6  skrll     687:        usbd_device_handle dev = pipe->up_dev;
1.7       augustss  688:        usb_device_request_t req;
                    689:
1.162.2.6  skrll     690:        pipe->up_methods->upm_cleartoggle(pipe);
1.33      augustss  691:
1.7       augustss  692:        req.bmRequestType = UT_WRITE_ENDPOINT;
                    693:        req.bRequest = UR_CLEAR_FEATURE;
1.15      augustss  694:        USETW(req.wValue, UF_ENDPOINT_HALT);
1.162.2.6  skrll     695:        USETW(req.wIndex, pipe->up_endpoint->ue_edesc->bEndpointAddress);
1.7       augustss  696:        USETW(req.wLength, 0);
1.156     skrll     697:        (void)usbd_do_request(dev, &req, 0);
1.139     mrg       698: }
                    699:
                    700: void
                    701: usbd_clear_endpoint_stall_async(usbd_pipe_handle pipe)
                    702: {
                    703:
1.162.2.6  skrll     704:        usb_add_task(pipe->up_dev, &pipe->up_async_task, USB_TASKQ_DRIVER);
1.7       augustss  705: }
                    706:
1.61      augustss  707: void
1.74      augustss  708: usbd_clear_endpoint_toggle(usbd_pipe_handle pipe)
1.61      augustss  709: {
1.162.2.6  skrll     710:        pipe->up_methods->upm_cleartoggle(pipe);
1.61      augustss  711: }
                    712:
1.102     augustss  713: usbd_status
1.162.2.1  skrll     714: usbd_endpoint_count(usbd_interface_handle iface, uint8_t *count)
1.1       augustss  715: {
1.73      augustss  716: #ifdef DIAGNOSTIC
1.162.2.6  skrll     717:        if (iface == NULL || iface->ui_idesc == NULL) {
1.73      augustss  718:                printf("usbd_endpoint_count: NULL pointer\n");
1.162.2.9! skrll     719:                return USBD_INVAL;
1.73      augustss  720:        }
                    721: #endif
1.162.2.6  skrll     722:        *count = iface->ui_idesc->bNumEndpoints;
1.162.2.9! skrll     723:        return USBD_NORMAL_COMPLETION;
1.1       augustss  724: }
                    725:
1.102     augustss  726: usbd_status
1.162.2.1  skrll     727: usbd_interface_count(usbd_device_handle dev, uint8_t *count)
1.1       augustss  728: {
1.162.2.6  skrll     729:        if (dev->ud_cdesc == NULL)
1.162.2.9! skrll     730:                return USBD_NOT_CONFIGURED;
1.162.2.6  skrll     731:        *count = dev->ud_cdesc->bNumInterface;
1.162.2.9! skrll     732:        return USBD_NORMAL_COMPLETION;
1.1       augustss  733: }
                    734:
1.85      augustss  735: void
1.74      augustss  736: usbd_interface2device_handle(usbd_interface_handle iface,
                    737:                             usbd_device_handle *dev)
1.1       augustss  738: {
1.162.2.6  skrll     739:        *dev = iface->ui_dev;
1.1       augustss  740: }
                    741:
1.102     augustss  742: usbd_status
1.74      augustss  743: usbd_device2interface_handle(usbd_device_handle dev,
1.162.2.1  skrll     744:                             uint8_t ifaceno, usbd_interface_handle *iface)
1.1       augustss  745: {
1.162.2.6  skrll     746:        if (dev->ud_cdesc == NULL)
1.162.2.9! skrll     747:                return USBD_NOT_CONFIGURED;
1.162.2.6  skrll     748:        if (ifaceno >= dev->ud_cdesc->bNumInterface)
1.162.2.9! skrll     749:                return USBD_INVAL;
1.162.2.6  skrll     750:        *iface = &dev->ud_ifaces[ifaceno];
1.162.2.9! skrll     751:        return USBD_NORMAL_COMPLETION;
1.1       augustss  752: }
                    753:
1.36      augustss  754: usbd_device_handle
1.74      augustss  755: usbd_pipe2device_handle(usbd_pipe_handle pipe)
1.36      augustss  756: {
1.162.2.9! skrll     757:        return pipe->up_dev;
1.36      augustss  758: }
                    759:
1.13      augustss  760: /* XXXX use altno */
1.3       augustss  761: usbd_status
1.74      augustss  762: usbd_set_interface(usbd_interface_handle iface, int altidx)
1.3       augustss  763: {
                    764:        usb_device_request_t req;
1.48      augustss  765:        usbd_status err;
1.73      augustss  766:        void *endpoints;
1.13      augustss  767:
1.162.2.6  skrll     768:        if (LIST_FIRST(&iface->ui_pipes) != 0)
1.162.2.9! skrll     769:                return USBD_IN_USE;
1.13      augustss  770:
1.162.2.6  skrll     771:        endpoints = iface->ui_endpoints;
                    772:        err = usbd_fill_iface_data(iface->ui_dev, iface->ui_index, altidx);
1.48      augustss  773:        if (err)
1.162.2.9! skrll     774:                return err;
1.73      augustss  775:
1.76      augustss  776:        /* new setting works, we can free old endpoints */
1.162.2.7  skrll     777:        if (endpoints != NULL) {
                    778:                int nendpt = iface->ui_idesc->bNumEndpoints;
                    779:                kmem_free(endpoints, nendpt * sizeof(struct usbd_endpoint));
                    780:        }
1.73      augustss  781:
                    782: #ifdef DIAGNOSTIC
1.162.2.6  skrll     783:        if (iface->ui_idesc == NULL) {
1.73      augustss  784:                printf("usbd_set_interface: NULL pointer\n");
1.162.2.9! skrll     785:                return USBD_INVAL;
1.73      augustss  786:        }
                    787: #endif
1.3       augustss  788:
                    789:        req.bmRequestType = UT_WRITE_INTERFACE;
                    790:        req.bRequest = UR_SET_INTERFACE;
1.162.2.6  skrll     791:        USETW(req.wValue, iface->ui_idesc->bAlternateSetting);
                    792:        USETW(req.wIndex, iface->ui_idesc->bInterfaceNumber);
1.3       augustss  793:        USETW(req.wLength, 0);
1.162.2.9! skrll     794:        return usbd_do_request(iface->ui_dev, &req, 0);
1.12      augustss  795: }
                    796:
                    797: int
1.74      augustss  798: usbd_get_no_alts(usb_config_descriptor_t *cdesc, int ifaceno)
1.12      augustss  799: {
1.13      augustss  800:        char *p = (char *)cdesc;
                    801:        char *end = p + UGETW(cdesc->wTotalLength);
1.12      augustss  802:        usb_interface_descriptor_t *d;
                    803:        int n;
                    804:
                    805:        for (n = 0; p < end; p += d->bLength) {
                    806:                d = (usb_interface_descriptor_t *)p;
1.102     augustss  807:                if (p + d->bLength <= end &&
1.12      augustss  808:                    d->bDescriptorType == UDESC_INTERFACE &&
1.13      augustss  809:                    d->bInterfaceNumber == ifaceno)
1.12      augustss  810:                        n++;
                    811:        }
1.162.2.9! skrll     812:        return n;
1.13      augustss  813: }
                    814:
                    815: int
1.74      augustss  816: usbd_get_interface_altindex(usbd_interface_handle iface)
1.13      augustss  817: {
1.162.2.9! skrll     818:        return iface->ui_altindex;
1.12      augustss  819: }
                    820:
                    821: usbd_status
1.162.2.1  skrll     822: usbd_get_interface(usbd_interface_handle iface, uint8_t *aiface)
1.12      augustss  823: {
                    824:        usb_device_request_t req;
                    825:
                    826:        req.bmRequestType = UT_READ_INTERFACE;
                    827:        req.bRequest = UR_GET_INTERFACE;
                    828:        USETW(req.wValue, 0);
1.162.2.6  skrll     829:        USETW(req.wIndex, iface->ui_idesc->bInterfaceNumber);
1.12      augustss  830:        USETW(req.wLength, 1);
1.162.2.9! skrll     831:        return usbd_do_request(iface->ui_dev, &req, aiface);
1.3       augustss  832: }
1.1       augustss  833:
                    834: /*** Internal routines ***/
                    835:
                    836: /* Dequeue all pipe operations, called at splusb(). */
1.69      augustss  837: Static usbd_status
1.74      augustss  838: usbd_ar_pipe(usbd_pipe_handle pipe)
1.1       augustss  839: {
1.48      augustss  840:        usbd_xfer_handle xfer;
1.1       augustss  841:
1.162     skrll     842:        USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
                    843:
1.162.2.6  skrll     844:        KASSERT(mutex_owned(pipe->up_dev->ud_bus->ub_lock));
1.138     mrg       845:
1.162     skrll     846:        USBHIST_LOG(usbdebug, "pipe = %p", pipe, 0, 0, 0);
1.28      augustss  847: #ifdef USB_DEBUG
                    848:        if (usbdebug > 5)
                    849:                usbd_dump_queue(pipe);
                    850: #endif
1.162.2.6  skrll     851:        pipe->up_repeat = 0;
                    852:        pipe->up_aborting = 1;
                    853:        while ((xfer = SIMPLEQ_FIRST(&pipe->up_queue)) != NULL) {
1.162     skrll     854:                USBHIST_LOG(usbdebug, "pipe = %p xfer = %p (methods = %p)",
1.162.2.6  skrll     855:                    pipe, xfer, pipe->up_methods, 0);
1.28      augustss  856:                /* Make the HC abort it (and invoke the callback). */
1.162.2.6  skrll     857:                pipe->up_methods->upm_abort(xfer);
1.33      augustss  858:                /* XXX only for non-0 usbd_clear_endpoint_stall(pipe); */
1.20      augustss  859:        }
1.162.2.6  skrll     860:        pipe->up_aborting = 0;
1.162.2.9! skrll     861:        return USBD_NORMAL_COMPLETION;
1.1       augustss  862: }
                    863:
1.138     mrg       864: /* Called with USB lock held. */
1.31      augustss  865: void
1.74      augustss  866: usb_transfer_complete(usbd_xfer_handle xfer)
1.1       augustss  867: {
1.162.2.6  skrll     868:        usbd_pipe_handle pipe = xfer->ux_pipe;
                    869:        struct usbd_bus *bus = pipe->up_dev->ud_bus;
                    870:        int sync = xfer->ux_flags & USBD_SYNCHRONOUS;
                    871:        int erred = xfer->ux_status == USBD_CANCELLED ||
                    872:            xfer->ux_status == USBD_TIMEOUT;
                    873:        int polling = bus->ub_usepolling;
1.152     skrll     874:        int repeat;
1.31      augustss  875:
1.162     skrll     876:        USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
                    877:
                    878:        USBHIST_LOG(usbdebug, "pipe = %p xfer = %p status = %d actlen = %d",
1.162.2.6  skrll     879:                pipe, xfer, xfer->ux_status, xfer->ux_actlen);
1.134     jmcneill  880:
1.162.2.6  skrll     881:        KASSERT(polling || mutex_owned(pipe->up_dev->ud_bus->ub_lock));
1.134     jmcneill  882:
1.93      augustss  883: #ifdef DIAGNOSTIC
1.162.2.6  skrll     884:        if (xfer->ux_state != XFER_ONQU) {
1.147     skrll     885:                printf("usb_transfer_complete: xfer=%p not queued 0x%08x\n",
1.162.2.6  skrll     886:                       xfer, xfer->ux_state);
1.93      augustss  887:        }
                    888: #endif
1.5       augustss  889:
1.23      augustss  890: #ifdef DIAGNOSTIC
1.48      augustss  891:        if (pipe == NULL) {
1.138     mrg       892:                printf("usb_transfer_complete: pipe==0, xfer=%p\n", xfer);
1.31      augustss  893:                return;
                    894:        }
1.23      augustss  895: #endif
1.162.2.6  skrll     896:        repeat = pipe->up_repeat;
1.31      augustss  897:        /* XXXX */
                    898:        if (polling)
1.162.2.6  skrll     899:                pipe->up_running = 0;
1.31      augustss  900:
1.162.2.6  skrll     901:        if (xfer->ux_buffer != xfer->ux_buf) {
1.162.2.5  skrll     902:                /* can only be different for DMA busses */
1.162.2.6  skrll     903:                KASSERT(bus->ub_usedma);
                    904:                KDASSERTMSG(xfer->ux_actlen <= xfer->ux_length,
                    905:                    "actlen %d length %d",xfer->ux_actlen, xfer->ux_length);
1.162.2.5  skrll     906:
1.162.2.6  skrll     907:                memcpy(xfer->ux_buffer, xfer->ux_buf, xfer->ux_actlen);
1.43      augustss  908:        }
1.38      augustss  909:
1.162.2.5  skrll     910:        /* XXX remove at some point */
1.37      augustss  911:        /* if we allocated the buffer in usbd_transfer() we free it here. */
1.162.2.6  skrll     912:        if (xfer->ux_rqflags & URQ_AUTO_BUFFER) {
1.47      augustss  913:                if (!repeat) {
1.162.2.5  skrll     914:                        usbd_free_buffer(xfer);
1.162.2.6  skrll     915:                        xfer->ux_rqflags &= ~URQ_AUTO_BUFFER;
1.37      augustss  916:                }
                    917:        }
                    918:
1.47      augustss  919:        if (!repeat) {
                    920:                /* Remove request from queue. */
1.153     jakllsch  921:
1.162.2.6  skrll     922:                KASSERTMSG(!SIMPLEQ_EMPTY(&pipe->up_queue),
1.145     skrll     923:                    "pipe %p is empty, but xfer %p wants to complete", pipe,
                    924:                     xfer);
1.47      augustss  925: #ifdef DIAGNOSTIC
1.162.2.6  skrll     926:                if (xfer != SIMPLEQ_FIRST(&pipe->up_queue))
1.145     skrll     927:                        printf("%s: bad dequeue %p != %p\n", __func__,
1.162.2.6  skrll     928:                               xfer, SIMPLEQ_FIRST(&pipe->up_queue));
                    929:                xfer->ux_state = XFER_BUSY;
1.45      augustss  930: #endif
1.162.2.6  skrll     931:                SIMPLEQ_REMOVE_HEAD(&pipe->up_queue, ux_next);
1.47      augustss  932:        }
1.162     skrll     933:        USBHIST_LOG(usbdebug, "xfer %p: repeat %d new head = %p",
1.162.2.6  skrll     934:            xfer, repeat, SIMPLEQ_FIRST(&pipe->up_queue), 0);
1.31      augustss  935:
                    936:        /* Count completed transfers. */
1.162.2.6  skrll     937:        ++pipe->up_dev->ud_bus->ub_stats.uds_requests
                    938:                [pipe->up_endpoint->ue_edesc->bmAttributes & UE_XFERTYPE];
1.1       augustss  939:
1.162.2.6  skrll     940:        xfer->ux_done = 1;
                    941:        if (!xfer->ux_status && xfer->ux_actlen < xfer->ux_length &&
                    942:            !(xfer->ux_flags & USBD_SHORT_XFER_OK)) {
1.162     skrll     943:                USBHIST_LOG(usbdebug, "short transfer %d < %d",
1.162.2.6  skrll     944:                    xfer->ux_actlen, xfer->ux_length, 0, 0);
                    945:                xfer->ux_status = USBD_SHORT_XFER;
1.1       augustss  946:        }
1.31      augustss  947:
1.124     jmcneill  948:        if (repeat) {
1.162     skrll     949:                USBHIST_LOG(usbdebug, "xfer %p doing callback %p status %x",
1.162.2.6  skrll     950:                    xfer, xfer->ux_callback, xfer->ux_status, 0);
                    951:                if (xfer->ux_callback) {
1.158     skrll     952:                        if (!polling)
1.162.2.6  skrll     953:                                mutex_exit(pipe->up_dev->ud_bus->ub_lock);
1.148     jmcneill  954:
1.162.2.6  skrll     955:                        if (!(pipe->up_flags & USBD_MPSAFE))
1.148     jmcneill  956:                                KERNEL_LOCK(1, curlwp);
1.162.2.6  skrll     957:                        xfer->ux_callback(xfer, xfer->ux_priv, xfer->ux_status);
1.162     skrll     958:                        USBHIST_LOG(usbdebug, "xfer %p doing done %p", xfer,
1.162.2.6  skrll     959:                            pipe->up_methods->upm_done, 0, 0);
                    960:                        if (!(pipe->up_flags & USBD_MPSAFE))
1.148     jmcneill  961:                                KERNEL_UNLOCK_ONE(curlwp);
                    962:
1.158     skrll     963:                        if (!polling)
1.162.2.6  skrll     964:                                mutex_enter(pipe->up_dev->ud_bus->ub_lock);
1.138     mrg       965:                }
1.162.2.6  skrll     966:                pipe->up_methods->upm_done(xfer);
1.124     jmcneill  967:        } else {
1.162     skrll     968:                USBHIST_LOG(usbdebug, "xfer %p doing done %p", xfer,
1.162.2.6  skrll     969:                    pipe->up_methods->upm_done, 0, 0);
                    970:                pipe->up_methods->upm_done(xfer);
1.162     skrll     971:                USBHIST_LOG(usbdebug, "xfer %p doing callback %p status %x",
1.162.2.6  skrll     972:                    xfer, xfer->ux_callback, xfer->ux_status, 0);
                    973:                if (xfer->ux_callback) {
1.158     skrll     974:                        if (!polling)
1.162.2.6  skrll     975:                                mutex_exit(pipe->up_dev->ud_bus->ub_lock);
1.148     jmcneill  976:
1.162.2.6  skrll     977:                        if (!(pipe->up_flags & USBD_MPSAFE))
1.148     jmcneill  978:                                KERNEL_LOCK(1, curlwp);
1.162.2.6  skrll     979:                        xfer->ux_callback(xfer, xfer->ux_priv, xfer->ux_status);
                    980:                        if (!(pipe->up_flags & USBD_MPSAFE))
1.148     jmcneill  981:                                KERNEL_UNLOCK_ONE(curlwp);
                    982:
1.158     skrll     983:                        if (!polling)
1.162.2.6  skrll     984:                                mutex_enter(pipe->up_dev->ud_bus->ub_lock);
1.138     mrg       985:                }
1.124     jmcneill  986:        }
1.31      augustss  987:
1.138     mrg       988:        if (sync && !polling) {
1.162     skrll     989:                USBHIST_LOG(usbdebug, "<- done xfer %p, wakeup", xfer, 0, 0, 0);
1.162.2.6  skrll     990:                cv_broadcast(&xfer->ux_cv);
1.138     mrg       991:        }
1.31      augustss  992:
1.47      augustss  993:        if (!repeat) {
1.40      augustss  994:                /* XXX should we stop the queue on all errors? */
1.162.2.6  skrll     995:                if (erred && pipe->up_iface != NULL)    /* not control pipe */
                    996:                        pipe->up_running = 0;
1.40      augustss  997:                else
                    998:                        usbd_start_next(pipe);
                    999:        }
1.1       augustss 1000: }
                   1001:
1.138     mrg      1002: /* Called with USB lock held. */
1.31      augustss 1003: usbd_status
1.74      augustss 1004: usb_insert_transfer(usbd_xfer_handle xfer)
1.1       augustss 1005: {
1.162.2.6  skrll    1006:        usbd_pipe_handle pipe = xfer->ux_pipe;
1.48      augustss 1007:        usbd_status err;
1.31      augustss 1008:
1.162     skrll    1009:        USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
                   1010:
                   1011:        USBHIST_LOG(usbdebug, "pipe = %p running = %d timeout = %d",
1.162.2.6  skrll    1012:            pipe, pipe->up_running, xfer->ux_timeout, 0);
1.134     jmcneill 1013:
1.162.2.6  skrll    1014:        KASSERT(mutex_owned(pipe->up_dev->ud_bus->ub_lock));
1.134     jmcneill 1015:
1.93      augustss 1016: #ifdef DIAGNOSTIC
1.162.2.6  skrll    1017:        if (xfer->ux_state != XFER_BUSY) {
1.162     skrll    1018:                USBHIST_LOG(usbdebug, "<- done, xfer %p not busy", xfer, 0, 0,
                   1019:                    0);
1.93      augustss 1020:                printf("usb_insert_transfer: xfer=%p not busy 0x%08x\n",
1.162.2.6  skrll    1021:                       xfer, xfer->ux_state);
1.162.2.9! skrll    1022:                return USBD_INVAL;
1.93      augustss 1023:        }
1.162.2.6  skrll    1024:        xfer->ux_state = XFER_ONQU;
1.93      augustss 1025: #endif
1.162.2.6  skrll    1026:        SIMPLEQ_INSERT_TAIL(&pipe->up_queue, xfer, ux_next);
                   1027:        if (pipe->up_running)
1.48      augustss 1028:                err = USBD_IN_PROGRESS;
1.37      augustss 1029:        else {
1.162.2.6  skrll    1030:                pipe->up_running = 1;
1.48      augustss 1031:                err = USBD_NORMAL_COMPLETION;
1.37      augustss 1032:        }
1.162     skrll    1033:        USBHIST_LOG(usbdebug, "<- done xfer %p, err %d", xfer, err, 0, 0);
1.162.2.9! skrll    1034:        return err;
1.1       augustss 1035: }
                   1036:
1.138     mrg      1037: /* Called with USB lock held. */
1.31      augustss 1038: void
1.74      augustss 1039: usbd_start_next(usbd_pipe_handle pipe)
1.31      augustss 1040: {
1.48      augustss 1041:        usbd_xfer_handle xfer;
                   1042:        usbd_status err;
1.40      augustss 1043:
1.162     skrll    1044:        USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
                   1045:
1.31      augustss 1046: #ifdef DIAGNOSTIC
1.48      augustss 1047:        if (pipe == NULL) {
1.51      augustss 1048:                printf("usbd_start_next: pipe == NULL\n");
1.31      augustss 1049:                return;
                   1050:        }
1.162.2.6  skrll    1051:        if (pipe->up_methods == NULL || pipe->up_methods->upm_start == NULL) {
1.51      augustss 1052:                printf("usbd_start_next: pipe=%p no start method\n", pipe);
1.31      augustss 1053:                return;
                   1054:        }
                   1055: #endif
                   1056:
1.162.2.6  skrll    1057:        KASSERT(mutex_owned(pipe->up_dev->ud_bus->ub_lock));
1.138     mrg      1058:
1.31      augustss 1059:        /* Get next request in queue. */
1.162.2.6  skrll    1060:        xfer = SIMPLEQ_FIRST(&pipe->up_queue);
1.162     skrll    1061:        USBHIST_LOG(usbdebug, "pipe = %p, xfer = %p", pipe, xfer, 0, 0);
1.51      augustss 1062:        if (xfer == NULL) {
1.162.2.6  skrll    1063:                pipe->up_running = 0;
1.51      augustss 1064:        } else {
1.162.2.6  skrll    1065:                mutex_exit(pipe->up_dev->ud_bus->ub_lock);
                   1066:                err = pipe->up_methods->upm_start(xfer);
                   1067:                mutex_enter(pipe->up_dev->ud_bus->ub_lock);
1.158     skrll    1068:
1.48      augustss 1069:                if (err != USBD_IN_PROGRESS) {
1.162     skrll    1070:                        USBHIST_LOG(usbdebug, "error = %d", err, 0, 0, 0);
1.162.2.6  skrll    1071:                        pipe->up_running = 0;
1.31      augustss 1072:                        /* XXX do what? */
                   1073:                }
1.1       augustss 1074:        }
1.138     mrg      1075:
1.162.2.6  skrll    1076:        KASSERT(mutex_owned(pipe->up_dev->ud_bus->ub_lock));
1.1       augustss 1077: }
                   1078:
                   1079: usbd_status
1.74      augustss 1080: usbd_do_request(usbd_device_handle dev, usb_device_request_t *req, void *data)
1.1       augustss 1081: {
1.99      thorpej  1082:        return (usbd_do_request_flags(dev, req, data, 0, 0,
1.98      augustss 1083:                                      USBD_DEFAULT_TIMEOUT));
1.17      augustss 1084: }
                   1085:
                   1086: usbd_status
1.74      augustss 1087: usbd_do_request_flags(usbd_device_handle dev, usb_device_request_t *req,
1.162.2.1  skrll    1088:                      void *data, uint16_t flags, int *actlen, uint32_t timo)
1.17      augustss 1089: {
1.162.2.6  skrll    1090:        return (usbd_do_request_flags_pipe(dev, dev->ud_pipe0, req,
1.96      augustss 1091:                                           data, flags, actlen, timo));
1.77      augustss 1092: }
                   1093:
                   1094: usbd_status
                   1095: usbd_do_request_flags_pipe(usbd_device_handle dev, usbd_pipe_handle pipe,
1.162.2.1  skrll    1096:        usb_device_request_t *req, void *data, uint16_t flags, int *actlen,
                   1097:        uint32_t timeout)
1.77      augustss 1098: {
1.48      augustss 1099:        usbd_xfer_handle xfer;
                   1100:        usbd_status err;
1.1       augustss 1101:
1.162     skrll    1102:        USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
                   1103:
1.162.2.3  skrll    1104:        ASSERT_SLEEPABLE();
1.7       augustss 1105:
1.50      augustss 1106:        xfer = usbd_alloc_xfer(dev);
1.48      augustss 1107:        if (xfer == NULL)
1.162.2.9! skrll    1108:                return USBD_NOMEM;
1.96      augustss 1109:        usbd_setup_default_xfer(xfer, dev, 0, timeout, req,
1.77      augustss 1110:                                data, UGETW(req->wLength), flags, 0);
1.162.2.6  skrll    1111:        xfer->ux_pipe = pipe;
1.48      augustss 1112:        err = usbd_sync_transfer(xfer);
1.1       augustss 1113: #if defined(USB_DEBUG) || defined(DIAGNOSTIC)
1.162.2.6  skrll    1114:        if (xfer->ux_actlen > xfer->ux_length) {
1.162     skrll    1115:                USBHIST_LOG(usbdebug, "overrun addr = %d type = 0x%02x",
1.162.2.6  skrll    1116:                    dev->ud_addr, xfer->ux_request.bmRequestType, 0, 0);
1.162     skrll    1117:                USBHIST_LOG(usbdebug, "     req = 0x%02x val = %d index = %d",
1.162.2.6  skrll    1118:                    xfer->ux_request.bRequest, UGETW(xfer->ux_request.wValue),
                   1119:                    UGETW(xfer->ux_request.wIndex), 0);
1.162     skrll    1120:                USBHIST_LOG(usbdebug, "     rlen = %d length = %d actlen = %d",
1.162.2.6  skrll    1121:                    UGETW(xfer->ux_request.wLength),
                   1122:                    xfer->ux_length, xfer->ux_actlen, 0);
1.112     dogcow   1123:        }
1.1       augustss 1124: #endif
1.48      augustss 1125:        if (actlen != NULL)
1.162.2.6  skrll    1126:                *actlen = xfer->ux_actlen;
1.48      augustss 1127:        if (err == USBD_STALLED) {
1.102     augustss 1128:                /*
1.15      augustss 1129:                 * The control endpoint has stalled.  Control endpoints
                   1130:                 * should not halt, but some may do so anyway so clear
                   1131:                 * any halt condition.
                   1132:                 */
                   1133:                usb_device_request_t treq;
                   1134:                usb_status_t status;
1.162.2.1  skrll    1135:                uint16_t s;
1.48      augustss 1136:                usbd_status nerr;
1.15      augustss 1137:
                   1138:                treq.bmRequestType = UT_READ_ENDPOINT;
                   1139:                treq.bRequest = UR_GET_STATUS;
                   1140:                USETW(treq.wValue, 0);
                   1141:                USETW(treq.wIndex, 0);
                   1142:                USETW(treq.wLength, sizeof(usb_status_t));
1.50      augustss 1143:                usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT,
1.37      augustss 1144:                                           &treq, &status,sizeof(usb_status_t),
1.36      augustss 1145:                                           0, 0);
1.48      augustss 1146:                nerr = usbd_sync_transfer(xfer);
                   1147:                if (nerr)
1.15      augustss 1148:                        goto bad;
                   1149:                s = UGETW(status.wStatus);
1.162     skrll    1150:                USBHIST_LOG(usbdebug, "status = 0x%04x", s, 0, 0, 0);
1.15      augustss 1151:                if (!(s & UES_HALT))
                   1152:                        goto bad;
                   1153:                treq.bmRequestType = UT_WRITE_ENDPOINT;
                   1154:                treq.bRequest = UR_CLEAR_FEATURE;
                   1155:                USETW(treq.wValue, UF_ENDPOINT_HALT);
                   1156:                USETW(treq.wIndex, 0);
                   1157:                USETW(treq.wLength, 0);
1.50      augustss 1158:                usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT,
1.36      augustss 1159:                                           &treq, &status, 0, 0, 0);
1.48      augustss 1160:                nerr = usbd_sync_transfer(xfer);
                   1161:                if (nerr)
1.15      augustss 1162:                        goto bad;
                   1163:        }
                   1164:
                   1165:  bad:
1.132     matt     1166:        if (err) {
1.162     skrll    1167:                USBHIST_LOG(usbdebug, "returning err = %s",
                   1168:                    usbd_errstr(err), 0, 0, 0);
1.132     matt     1169:        }
1.50      augustss 1170:        usbd_free_xfer(xfer);
1.162.2.9! skrll    1171:        return err;
1.7       augustss 1172: }
                   1173:
1.78      augustss 1174: const struct usbd_quirks *
1.74      augustss 1175: usbd_get_quirks(usbd_device_handle dev)
1.1       augustss 1176: {
1.81      augustss 1177: #ifdef DIAGNOSTIC
                   1178:        if (dev == NULL) {
                   1179:                printf("usbd_get_quirks: dev == NULL\n");
                   1180:                return 0;
                   1181:        }
                   1182: #endif
1.162.2.9! skrll    1183:        return dev->ud_quirks;
1.1       augustss 1184: }
                   1185:
                   1186: /* XXX do periodic free() of free list */
                   1187:
1.6       augustss 1188: /*
                   1189:  * Called from keyboard driver when in polling mode.
                   1190:  */
                   1191: void
1.74      augustss 1192: usbd_dopoll(usbd_interface_handle iface)
1.6       augustss 1193: {
1.162.2.6  skrll    1194:        iface->ui_dev->ud_bus->ub_methods->ubm_dopoll(iface->ui_dev->ud_bus);
1.8       augustss 1195: }
                   1196:
1.138     mrg      1197: /*
1.162.2.6  skrll    1198:  * XXX use this more???  ub_usepolling it touched manually all over
1.138     mrg      1199:  */
1.8       augustss 1200: void
1.74      augustss 1201: usbd_set_polling(usbd_device_handle dev, int on)
1.8       augustss 1202: {
1.42      augustss 1203:        if (on)
1.162.2.6  skrll    1204:                dev->ud_bus->ub_usepolling++;
1.42      augustss 1205:        else
1.162.2.6  skrll    1206:                dev->ud_bus->ub_usepolling--;
1.133     jmcneill 1207:
                   1208:        /* Kick the host controller when switching modes */
1.162.2.6  skrll    1209:        mutex_enter(dev->ud_bus->ub_lock);
                   1210:        dev->ud_bus->ub_methods->ubm_softint(dev->ud_bus);
                   1211:        mutex_exit(dev->ud_bus->ub_lock);
1.6       augustss 1212: }
1.12      augustss 1213:
                   1214:
                   1215: usb_endpoint_descriptor_t *
1.162.2.1  skrll    1216: usbd_get_endpoint_descriptor(usbd_interface_handle iface, uint8_t address)
1.12      augustss 1217: {
                   1218:        struct usbd_endpoint *ep;
                   1219:        int i;
                   1220:
1.162.2.6  skrll    1221:        for (i = 0; i < iface->ui_idesc->bNumEndpoints; i++) {
                   1222:                ep = &iface->ui_endpoints[i];
                   1223:                if (ep->ue_edesc->bEndpointAddress == address)
1.162.2.9! skrll    1224:                        return iface->ui_endpoints[i].ue_edesc;
1.12      augustss 1225:        }
1.162.2.9! skrll    1226:        return NULL;
1.63      augustss 1227: }
                   1228:
                   1229: /*
                   1230:  * usbd_ratecheck() can limit the number of error messages that occurs.
                   1231:  * When a device is unplugged it may take up to 0.25s for the hub driver
                   1232:  * to notice it.  If the driver continuosly tries to do I/O operations
                   1233:  * this can generate a large number of messages.
                   1234:  */
                   1235: int
1.74      augustss 1236: usbd_ratecheck(struct timeval *last)
1.63      augustss 1237: {
1.64      augustss 1238:        static struct timeval errinterval = { 0, 250000 }; /* 0.25 s*/
1.63      augustss 1239:
1.162.2.9! skrll    1240:        return ratecheck(last, &errinterval);
1.89      augustss 1241: }
                   1242:
                   1243: /*
                   1244:  * Search for a vendor/product pair in an array.  The item size is
                   1245:  * given as an argument.
                   1246:  */
1.90      augustss 1247: const struct usb_devno *
                   1248: usb_match_device(const struct usb_devno *tbl, u_int nentries, u_int sz,
1.162.2.1  skrll    1249:                 uint16_t vendor, uint16_t product)
1.89      augustss 1250: {
                   1251:        while (nentries-- > 0) {
1.162.2.1  skrll    1252:                uint16_t tproduct = tbl->ud_product;
1.93      augustss 1253:                if (tbl->ud_vendor == vendor &&
                   1254:                    (tproduct == product || tproduct == USB_PRODUCT_ANY))
1.162.2.9! skrll    1255:                        return tbl;
1.95      augustss 1256:                tbl = (const struct usb_devno *)((const char *)tbl + sz);
1.89      augustss 1257:        }
1.162.2.9! skrll    1258:        return NULL;
1.12      augustss 1259: }
                   1260:
1.105     augustss 1261:
                   1262: void
                   1263: usb_desc_iter_init(usbd_device_handle dev, usbd_desc_iter_t *iter)
                   1264: {
                   1265:        const usb_config_descriptor_t *cd = usbd_get_config_descriptor(dev);
                   1266:
1.162.2.2  skrll    1267:        iter->cur = (const uByte *)cd;
                   1268:        iter->end = (const uByte *)cd + UGETW(cd->wTotalLength);
1.105     augustss 1269: }
                   1270:
                   1271: const usb_descriptor_t *
                   1272: usb_desc_iter_next(usbd_desc_iter_t *iter)
                   1273: {
                   1274:        const usb_descriptor_t *desc;
                   1275:
                   1276:        if (iter->cur + sizeof(usb_descriptor_t) >= iter->end) {
                   1277:                if (iter->cur != iter->end)
                   1278:                        printf("usb_desc_iter_next: bad descriptor\n");
                   1279:                return NULL;
                   1280:        }
1.108     christos 1281:        desc = (const usb_descriptor_t *)iter->cur;
1.105     augustss 1282:        if (desc->bLength == 0) {
                   1283:                printf("usb_desc_iter_next: descriptor length = 0\n");
                   1284:                return NULL;
                   1285:        }
                   1286:        iter->cur += desc->bLength;
                   1287:        if (iter->cur > iter->end) {
                   1288:                printf("usb_desc_iter_next: descriptor length too large\n");
                   1289:                return NULL;
                   1290:        }
                   1291:        return desc;
                   1292: }
                   1293:
                   1294: usbd_status
                   1295: usbd_get_string(usbd_device_handle dev, int si, char *buf)
                   1296: {
1.115     pavel    1297:        return usbd_get_string0(dev, si, buf, 1);
                   1298: }
                   1299:
                   1300: usbd_status
                   1301: usbd_get_string0(usbd_device_handle dev, int si, char *buf, int unicode)
                   1302: {
1.162.2.6  skrll    1303:        int swap = dev->ud_quirks->uq_flags & UQ_SWAP_UNICODE;
1.105     augustss 1304:        usb_string_descriptor_t us;
                   1305:        char *s;
1.116     macallan 1306:        int i, n;
1.162.2.1  skrll    1307:        uint16_t c;
1.105     augustss 1308:        usbd_status err;
                   1309:        int size;
                   1310:
1.162     skrll    1311:        USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
                   1312:
1.105     augustss 1313:        buf[0] = '\0';
                   1314:        if (si == 0)
1.162.2.9! skrll    1315:                return USBD_INVAL;
1.162.2.6  skrll    1316:        if (dev->ud_quirks->uq_flags & UQ_NO_STRINGS)
1.162.2.9! skrll    1317:                return USBD_STALLED;
1.162.2.6  skrll    1318:        if (dev->ud_langid == USBD_NOLANG) {
1.105     augustss 1319:                /* Set up default language */
                   1320:                err = usbd_get_string_desc(dev, USB_LANGUAGE_TABLE, 0, &us,
                   1321:                    &size);
                   1322:                if (err || size < 4) {
1.162     skrll    1323:                        USBHIST_LOG(usbdebug, "getting lang failed, using 0",
                   1324:                            0, 0, 0, 0);
1.162.2.6  skrll    1325:                        dev->ud_langid = 0; /* Well, just pick something then */
1.105     augustss 1326:                } else {
                   1327:                        /* Pick the first language as the default. */
1.162.2.6  skrll    1328:                        dev->ud_langid = UGETW(us.bString[0]);
1.105     augustss 1329:                }
                   1330:        }
1.162.2.6  skrll    1331:        err = usbd_get_string_desc(dev, si, dev->ud_langid, &us, &size);
1.105     augustss 1332:        if (err)
1.162.2.9! skrll    1333:                return err;
1.105     augustss 1334:        s = buf;
                   1335:        n = size / 2 - 1;
1.115     pavel    1336:        if (unicode) {
                   1337:                for (i = 0; i < n; i++) {
                   1338:                        c = UGETW(us.bString[i]);
                   1339:                        if (swap)
                   1340:                                c = (c >> 8) | (c << 8);
1.119     drochner 1341:                        s += wput_utf8(s, 3, c);
1.115     pavel    1342:                }
                   1343:                *s++ = 0;
                   1344:        }
                   1345: #ifdef COMPAT_30
                   1346:        else {
1.119     drochner 1347:                for (i = 0; i < n; i++) {
1.115     pavel    1348:                        c = UGETW(us.bString[i]);
                   1349:                        if (swap)
                   1350:                                c = (c >> 8) | (c << 8);
1.119     drochner 1351:                        *s++ = (c < 0x80) ? c : '?';
1.107     augustss 1352:                }
1.119     drochner 1353:                *s++ = 0;
1.105     augustss 1354:        }
1.115     pavel    1355: #endif
1.162.2.9! skrll    1356:        return USBD_NORMAL_COMPLETION;
1.105     augustss 1357: }

CVSweb <webmaster@jp.NetBSD.org>