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

1.162.2.19! skrll       1: /*     $NetBSD: usbdi.c,v 1.162.2.18 2015/03/06 14:08:39 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.19! skrll      34: __KERNEL_RCSID(0, "$NetBSD: usbdi.c,v 1.162.2.18 2015/03/06 14:08:39 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:
1.162.2.10  skrll      86:        USBHIST_LOG(usbdebug, "iface %p", 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.162.2.11  skrll     225:        void *buf = usbd_alloc_buffer(xfer, len);
                    226:        if (buf == NULL) {
1.162.2.17  skrll     227:                err = USBD_NOMEM;
1.162.2.11  skrll     228:                goto bad2;
                    229:        }
                    230:
1.60      augustss  231:        usbd_setup_xfer(xfer, ipipe, priv, buffer, len, flags,
                    232:            USBD_NO_TIMEOUT, cb);
1.162.2.6  skrll     233:        ipipe->up_intrxfer = xfer;
                    234:        ipipe->up_repeat = 1;
1.48      augustss  235:        err = usbd_transfer(xfer);
1.1       augustss  236:        *pipe = ipipe;
1.48      augustss  237:        if (err != USBD_IN_PROGRESS)
1.162.2.11  skrll     238:                goto bad3;
1.162.2.9  skrll     239:        return USBD_NORMAL_COMPLETION;
1.1       augustss  240:
1.162.2.11  skrll     241:  bad3:
1.162.2.6  skrll     242:        ipipe->up_intrxfer = NULL;
                    243:        ipipe->up_repeat = 0;
1.162.2.11  skrll     244:  bad2:
1.50      augustss  245:        usbd_free_xfer(xfer);
1.36      augustss  246:  bad1:
1.1       augustss  247:        usbd_close_pipe(ipipe);
1.162.2.9  skrll     248:        return err;
1.9       augustss  249: }
                    250:
1.1       augustss  251: usbd_status
1.74      augustss  252: usbd_close_pipe(usbd_pipe_handle pipe)
1.1       augustss  253: {
1.138     mrg       254:
1.162     skrll     255:        USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
                    256:
1.26      augustss  257: #ifdef DIAGNOSTIC
1.48      augustss  258:        if (pipe == NULL) {
1.162     skrll     259:                USBHIST_LOG(usbdebug, "pipe == NULL", 0, 0, 0, 0);
1.162.2.9  skrll     260:                return USBD_NORMAL_COMPLETION;
1.26      augustss  261:        }
                    262: #endif
                    263:
1.138     mrg       264:        usbd_lock_pipe(pipe);
1.162.2.6  skrll     265:        if (--pipe->up_refcnt != 0) {
1.138     mrg       266:                usbd_unlock_pipe(pipe);
1.162.2.9  skrll     267:                return USBD_NORMAL_COMPLETION;
1.138     mrg       268:        }
1.162.2.6  skrll     269:        if (! SIMPLEQ_EMPTY(&pipe->up_queue)) {
1.138     mrg       270:                usbd_unlock_pipe(pipe);
1.162.2.9  skrll     271:                return USBD_PENDING_REQUESTS;
1.138     mrg       272:        }
1.162.2.6  skrll     273:        LIST_REMOVE(pipe, up_next);
                    274:        pipe->up_endpoint->ue_refcnt--;
                    275:        pipe->up_methods->upm_close(pipe);
1.138     mrg       276:        usbd_unlock_pipe(pipe);
1.162.2.13  skrll     277:        if (pipe->up_intrxfer != NULL)
1.162.2.6  skrll     278:                usbd_free_xfer(pipe->up_intrxfer);
1.162.2.7  skrll     279:        kmem_free(pipe, pipe->up_dev->ud_bus->ub_pipesize);
1.162.2.9  skrll     280:        return USBD_NORMAL_COMPLETION;
1.1       augustss  281: }
                    282:
1.31      augustss  283: usbd_status
1.74      augustss  284: usbd_transfer(usbd_xfer_handle xfer)
1.1       augustss  285: {
1.162.2.6  skrll     286:        usbd_pipe_handle pipe = xfer->ux_pipe;
1.48      augustss  287:        usbd_status err;
1.120     kiyohara  288:        unsigned int size, flags;
1.16      augustss  289:
1.162     skrll     290:        USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
                    291:
                    292:        USBHIST_LOG(usbdebug,
                    293:            "xfer = %p, flags = %#x, pipe = %p, running = %d",
1.162.2.6  skrll     294:            xfer, xfer->ux_flags, pipe, pipe->up_running);
1.134     jmcneill  295:
1.28      augustss  296: #ifdef USB_DEBUG
                    297:        if (usbdebug > 5)
                    298:                usbd_dump_queue(pipe);
                    299: #endif
1.162.2.6  skrll     300:        xfer->ux_done = 0;
1.31      augustss  301:
1.162.2.6  skrll     302:        if (pipe->up_aborting) {
1.162     skrll     303:                USBHIST_LOG(usbdebug, "<- done xfer %p, aborting", xfer, 0, 0,
                    304:                    0);
1.162.2.9  skrll     305:                return USBD_CANCELLED;
1.162     skrll     306:        }
1.71      augustss  307:
1.162.2.11  skrll     308:        KASSERT(xfer->ux_length == 0 || xfer->ux_buf != NULL);
1.162.2.5  skrll     309:
1.162.2.6  skrll     310:        size = xfer->ux_length;
                    311:        flags = xfer->ux_flags;
1.162.2.5  skrll     312:
1.162.2.11  skrll     313:        struct usbd_bus *bus = pipe->up_dev->ud_bus;
1.37      augustss  314:
1.162.2.6  skrll     315:        if (bus->ub_usedma) {
1.162.2.5  skrll     316:                /*
                    317:                 * Copy data if not using the xfer buffer.  isoc transfers
                    318:                 * always use DMA buffer, i.e. buffer == NULL
                    319:                 */
1.162.2.6  skrll     320:                if (xfer->ux_buffer == NULL) {
                    321:                        xfer->ux_buffer = xfer->ux_buf;
                    322:                } else if (xfer->ux_buffer != xfer->ux_buf) {
                    323:                        memcpy(xfer->ux_buf, xfer->ux_buffer, size);
1.162.2.5  skrll     324:                }
                    325:        } else {
1.162.2.6  skrll     326:                xfer->ux_buffer = xfer->ux_buf;
1.162.2.5  skrll     327:        }
1.37      augustss  328:
1.120     kiyohara  329:        /* xfer is not valid after the transfer method unless synchronous */
1.162.2.6  skrll     330:        err = pipe->up_methods->upm_transfer(xfer);
1.162     skrll     331:        USBHIST_LOG(usbdebug, "<- done transfer %p, err = %d", xfer, err, 0, 0);
1.37      augustss  332:
1.162     skrll     333:        if (!(flags & USBD_SYNCHRONOUS)) {
                    334:                USBHIST_LOG(usbdebug, "<- done xfer %p, not sync", xfer, 0, 0,
                    335:                    0);
1.162.2.9  skrll     336:                return err;
1.162     skrll     337:        }
1.31      augustss  338:
                    339:        /* Sync transfer, wait for completion. */
1.162     skrll     340:        if (err != USBD_IN_PROGRESS) {
1.162.2.14  skrll     341:                USBHIST_LOG(usbdebug, "<- done xfer %p, err %d (complete/error)", xfer,
1.162.2.15  skrll     342:                    err, 0, 0);
1.162.2.9  skrll     343:                return err;
1.162     skrll     344:        }
1.138     mrg       345:        usbd_lock_pipe(pipe);
1.162.2.6  skrll     346:        while (!xfer->ux_done) {
                    347:                if (pipe->up_dev->ud_bus->ub_usepolling)
1.103     provos    348:                        panic("usbd_transfer: not done");
1.162     skrll     349:                USBHIST_LOG(usbdebug, "<- sleeping on xfer %p", xfer, 0, 0, 0);
1.138     mrg       350:
1.144     christos  351:                err = 0;
1.138     mrg       352:                if ((flags & USBD_SYNCHRONOUS_SIG) != 0) {
1.162.2.6  skrll     353:                        err = cv_wait_sig(&xfer->ux_cv, pipe->up_dev->ud_bus->ub_lock);
1.138     mrg       354:                } else {
1.162.2.6  skrll     355:                        cv_wait(&xfer->ux_cv, pipe->up_dev->ud_bus->ub_lock);
1.138     mrg       356:                }
1.154     aymeric   357:                if (err) {
1.162.2.6  skrll     358:                        if (!xfer->ux_done)
                    359:                                pipe->up_methods->upm_abort(xfer);
1.144     christos  360:                        break;
1.154     aymeric   361:                }
1.31      augustss  362:        }
1.138     mrg       363:        usbd_unlock_pipe(pipe);
1.162.2.9  skrll     364:        return xfer->ux_status;
1.31      augustss  365: }
                    366:
                    367: /* Like usbd_transfer(), but waits for completion. */
                    368: usbd_status
1.74      augustss  369: usbd_sync_transfer(usbd_xfer_handle xfer)
1.31      augustss  370: {
1.162.2.6  skrll     371:        xfer->ux_flags |= USBD_SYNCHRONOUS;
1.162.2.9  skrll     372:        return usbd_transfer(xfer);
1.16      augustss  373: }
                    374:
1.138     mrg       375: /* Like usbd_transfer(), but waits for completion and listens for signals. */
                    376: usbd_status
                    377: usbd_sync_transfer_sig(usbd_xfer_handle xfer)
                    378: {
1.162.2.6  skrll     379:        xfer->ux_flags |= USBD_SYNCHRONOUS | USBD_SYNCHRONOUS_SIG;
1.162.2.9  skrll     380:        return usbd_transfer(xfer);
1.138     mrg       381: }
                    382:
1.36      augustss  383: void *
1.162.2.1  skrll     384: usbd_alloc_buffer(usbd_xfer_handle xfer, uint32_t size)
1.36      augustss  385: {
1.162.2.5  skrll     386:
1.162.2.6  skrll     387:        KASSERT(xfer->ux_buf == NULL);
1.162.2.5  skrll     388:        KASSERT(size != 0);
                    389:
1.162.2.6  skrll     390:        xfer->ux_bufsize = 0;
1.162.2.5  skrll     391: #if NUSB_DMA > 0
1.162.2.6  skrll     392:        struct usbd_bus *bus = xfer->ux_dev->ud_bus;
1.37      augustss  393:
1.162.2.6  skrll     394:        if (bus->ub_usedma) {
                    395:                usb_dma_t *dmap = &xfer->ux_dmabuf;
1.162.2.5  skrll     396:
1.162.2.6  skrll     397:                int err = usb_allocmem_flags(bus, size, 0, dmap, bus->ub_dmaflags);
1.162.2.5  skrll     398:                if (err) {
                    399:                        return NULL;
                    400:                }
1.162.2.6  skrll     401:                xfer->ux_buf = KERNADDR(&xfer->ux_dmabuf, 0);
                    402:                xfer->ux_bufsize = size;
1.162.2.5  skrll     403:
1.162.2.6  skrll     404:                return xfer->ux_buf;
1.162.2.5  skrll     405:        }
1.92      augustss  406: #endif
1.162.2.6  skrll     407:        KASSERT(xfer->ux_dev->ud_bus->ub_usedma == false);
                    408:        xfer->ux_buf = kmem_alloc(size, KM_SLEEP);
1.162.2.5  skrll     409:
1.162.2.6  skrll     410:        if (xfer->ux_buf != NULL) {
                    411:                xfer->ux_bufsize = size;
1.162.2.5  skrll     412:        }
                    413:
1.162.2.6  skrll     414:        return xfer->ux_buf;
1.36      augustss  415: }
                    416:
                    417: void
1.74      augustss  418: usbd_free_buffer(usbd_xfer_handle xfer)
1.36      augustss  419: {
1.162.2.6  skrll     420:        KASSERT(xfer->ux_buf != NULL);
                    421:        KASSERT(xfer->ux_bufsize != 0);
1.162.2.5  skrll     422:
1.162.2.6  skrll     423:        void *buf = xfer->ux_buf;
                    424:        uint32_t size = xfer->ux_bufsize;
1.162.2.5  skrll     425:
1.162.2.6  skrll     426:        xfer->ux_buf = NULL;
                    427:        xfer->ux_bufsize = 0;
1.162.2.5  skrll     428:
                    429: #if NUSB_DMA > 0
1.162.2.6  skrll     430:        struct usbd_bus *bus = xfer->ux_dev->ud_bus;
1.162.2.5  skrll     431:
1.162.2.6  skrll     432:        if (bus->ub_usedma) {
                    433:                usb_dma_t *dmap = &xfer->ux_dmabuf;
1.162.2.5  skrll     434:
                    435:                usb_freemem(bus, dmap);
1.37      augustss  436:                return;
                    437:        }
                    438: #endif
1.162.2.6  skrll     439:        KASSERT(xfer->ux_dev->ud_bus->ub_usedma == false);
1.162.2.5  skrll     440:
                    441:        kmem_free(buf, size);
1.36      augustss  442: }
                    443:
1.38      augustss  444: void *
1.74      augustss  445: usbd_get_buffer(usbd_xfer_handle xfer)
1.38      augustss  446: {
1.162.2.5  skrll     447:
1.162.2.6  skrll     448:        return xfer->ux_buf;
1.38      augustss  449: }
                    450:
1.102     augustss  451: usbd_xfer_handle
1.74      augustss  452: usbd_alloc_xfer(usbd_device_handle dev)
1.1       augustss  453: {
1.48      augustss  454:        usbd_xfer_handle xfer;
1.1       augustss  455:
1.162     skrll     456:        USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
                    457:
1.162.2.3  skrll     458:        ASSERT_SLEEPABLE();
                    459:
1.162.2.6  skrll     460:        xfer = dev->ud_bus->ub_methods->ubm_allocx(dev->ud_bus);
1.48      augustss  461:        if (xfer == NULL)
1.162.2.9  skrll     462:                return NULL;
1.162.2.6  skrll     463:        xfer->ux_dev = dev;
                    464:        callout_init(&xfer->ux_callout, CALLOUT_MPSAFE);
                    465:        cv_init(&xfer->ux_cv, "usbxfer");
                    466:        cv_init(&xfer->ux_hccv, "usbhcxfer");
1.162     skrll     467:
                    468:        USBHIST_LOG(usbdebug, "returns %p", xfer, 0, 0, 0);
                    469:
1.162.2.9  skrll     470:        return xfer;
1.1       augustss  471: }
                    472:
1.102     augustss  473: usbd_status
1.74      augustss  474: usbd_free_xfer(usbd_xfer_handle xfer)
1.1       augustss  475: {
1.162     skrll     476:        USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
                    477:
                    478:        USBHIST_LOG(usbdebug, "%p", xfer, 0, 0, 0);
1.162.2.6  skrll     479:        if (xfer->ux_buf) {
1.48      augustss  480:                usbd_free_buffer(xfer);
1.162.2.5  skrll     481:        }
1.123     drochner  482: #if defined(DIAGNOSTIC)
1.162.2.6  skrll     483:        if (callout_pending(&xfer->ux_callout)) {
                    484:                callout_stop(&xfer->ux_callout);
1.140     skrll     485:                printf("usbd_free_xfer: timeout_handle pending\n");
1.68      augustss  486:        }
1.66      thorpej   487: #endif
1.162.2.6  skrll     488:        cv_destroy(&xfer->ux_cv);
                    489:        cv_destroy(&xfer->ux_hccv);
                    490:        xfer->ux_dev->ud_bus->ub_methods->ubm_freex(xfer->ux_dev->ud_bus, xfer);
1.162.2.9  skrll     491:        return USBD_NORMAL_COMPLETION;
1.1       augustss  492: }
                    493:
1.36      augustss  494: void
1.74      augustss  495: usbd_setup_xfer(usbd_xfer_handle xfer, usbd_pipe_handle pipe,
1.162.2.1  skrll     496:                usbd_private_handle priv, void *buffer, uint32_t length,
                    497:                uint16_t flags, uint32_t timeout,
1.74      augustss  498:                usbd_callback callback)
1.1       augustss  499: {
1.162.2.6  skrll     500:        xfer->ux_pipe = pipe;
                    501:        xfer->ux_priv = priv;
                    502:        xfer->ux_buffer = buffer;
                    503:        xfer->ux_length = length;
                    504:        xfer->ux_actlen = 0;
                    505:        xfer->ux_flags = flags;
                    506:        xfer->ux_timeout = timeout;
                    507:        xfer->ux_status = USBD_NOT_STARTED;
                    508:        xfer->ux_callback = callback;
                    509:        xfer->ux_rqflags &= ~URQ_REQUEST;
                    510:        xfer->ux_nframes = 0;
1.1       augustss  511: }
                    512:
1.36      augustss  513: void
1.74      augustss  514: usbd_setup_default_xfer(usbd_xfer_handle xfer, usbd_device_handle dev,
1.162.2.1  skrll     515:                        usbd_private_handle priv, uint32_t timeout,
1.74      augustss  516:                        usb_device_request_t *req, void *buffer,
1.162.2.1  skrll     517:                        uint32_t length, uint16_t flags,
1.74      augustss  518:                        usbd_callback callback)
1.1       augustss  519: {
1.162.2.6  skrll     520:        xfer->ux_pipe = dev->ud_pipe0;
                    521:        xfer->ux_priv = priv;
                    522:        xfer->ux_buffer = buffer;
                    523:        xfer->ux_length = length;
                    524:        xfer->ux_actlen = 0;
                    525:        xfer->ux_flags = flags;
                    526:        xfer->ux_timeout = timeout;
                    527:        xfer->ux_status = USBD_NOT_STARTED;
                    528:        xfer->ux_callback = callback;
                    529:        xfer->ux_request = *req;
                    530:        xfer->ux_rqflags |= URQ_REQUEST;
                    531:        xfer->ux_nframes = 0;
1.36      augustss  532: }
                    533:
                    534: void
1.74      augustss  535: usbd_setup_isoc_xfer(usbd_xfer_handle xfer, usbd_pipe_handle pipe,
1.162.2.1  skrll     536:                     usbd_private_handle priv, uint16_t *frlengths,
                    537:                     uint32_t nframes, uint16_t flags, usbd_callback callback)
1.36      augustss  538: {
1.162.2.6  skrll     539:        xfer->ux_pipe = pipe;
                    540:        xfer->ux_priv = priv;
                    541:        xfer->ux_buffer = 0;
                    542:        xfer->ux_length = 0;
                    543:        xfer->ux_actlen = 0;
                    544:        xfer->ux_flags = flags;
                    545:        xfer->ux_timeout = USBD_NO_TIMEOUT;
                    546:        xfer->ux_status = USBD_NOT_STARTED;
                    547:        xfer->ux_callback = callback;
                    548:        xfer->ux_rqflags &= ~URQ_REQUEST;
                    549:        xfer->ux_frlengths = frlengths;
                    550:        xfer->ux_nframes = nframes;
1.1       augustss  551: }
                    552:
1.31      augustss  553: void
1.74      augustss  554: usbd_get_xfer_status(usbd_xfer_handle xfer, usbd_private_handle *priv,
1.162.2.1  skrll     555:                     void **buffer, uint32_t *count, usbd_status *status)
1.1       augustss  556: {
1.48      augustss  557:        if (priv != NULL)
1.162.2.6  skrll     558:                *priv = xfer->ux_priv;
1.48      augustss  559:        if (buffer != NULL)
1.162.2.6  skrll     560:                *buffer = xfer->ux_buffer;
1.48      augustss  561:        if (count != NULL)
1.162.2.6  skrll     562:                *count = xfer->ux_actlen;
1.48      augustss  563:        if (status != NULL)
1.162.2.6  skrll     564:                *status = xfer->ux_status;
1.1       augustss  565: }
                    566:
                    567: usb_config_descriptor_t *
1.74      augustss  568: usbd_get_config_descriptor(usbd_device_handle dev)
1.1       augustss  569: {
1.53      augustss  570: #ifdef DIAGNOSTIC
                    571:        if (dev == NULL) {
                    572:                printf("usbd_get_config_descriptor: dev == NULL\n");
1.162.2.9  skrll     573:                return NULL;
1.53      augustss  574:        }
                    575: #endif
1.162.2.9  skrll     576:        return dev->ud_cdesc;
1.1       augustss  577: }
                    578:
                    579: usb_interface_descriptor_t *
1.74      augustss  580: usbd_get_interface_descriptor(usbd_interface_handle iface)
1.1       augustss  581: {
1.53      augustss  582: #ifdef DIAGNOSTIC
                    583:        if (iface == NULL) {
                    584:                printf("usbd_get_interface_descriptor: dev == NULL\n");
1.162.2.9  skrll     585:                return NULL;
1.53      augustss  586:        }
                    587: #endif
1.162.2.9  skrll     588:        return iface->ui_idesc;
1.1       augustss  589: }
                    590:
                    591: usb_device_descriptor_t *
1.74      augustss  592: usbd_get_device_descriptor(usbd_device_handle dev)
1.1       augustss  593: {
1.162.2.9  skrll     594:        return &dev->ud_ddesc;
1.1       augustss  595: }
                    596:
                    597: usb_endpoint_descriptor_t *
1.162.2.1  skrll     598: usbd_interface2endpoint_descriptor(usbd_interface_handle iface, uint8_t index)
1.1       augustss  599: {
1.162.2.6  skrll     600:        if (index >= iface->ui_idesc->bNumEndpoints)
1.162.2.9  skrll     601:                return NULL;
                    602:        return iface->ui_endpoints[index].ue_edesc;
1.1       augustss  603: }
                    604:
1.125     jmorse    605: /* Some drivers may wish to abort requests on the default pipe, *
                    606:  * but there is no mechanism for getting a handle on it.        */
                    607: usbd_status
                    608: usbd_abort_default_pipe(struct usbd_device *device)
                    609: {
                    610:
1.162.2.6  skrll     611:        return usbd_abort_pipe(device->ud_pipe0);
1.125     jmorse    612: }
                    613:
1.102     augustss  614: usbd_status
1.74      augustss  615: usbd_abort_pipe(usbd_pipe_handle pipe)
1.1       augustss  616: {
1.48      augustss  617:        usbd_status err;
1.1       augustss  618:
1.26      augustss  619: #ifdef DIAGNOSTIC
1.48      augustss  620:        if (pipe == NULL) {
1.126     uebayasi  621:                printf("usbd_abort_pipe: pipe==NULL\n");
1.162.2.9  skrll     622:                return USBD_NORMAL_COMPLETION;
1.26      augustss  623:        }
                    624: #endif
1.138     mrg       625:        usbd_lock_pipe(pipe);
1.48      augustss  626:        err = usbd_ar_pipe(pipe);
1.138     mrg       627:        usbd_unlock_pipe(pipe);
1.162.2.9  skrll     628:        return err;
1.1       augustss  629: }
1.102     augustss  630:
                    631: usbd_status
1.74      augustss  632: usbd_clear_endpoint_stall(usbd_pipe_handle pipe)
1.1       augustss  633: {
1.162.2.6  skrll     634:        usbd_device_handle dev = pipe->up_dev;
1.1       augustss  635:        usb_device_request_t req;
1.48      augustss  636:        usbd_status err;
1.1       augustss  637:
1.162     skrll     638:        USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
1.33      augustss  639:
1.102     augustss  640:        /*
1.87      augustss  641:         * Clearing en endpoint stall resets the endpoint toggle, so
1.33      augustss  642:         * do the same to the HC toggle.
                    643:         */
1.162.2.6  skrll     644:        pipe->up_methods->upm_cleartoggle(pipe);
1.33      augustss  645:
1.1       augustss  646:        req.bmRequestType = UT_WRITE_ENDPOINT;
                    647:        req.bRequest = UR_CLEAR_FEATURE;
1.15      augustss  648:        USETW(req.wValue, UF_ENDPOINT_HALT);
1.162.2.6  skrll     649:        USETW(req.wIndex, pipe->up_endpoint->ue_edesc->bEndpointAddress);
1.1       augustss  650:        USETW(req.wLength, 0);
1.48      augustss  651:        err = usbd_do_request(dev, &req, 0);
1.1       augustss  652: #if 0
                    653: XXX should we do this?
1.51      augustss  654:        if (!err) {
1.1       augustss  655:                pipe->state = USBD_PIPE_ACTIVE;
                    656:                /* XXX activate pipe */
                    657:        }
                    658: #endif
1.162.2.9  skrll     659:        return err;
1.1       augustss  660: }
                    661:
1.139     mrg       662: void
1.156     skrll     663: usbd_clear_endpoint_stall_task(void *arg)
1.7       augustss  664: {
1.139     mrg       665:        usbd_pipe_handle pipe = arg;
1.162.2.6  skrll     666:        usbd_device_handle dev = pipe->up_dev;
1.7       augustss  667:        usb_device_request_t req;
                    668:
1.162.2.6  skrll     669:        pipe->up_methods->upm_cleartoggle(pipe);
1.33      augustss  670:
1.7       augustss  671:        req.bmRequestType = UT_WRITE_ENDPOINT;
                    672:        req.bRequest = UR_CLEAR_FEATURE;
1.15      augustss  673:        USETW(req.wValue, UF_ENDPOINT_HALT);
1.162.2.6  skrll     674:        USETW(req.wIndex, pipe->up_endpoint->ue_edesc->bEndpointAddress);
1.7       augustss  675:        USETW(req.wLength, 0);
1.156     skrll     676:        (void)usbd_do_request(dev, &req, 0);
1.139     mrg       677: }
                    678:
                    679: void
                    680: usbd_clear_endpoint_stall_async(usbd_pipe_handle pipe)
                    681: {
                    682:
1.162.2.6  skrll     683:        usb_add_task(pipe->up_dev, &pipe->up_async_task, USB_TASKQ_DRIVER);
1.7       augustss  684: }
                    685:
1.61      augustss  686: void
1.74      augustss  687: usbd_clear_endpoint_toggle(usbd_pipe_handle pipe)
1.61      augustss  688: {
1.162.2.6  skrll     689:        pipe->up_methods->upm_cleartoggle(pipe);
1.61      augustss  690: }
                    691:
1.102     augustss  692: usbd_status
1.162.2.1  skrll     693: usbd_endpoint_count(usbd_interface_handle iface, uint8_t *count)
1.1       augustss  694: {
1.73      augustss  695: #ifdef DIAGNOSTIC
1.162.2.6  skrll     696:        if (iface == NULL || iface->ui_idesc == NULL) {
1.73      augustss  697:                printf("usbd_endpoint_count: NULL pointer\n");
1.162.2.9  skrll     698:                return USBD_INVAL;
1.73      augustss  699:        }
                    700: #endif
1.162.2.6  skrll     701:        *count = iface->ui_idesc->bNumEndpoints;
1.162.2.9  skrll     702:        return USBD_NORMAL_COMPLETION;
1.1       augustss  703: }
                    704:
1.102     augustss  705: usbd_status
1.162.2.1  skrll     706: usbd_interface_count(usbd_device_handle dev, uint8_t *count)
1.1       augustss  707: {
1.162.2.6  skrll     708:        if (dev->ud_cdesc == NULL)
1.162.2.9  skrll     709:                return USBD_NOT_CONFIGURED;
1.162.2.6  skrll     710:        *count = dev->ud_cdesc->bNumInterface;
1.162.2.9  skrll     711:        return USBD_NORMAL_COMPLETION;
1.1       augustss  712: }
                    713:
1.85      augustss  714: void
1.74      augustss  715: usbd_interface2device_handle(usbd_interface_handle iface,
                    716:                             usbd_device_handle *dev)
1.1       augustss  717: {
1.162.2.6  skrll     718:        *dev = iface->ui_dev;
1.1       augustss  719: }
                    720:
1.102     augustss  721: usbd_status
1.74      augustss  722: usbd_device2interface_handle(usbd_device_handle dev,
1.162.2.1  skrll     723:                             uint8_t ifaceno, usbd_interface_handle *iface)
1.1       augustss  724: {
1.162.2.6  skrll     725:        if (dev->ud_cdesc == NULL)
1.162.2.9  skrll     726:                return USBD_NOT_CONFIGURED;
1.162.2.6  skrll     727:        if (ifaceno >= dev->ud_cdesc->bNumInterface)
1.162.2.9  skrll     728:                return USBD_INVAL;
1.162.2.6  skrll     729:        *iface = &dev->ud_ifaces[ifaceno];
1.162.2.9  skrll     730:        return USBD_NORMAL_COMPLETION;
1.1       augustss  731: }
                    732:
1.36      augustss  733: usbd_device_handle
1.74      augustss  734: usbd_pipe2device_handle(usbd_pipe_handle pipe)
1.36      augustss  735: {
1.162.2.9  skrll     736:        return pipe->up_dev;
1.36      augustss  737: }
                    738:
1.13      augustss  739: /* XXXX use altno */
1.3       augustss  740: usbd_status
1.74      augustss  741: usbd_set_interface(usbd_interface_handle iface, int altidx)
1.3       augustss  742: {
                    743:        usb_device_request_t req;
1.48      augustss  744:        usbd_status err;
1.73      augustss  745:        void *endpoints;
1.13      augustss  746:
1.162.2.6  skrll     747:        if (LIST_FIRST(&iface->ui_pipes) != 0)
1.162.2.9  skrll     748:                return USBD_IN_USE;
1.13      augustss  749:
1.162.2.6  skrll     750:        endpoints = iface->ui_endpoints;
1.162.2.19! skrll     751:        int nendpt = iface->ui_idesc->bNumEndpoints;
1.162.2.6  skrll     752:        err = usbd_fill_iface_data(iface->ui_dev, iface->ui_index, altidx);
1.48      augustss  753:        if (err)
1.162.2.9  skrll     754:                return err;
1.73      augustss  755:
1.76      augustss  756:        /* new setting works, we can free old endpoints */
1.162.2.7  skrll     757:        if (endpoints != NULL) {
                    758:                kmem_free(endpoints, nendpt * sizeof(struct usbd_endpoint));
                    759:        }
1.73      augustss  760:
                    761: #ifdef DIAGNOSTIC
1.162.2.6  skrll     762:        if (iface->ui_idesc == NULL) {
1.73      augustss  763:                printf("usbd_set_interface: NULL pointer\n");
1.162.2.9  skrll     764:                return USBD_INVAL;
1.73      augustss  765:        }
                    766: #endif
1.3       augustss  767:
                    768:        req.bmRequestType = UT_WRITE_INTERFACE;
                    769:        req.bRequest = UR_SET_INTERFACE;
1.162.2.6  skrll     770:        USETW(req.wValue, iface->ui_idesc->bAlternateSetting);
                    771:        USETW(req.wIndex, iface->ui_idesc->bInterfaceNumber);
1.3       augustss  772:        USETW(req.wLength, 0);
1.162.2.9  skrll     773:        return usbd_do_request(iface->ui_dev, &req, 0);
1.12      augustss  774: }
                    775:
                    776: int
1.74      augustss  777: usbd_get_no_alts(usb_config_descriptor_t *cdesc, int ifaceno)
1.12      augustss  778: {
1.13      augustss  779:        char *p = (char *)cdesc;
                    780:        char *end = p + UGETW(cdesc->wTotalLength);
1.12      augustss  781:        usb_interface_descriptor_t *d;
                    782:        int n;
                    783:
                    784:        for (n = 0; p < end; p += d->bLength) {
                    785:                d = (usb_interface_descriptor_t *)p;
1.102     augustss  786:                if (p + d->bLength <= end &&
1.12      augustss  787:                    d->bDescriptorType == UDESC_INTERFACE &&
1.13      augustss  788:                    d->bInterfaceNumber == ifaceno)
1.12      augustss  789:                        n++;
                    790:        }
1.162.2.9  skrll     791:        return n;
1.13      augustss  792: }
                    793:
                    794: int
1.74      augustss  795: usbd_get_interface_altindex(usbd_interface_handle iface)
1.13      augustss  796: {
1.162.2.9  skrll     797:        return iface->ui_altindex;
1.12      augustss  798: }
                    799:
                    800: usbd_status
1.162.2.1  skrll     801: usbd_get_interface(usbd_interface_handle iface, uint8_t *aiface)
1.12      augustss  802: {
                    803:        usb_device_request_t req;
                    804:
                    805:        req.bmRequestType = UT_READ_INTERFACE;
                    806:        req.bRequest = UR_GET_INTERFACE;
                    807:        USETW(req.wValue, 0);
1.162.2.6  skrll     808:        USETW(req.wIndex, iface->ui_idesc->bInterfaceNumber);
1.12      augustss  809:        USETW(req.wLength, 1);
1.162.2.9  skrll     810:        return usbd_do_request(iface->ui_dev, &req, aiface);
1.3       augustss  811: }
1.1       augustss  812:
                    813: /*** Internal routines ***/
                    814:
                    815: /* Dequeue all pipe operations, called at splusb(). */
1.69      augustss  816: Static usbd_status
1.74      augustss  817: usbd_ar_pipe(usbd_pipe_handle pipe)
1.1       augustss  818: {
1.48      augustss  819:        usbd_xfer_handle xfer;
1.1       augustss  820:
1.162     skrll     821:        USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
                    822:
1.162.2.6  skrll     823:        KASSERT(mutex_owned(pipe->up_dev->ud_bus->ub_lock));
1.138     mrg       824:
1.162     skrll     825:        USBHIST_LOG(usbdebug, "pipe = %p", pipe, 0, 0, 0);
1.28      augustss  826: #ifdef USB_DEBUG
                    827:        if (usbdebug > 5)
                    828:                usbd_dump_queue(pipe);
                    829: #endif
1.162.2.6  skrll     830:        pipe->up_repeat = 0;
                    831:        pipe->up_aborting = 1;
                    832:        while ((xfer = SIMPLEQ_FIRST(&pipe->up_queue)) != NULL) {
1.162     skrll     833:                USBHIST_LOG(usbdebug, "pipe = %p xfer = %p (methods = %p)",
1.162.2.6  skrll     834:                    pipe, xfer, pipe->up_methods, 0);
1.28      augustss  835:                /* Make the HC abort it (and invoke the callback). */
1.162.2.6  skrll     836:                pipe->up_methods->upm_abort(xfer);
1.33      augustss  837:                /* XXX only for non-0 usbd_clear_endpoint_stall(pipe); */
1.20      augustss  838:        }
1.162.2.6  skrll     839:        pipe->up_aborting = 0;
1.162.2.9  skrll     840:        return USBD_NORMAL_COMPLETION;
1.1       augustss  841: }
                    842:
1.138     mrg       843: /* Called with USB lock held. */
1.31      augustss  844: void
1.74      augustss  845: usb_transfer_complete(usbd_xfer_handle xfer)
1.1       augustss  846: {
1.162.2.6  skrll     847:        usbd_pipe_handle pipe = xfer->ux_pipe;
                    848:        struct usbd_bus *bus = pipe->up_dev->ud_bus;
                    849:        int sync = xfer->ux_flags & USBD_SYNCHRONOUS;
                    850:        int erred = xfer->ux_status == USBD_CANCELLED ||
                    851:            xfer->ux_status == USBD_TIMEOUT;
                    852:        int polling = bus->ub_usepolling;
1.152     skrll     853:        int repeat;
1.31      augustss  854:
1.162     skrll     855:        USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
                    856:
                    857:        USBHIST_LOG(usbdebug, "pipe = %p xfer = %p status = %d actlen = %d",
1.162.2.6  skrll     858:                pipe, xfer, xfer->ux_status, xfer->ux_actlen);
1.134     jmcneill  859:
1.162.2.6  skrll     860:        KASSERT(polling || mutex_owned(pipe->up_dev->ud_bus->ub_lock));
1.134     jmcneill  861:
1.93      augustss  862: #ifdef DIAGNOSTIC
1.162.2.6  skrll     863:        if (xfer->ux_state != XFER_ONQU) {
1.147     skrll     864:                printf("usb_transfer_complete: xfer=%p not queued 0x%08x\n",
1.162.2.6  skrll     865:                       xfer, xfer->ux_state);
1.93      augustss  866:        }
                    867: #endif
1.5       augustss  868:
1.23      augustss  869: #ifdef DIAGNOSTIC
1.48      augustss  870:        if (pipe == NULL) {
1.138     mrg       871:                printf("usb_transfer_complete: pipe==0, xfer=%p\n", xfer);
1.31      augustss  872:                return;
                    873:        }
1.23      augustss  874: #endif
1.162.2.6  skrll     875:        repeat = pipe->up_repeat;
1.31      augustss  876:        /* XXXX */
                    877:        if (polling)
1.162.2.6  skrll     878:                pipe->up_running = 0;
1.31      augustss  879:
1.162.2.6  skrll     880:        if (xfer->ux_buffer != xfer->ux_buf) {
1.162.2.5  skrll     881:                /* can only be different for DMA busses */
1.162.2.6  skrll     882:                KASSERT(bus->ub_usedma);
                    883:                KDASSERTMSG(xfer->ux_actlen <= xfer->ux_length,
                    884:                    "actlen %d length %d",xfer->ux_actlen, xfer->ux_length);
1.162.2.5  skrll     885:
1.162.2.6  skrll     886:                memcpy(xfer->ux_buffer, xfer->ux_buf, xfer->ux_actlen);
1.43      augustss  887:        }
1.38      augustss  888:
1.37      augustss  889:
1.47      augustss  890:        if (!repeat) {
                    891:                /* Remove request from queue. */
1.153     jakllsch  892:
1.162.2.6  skrll     893:                KASSERTMSG(!SIMPLEQ_EMPTY(&pipe->up_queue),
1.145     skrll     894:                    "pipe %p is empty, but xfer %p wants to complete", pipe,
                    895:                     xfer);
1.47      augustss  896: #ifdef DIAGNOSTIC
1.162.2.6  skrll     897:                if (xfer != SIMPLEQ_FIRST(&pipe->up_queue))
1.145     skrll     898:                        printf("%s: bad dequeue %p != %p\n", __func__,
1.162.2.6  skrll     899:                               xfer, SIMPLEQ_FIRST(&pipe->up_queue));
                    900:                xfer->ux_state = XFER_BUSY;
1.45      augustss  901: #endif
1.162.2.6  skrll     902:                SIMPLEQ_REMOVE_HEAD(&pipe->up_queue, ux_next);
1.47      augustss  903:        }
1.162     skrll     904:        USBHIST_LOG(usbdebug, "xfer %p: repeat %d new head = %p",
1.162.2.6  skrll     905:            xfer, repeat, SIMPLEQ_FIRST(&pipe->up_queue), 0);
1.31      augustss  906:
                    907:        /* Count completed transfers. */
1.162.2.6  skrll     908:        ++pipe->up_dev->ud_bus->ub_stats.uds_requests
                    909:                [pipe->up_endpoint->ue_edesc->bmAttributes & UE_XFERTYPE];
1.1       augustss  910:
1.162.2.6  skrll     911:        xfer->ux_done = 1;
                    912:        if (!xfer->ux_status && xfer->ux_actlen < xfer->ux_length &&
                    913:            !(xfer->ux_flags & USBD_SHORT_XFER_OK)) {
1.162     skrll     914:                USBHIST_LOG(usbdebug, "short transfer %d < %d",
1.162.2.6  skrll     915:                    xfer->ux_actlen, xfer->ux_length, 0, 0);
                    916:                xfer->ux_status = USBD_SHORT_XFER;
1.1       augustss  917:        }
1.31      augustss  918:
1.124     jmcneill  919:        if (repeat) {
1.162     skrll     920:                USBHIST_LOG(usbdebug, "xfer %p doing callback %p status %x",
1.162.2.6  skrll     921:                    xfer, xfer->ux_callback, xfer->ux_status, 0);
                    922:                if (xfer->ux_callback) {
1.158     skrll     923:                        if (!polling)
1.162.2.6  skrll     924:                                mutex_exit(pipe->up_dev->ud_bus->ub_lock);
1.148     jmcneill  925:
1.162.2.6  skrll     926:                        if (!(pipe->up_flags & USBD_MPSAFE))
1.148     jmcneill  927:                                KERNEL_LOCK(1, curlwp);
1.162.2.6  skrll     928:                        xfer->ux_callback(xfer, xfer->ux_priv, xfer->ux_status);
1.162     skrll     929:                        USBHIST_LOG(usbdebug, "xfer %p doing done %p", xfer,
1.162.2.6  skrll     930:                            pipe->up_methods->upm_done, 0, 0);
                    931:                        if (!(pipe->up_flags & USBD_MPSAFE))
1.148     jmcneill  932:                                KERNEL_UNLOCK_ONE(curlwp);
                    933:
1.158     skrll     934:                        if (!polling)
1.162.2.6  skrll     935:                                mutex_enter(pipe->up_dev->ud_bus->ub_lock);
1.138     mrg       936:                }
1.162.2.6  skrll     937:                pipe->up_methods->upm_done(xfer);
1.124     jmcneill  938:        } else {
1.162     skrll     939:                USBHIST_LOG(usbdebug, "xfer %p doing done %p", xfer,
1.162.2.6  skrll     940:                    pipe->up_methods->upm_done, 0, 0);
                    941:                pipe->up_methods->upm_done(xfer);
1.162     skrll     942:                USBHIST_LOG(usbdebug, "xfer %p doing callback %p status %x",
1.162.2.6  skrll     943:                    xfer, xfer->ux_callback, xfer->ux_status, 0);
                    944:                if (xfer->ux_callback) {
1.158     skrll     945:                        if (!polling)
1.162.2.6  skrll     946:                                mutex_exit(pipe->up_dev->ud_bus->ub_lock);
1.148     jmcneill  947:
1.162.2.6  skrll     948:                        if (!(pipe->up_flags & USBD_MPSAFE))
1.148     jmcneill  949:                                KERNEL_LOCK(1, curlwp);
1.162.2.6  skrll     950:                        xfer->ux_callback(xfer, xfer->ux_priv, xfer->ux_status);
                    951:                        if (!(pipe->up_flags & USBD_MPSAFE))
1.148     jmcneill  952:                                KERNEL_UNLOCK_ONE(curlwp);
                    953:
1.158     skrll     954:                        if (!polling)
1.162.2.6  skrll     955:                                mutex_enter(pipe->up_dev->ud_bus->ub_lock);
1.138     mrg       956:                }
1.124     jmcneill  957:        }
1.31      augustss  958:
1.138     mrg       959:        if (sync && !polling) {
1.162     skrll     960:                USBHIST_LOG(usbdebug, "<- done xfer %p, wakeup", xfer, 0, 0, 0);
1.162.2.6  skrll     961:                cv_broadcast(&xfer->ux_cv);
1.138     mrg       962:        }
1.31      augustss  963:
1.47      augustss  964:        if (!repeat) {
1.40      augustss  965:                /* XXX should we stop the queue on all errors? */
1.162.2.6  skrll     966:                if (erred && pipe->up_iface != NULL)    /* not control pipe */
                    967:                        pipe->up_running = 0;
1.40      augustss  968:                else
                    969:                        usbd_start_next(pipe);
                    970:        }
1.1       augustss  971: }
                    972:
1.138     mrg       973: /* Called with USB lock held. */
1.31      augustss  974: usbd_status
1.74      augustss  975: usb_insert_transfer(usbd_xfer_handle xfer)
1.1       augustss  976: {
1.162.2.6  skrll     977:        usbd_pipe_handle pipe = xfer->ux_pipe;
1.48      augustss  978:        usbd_status err;
1.31      augustss  979:
1.162     skrll     980:        USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
                    981:
                    982:        USBHIST_LOG(usbdebug, "pipe = %p running = %d timeout = %d",
1.162.2.6  skrll     983:            pipe, pipe->up_running, xfer->ux_timeout, 0);
1.134     jmcneill  984:
1.162.2.6  skrll     985:        KASSERT(mutex_owned(pipe->up_dev->ud_bus->ub_lock));
1.134     jmcneill  986:
1.93      augustss  987: #ifdef DIAGNOSTIC
1.162.2.6  skrll     988:        if (xfer->ux_state != XFER_BUSY) {
1.162     skrll     989:                USBHIST_LOG(usbdebug, "<- done, xfer %p not busy", xfer, 0, 0,
                    990:                    0);
1.93      augustss  991:                printf("usb_insert_transfer: xfer=%p not busy 0x%08x\n",
1.162.2.6  skrll     992:                       xfer, xfer->ux_state);
1.162.2.9  skrll     993:                return USBD_INVAL;
1.93      augustss  994:        }
1.162.2.6  skrll     995:        xfer->ux_state = XFER_ONQU;
1.93      augustss  996: #endif
1.162.2.6  skrll     997:        SIMPLEQ_INSERT_TAIL(&pipe->up_queue, xfer, ux_next);
                    998:        if (pipe->up_running)
1.48      augustss  999:                err = USBD_IN_PROGRESS;
1.37      augustss 1000:        else {
1.162.2.6  skrll    1001:                pipe->up_running = 1;
1.48      augustss 1002:                err = USBD_NORMAL_COMPLETION;
1.37      augustss 1003:        }
1.162     skrll    1004:        USBHIST_LOG(usbdebug, "<- done xfer %p, err %d", xfer, err, 0, 0);
1.162.2.9  skrll    1005:        return err;
1.1       augustss 1006: }
                   1007:
1.138     mrg      1008: /* Called with USB lock held. */
1.31      augustss 1009: void
1.74      augustss 1010: usbd_start_next(usbd_pipe_handle pipe)
1.31      augustss 1011: {
1.48      augustss 1012:        usbd_xfer_handle xfer;
                   1013:        usbd_status err;
1.40      augustss 1014:
1.162     skrll    1015:        USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
                   1016:
1.31      augustss 1017: #ifdef DIAGNOSTIC
1.48      augustss 1018:        if (pipe == NULL) {
1.51      augustss 1019:                printf("usbd_start_next: pipe == NULL\n");
1.31      augustss 1020:                return;
                   1021:        }
1.162.2.6  skrll    1022:        if (pipe->up_methods == NULL || pipe->up_methods->upm_start == NULL) {
1.51      augustss 1023:                printf("usbd_start_next: pipe=%p no start method\n", pipe);
1.31      augustss 1024:                return;
                   1025:        }
                   1026: #endif
                   1027:
1.162.2.6  skrll    1028:        KASSERT(mutex_owned(pipe->up_dev->ud_bus->ub_lock));
1.138     mrg      1029:
1.31      augustss 1030:        /* Get next request in queue. */
1.162.2.6  skrll    1031:        xfer = SIMPLEQ_FIRST(&pipe->up_queue);
1.162     skrll    1032:        USBHIST_LOG(usbdebug, "pipe = %p, xfer = %p", pipe, xfer, 0, 0);
1.51      augustss 1033:        if (xfer == NULL) {
1.162.2.6  skrll    1034:                pipe->up_running = 0;
1.51      augustss 1035:        } else {
1.162.2.6  skrll    1036:                mutex_exit(pipe->up_dev->ud_bus->ub_lock);
                   1037:                err = pipe->up_methods->upm_start(xfer);
                   1038:                mutex_enter(pipe->up_dev->ud_bus->ub_lock);
1.158     skrll    1039:
1.48      augustss 1040:                if (err != USBD_IN_PROGRESS) {
1.162     skrll    1041:                        USBHIST_LOG(usbdebug, "error = %d", err, 0, 0, 0);
1.162.2.6  skrll    1042:                        pipe->up_running = 0;
1.31      augustss 1043:                        /* XXX do what? */
                   1044:                }
1.1       augustss 1045:        }
1.138     mrg      1046:
1.162.2.6  skrll    1047:        KASSERT(mutex_owned(pipe->up_dev->ud_bus->ub_lock));
1.1       augustss 1048: }
                   1049:
                   1050: usbd_status
1.74      augustss 1051: usbd_do_request(usbd_device_handle dev, usb_device_request_t *req, void *data)
1.1       augustss 1052: {
1.99      thorpej  1053:        return (usbd_do_request_flags(dev, req, data, 0, 0,
1.98      augustss 1054:                                      USBD_DEFAULT_TIMEOUT));
1.17      augustss 1055: }
                   1056:
                   1057: usbd_status
1.74      augustss 1058: usbd_do_request_flags(usbd_device_handle dev, usb_device_request_t *req,
1.162.2.1  skrll    1059:                      void *data, uint16_t flags, int *actlen, uint32_t timo)
1.17      augustss 1060: {
1.162.2.6  skrll    1061:        return (usbd_do_request_flags_pipe(dev, dev->ud_pipe0, req,
1.96      augustss 1062:                                           data, flags, actlen, timo));
1.77      augustss 1063: }
                   1064:
                   1065: usbd_status
                   1066: usbd_do_request_flags_pipe(usbd_device_handle dev, usbd_pipe_handle pipe,
1.162.2.1  skrll    1067:        usb_device_request_t *req, void *data, uint16_t flags, int *actlen,
                   1068:        uint32_t timeout)
1.77      augustss 1069: {
1.48      augustss 1070:        usbd_xfer_handle xfer;
                   1071:        usbd_status err;
1.1       augustss 1072:
1.162     skrll    1073:        USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
                   1074:
1.162.2.3  skrll    1075:        ASSERT_SLEEPABLE();
1.7       augustss 1076:
1.50      augustss 1077:        xfer = usbd_alloc_xfer(dev);
1.48      augustss 1078:        if (xfer == NULL)
1.162.2.9  skrll    1079:                return USBD_NOMEM;
1.162.2.11  skrll    1080:
                   1081:        if (UGETW(req->wLength) != 0) {
1.162.2.13  skrll    1082:                void *buf = usbd_alloc_buffer(xfer, UGETW(req->wLength));
1.162.2.11  skrll    1083:                if (buf == NULL) {
1.162.2.18  skrll    1084:                        err = USBD_NOMEM;
1.162.2.11  skrll    1085:                        goto bad;
                   1086:                }
                   1087:        }
                   1088:
1.96      augustss 1089:        usbd_setup_default_xfer(xfer, dev, 0, timeout, req,
1.77      augustss 1090:                                data, UGETW(req->wLength), flags, 0);
1.162.2.6  skrll    1091:        xfer->ux_pipe = pipe;
1.48      augustss 1092:        err = usbd_sync_transfer(xfer);
1.1       augustss 1093: #if defined(USB_DEBUG) || defined(DIAGNOSTIC)
1.162.2.6  skrll    1094:        if (xfer->ux_actlen > xfer->ux_length) {
1.162     skrll    1095:                USBHIST_LOG(usbdebug, "overrun addr = %d type = 0x%02x",
1.162.2.6  skrll    1096:                    dev->ud_addr, xfer->ux_request.bmRequestType, 0, 0);
1.162     skrll    1097:                USBHIST_LOG(usbdebug, "     req = 0x%02x val = %d index = %d",
1.162.2.6  skrll    1098:                    xfer->ux_request.bRequest, UGETW(xfer->ux_request.wValue),
                   1099:                    UGETW(xfer->ux_request.wIndex), 0);
1.162     skrll    1100:                USBHIST_LOG(usbdebug, "     rlen = %d length = %d actlen = %d",
1.162.2.6  skrll    1101:                    UGETW(xfer->ux_request.wLength),
                   1102:                    xfer->ux_length, xfer->ux_actlen, 0);
1.112     dogcow   1103:        }
1.1       augustss 1104: #endif
1.48      augustss 1105:        if (actlen != NULL)
1.162.2.6  skrll    1106:                *actlen = xfer->ux_actlen;
1.48      augustss 1107:        if (err == USBD_STALLED) {
1.102     augustss 1108:                /*
1.15      augustss 1109:                 * The control endpoint has stalled.  Control endpoints
                   1110:                 * should not halt, but some may do so anyway so clear
                   1111:                 * any halt condition.
                   1112:                 */
                   1113:                usb_device_request_t treq;
                   1114:                usb_status_t status;
1.162.2.1  skrll    1115:                uint16_t s;
1.48      augustss 1116:                usbd_status nerr;
1.15      augustss 1117:
                   1118:                treq.bmRequestType = UT_READ_ENDPOINT;
                   1119:                treq.bRequest = UR_GET_STATUS;
                   1120:                USETW(treq.wValue, 0);
                   1121:                USETW(treq.wIndex, 0);
                   1122:                USETW(treq.wLength, sizeof(usb_status_t));
1.50      augustss 1123:                usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT,
1.37      augustss 1124:                                           &treq, &status,sizeof(usb_status_t),
1.36      augustss 1125:                                           0, 0);
1.48      augustss 1126:                nerr = usbd_sync_transfer(xfer);
                   1127:                if (nerr)
1.15      augustss 1128:                        goto bad;
                   1129:                s = UGETW(status.wStatus);
1.162     skrll    1130:                USBHIST_LOG(usbdebug, "status = 0x%04x", s, 0, 0, 0);
1.15      augustss 1131:                if (!(s & UES_HALT))
                   1132:                        goto bad;
                   1133:                treq.bmRequestType = UT_WRITE_ENDPOINT;
                   1134:                treq.bRequest = UR_CLEAR_FEATURE;
                   1135:                USETW(treq.wValue, UF_ENDPOINT_HALT);
                   1136:                USETW(treq.wIndex, 0);
                   1137:                USETW(treq.wLength, 0);
1.50      augustss 1138:                usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT,
1.36      augustss 1139:                                           &treq, &status, 0, 0, 0);
1.48      augustss 1140:                nerr = usbd_sync_transfer(xfer);
                   1141:                if (nerr)
1.15      augustss 1142:                        goto bad;
                   1143:        }
                   1144:
                   1145:  bad:
1.132     matt     1146:        if (err) {
1.162.2.14  skrll    1147:                USBHIST_LOG(usbdebug, "returning err = %d", err, 0, 0, 0);
1.132     matt     1148:        }
1.50      augustss 1149:        usbd_free_xfer(xfer);
1.162.2.9  skrll    1150:        return err;
1.7       augustss 1151: }
                   1152:
1.78      augustss 1153: const struct usbd_quirks *
1.74      augustss 1154: usbd_get_quirks(usbd_device_handle dev)
1.1       augustss 1155: {
1.81      augustss 1156: #ifdef DIAGNOSTIC
                   1157:        if (dev == NULL) {
                   1158:                printf("usbd_get_quirks: dev == NULL\n");
                   1159:                return 0;
                   1160:        }
                   1161: #endif
1.162.2.9  skrll    1162:        return dev->ud_quirks;
1.1       augustss 1163: }
                   1164:
                   1165: /* XXX do periodic free() of free list */
                   1166:
1.6       augustss 1167: /*
                   1168:  * Called from keyboard driver when in polling mode.
                   1169:  */
                   1170: void
1.74      augustss 1171: usbd_dopoll(usbd_interface_handle iface)
1.6       augustss 1172: {
1.162.2.6  skrll    1173:        iface->ui_dev->ud_bus->ub_methods->ubm_dopoll(iface->ui_dev->ud_bus);
1.8       augustss 1174: }
                   1175:
1.138     mrg      1176: /*
1.162.2.6  skrll    1177:  * XXX use this more???  ub_usepolling it touched manually all over
1.138     mrg      1178:  */
1.8       augustss 1179: void
1.74      augustss 1180: usbd_set_polling(usbd_device_handle dev, int on)
1.8       augustss 1181: {
1.42      augustss 1182:        if (on)
1.162.2.6  skrll    1183:                dev->ud_bus->ub_usepolling++;
1.42      augustss 1184:        else
1.162.2.6  skrll    1185:                dev->ud_bus->ub_usepolling--;
1.133     jmcneill 1186:
                   1187:        /* Kick the host controller when switching modes */
1.162.2.6  skrll    1188:        mutex_enter(dev->ud_bus->ub_lock);
                   1189:        dev->ud_bus->ub_methods->ubm_softint(dev->ud_bus);
                   1190:        mutex_exit(dev->ud_bus->ub_lock);
1.6       augustss 1191: }
1.12      augustss 1192:
                   1193:
                   1194: usb_endpoint_descriptor_t *
1.162.2.1  skrll    1195: usbd_get_endpoint_descriptor(usbd_interface_handle iface, uint8_t address)
1.12      augustss 1196: {
                   1197:        struct usbd_endpoint *ep;
                   1198:        int i;
                   1199:
1.162.2.6  skrll    1200:        for (i = 0; i < iface->ui_idesc->bNumEndpoints; i++) {
                   1201:                ep = &iface->ui_endpoints[i];
                   1202:                if (ep->ue_edesc->bEndpointAddress == address)
1.162.2.9  skrll    1203:                        return iface->ui_endpoints[i].ue_edesc;
1.12      augustss 1204:        }
1.162.2.9  skrll    1205:        return NULL;
1.63      augustss 1206: }
                   1207:
                   1208: /*
                   1209:  * usbd_ratecheck() can limit the number of error messages that occurs.
                   1210:  * When a device is unplugged it may take up to 0.25s for the hub driver
                   1211:  * to notice it.  If the driver continuosly tries to do I/O operations
                   1212:  * this can generate a large number of messages.
                   1213:  */
                   1214: int
1.74      augustss 1215: usbd_ratecheck(struct timeval *last)
1.63      augustss 1216: {
1.64      augustss 1217:        static struct timeval errinterval = { 0, 250000 }; /* 0.25 s*/
1.63      augustss 1218:
1.162.2.9  skrll    1219:        return ratecheck(last, &errinterval);
1.89      augustss 1220: }
                   1221:
                   1222: /*
                   1223:  * Search for a vendor/product pair in an array.  The item size is
                   1224:  * given as an argument.
                   1225:  */
1.90      augustss 1226: const struct usb_devno *
                   1227: usb_match_device(const struct usb_devno *tbl, u_int nentries, u_int sz,
1.162.2.1  skrll    1228:                 uint16_t vendor, uint16_t product)
1.89      augustss 1229: {
                   1230:        while (nentries-- > 0) {
1.162.2.1  skrll    1231:                uint16_t tproduct = tbl->ud_product;
1.93      augustss 1232:                if (tbl->ud_vendor == vendor &&
                   1233:                    (tproduct == product || tproduct == USB_PRODUCT_ANY))
1.162.2.9  skrll    1234:                        return tbl;
1.95      augustss 1235:                tbl = (const struct usb_devno *)((const char *)tbl + sz);
1.89      augustss 1236:        }
1.162.2.9  skrll    1237:        return NULL;
1.12      augustss 1238: }
                   1239:
1.105     augustss 1240:
                   1241: void
                   1242: usb_desc_iter_init(usbd_device_handle dev, usbd_desc_iter_t *iter)
                   1243: {
                   1244:        const usb_config_descriptor_t *cd = usbd_get_config_descriptor(dev);
                   1245:
1.162.2.2  skrll    1246:        iter->cur = (const uByte *)cd;
                   1247:        iter->end = (const uByte *)cd + UGETW(cd->wTotalLength);
1.105     augustss 1248: }
                   1249:
                   1250: const usb_descriptor_t *
                   1251: usb_desc_iter_next(usbd_desc_iter_t *iter)
                   1252: {
                   1253:        const usb_descriptor_t *desc;
                   1254:
                   1255:        if (iter->cur + sizeof(usb_descriptor_t) >= iter->end) {
                   1256:                if (iter->cur != iter->end)
                   1257:                        printf("usb_desc_iter_next: bad descriptor\n");
                   1258:                return NULL;
                   1259:        }
1.108     christos 1260:        desc = (const usb_descriptor_t *)iter->cur;
1.105     augustss 1261:        if (desc->bLength == 0) {
                   1262:                printf("usb_desc_iter_next: descriptor length = 0\n");
                   1263:                return NULL;
                   1264:        }
                   1265:        iter->cur += desc->bLength;
                   1266:        if (iter->cur > iter->end) {
                   1267:                printf("usb_desc_iter_next: descriptor length too large\n");
                   1268:                return NULL;
                   1269:        }
                   1270:        return desc;
                   1271: }
                   1272:
                   1273: usbd_status
                   1274: usbd_get_string(usbd_device_handle dev, int si, char *buf)
                   1275: {
1.115     pavel    1276:        return usbd_get_string0(dev, si, buf, 1);
                   1277: }
                   1278:
                   1279: usbd_status
                   1280: usbd_get_string0(usbd_device_handle dev, int si, char *buf, int unicode)
                   1281: {
1.162.2.6  skrll    1282:        int swap = dev->ud_quirks->uq_flags & UQ_SWAP_UNICODE;
1.105     augustss 1283:        usb_string_descriptor_t us;
                   1284:        char *s;
1.116     macallan 1285:        int i, n;
1.162.2.1  skrll    1286:        uint16_t c;
1.105     augustss 1287:        usbd_status err;
                   1288:        int size;
                   1289:
1.162     skrll    1290:        USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
                   1291:
1.105     augustss 1292:        buf[0] = '\0';
                   1293:        if (si == 0)
1.162.2.9  skrll    1294:                return USBD_INVAL;
1.162.2.6  skrll    1295:        if (dev->ud_quirks->uq_flags & UQ_NO_STRINGS)
1.162.2.9  skrll    1296:                return USBD_STALLED;
1.162.2.6  skrll    1297:        if (dev->ud_langid == USBD_NOLANG) {
1.105     augustss 1298:                /* Set up default language */
                   1299:                err = usbd_get_string_desc(dev, USB_LANGUAGE_TABLE, 0, &us,
                   1300:                    &size);
                   1301:                if (err || size < 4) {
1.162     skrll    1302:                        USBHIST_LOG(usbdebug, "getting lang failed, using 0",
                   1303:                            0, 0, 0, 0);
1.162.2.6  skrll    1304:                        dev->ud_langid = 0; /* Well, just pick something then */
1.105     augustss 1305:                } else {
                   1306:                        /* Pick the first language as the default. */
1.162.2.6  skrll    1307:                        dev->ud_langid = UGETW(us.bString[0]);
1.105     augustss 1308:                }
                   1309:        }
1.162.2.6  skrll    1310:        err = usbd_get_string_desc(dev, si, dev->ud_langid, &us, &size);
1.105     augustss 1311:        if (err)
1.162.2.9  skrll    1312:                return err;
1.105     augustss 1313:        s = buf;
                   1314:        n = size / 2 - 1;
1.115     pavel    1315:        if (unicode) {
                   1316:                for (i = 0; i < n; i++) {
                   1317:                        c = UGETW(us.bString[i]);
                   1318:                        if (swap)
                   1319:                                c = (c >> 8) | (c << 8);
1.119     drochner 1320:                        s += wput_utf8(s, 3, c);
1.115     pavel    1321:                }
                   1322:                *s++ = 0;
                   1323:        }
                   1324: #ifdef COMPAT_30
                   1325:        else {
1.119     drochner 1326:                for (i = 0; i < n; i++) {
1.115     pavel    1327:                        c = UGETW(us.bString[i]);
                   1328:                        if (swap)
                   1329:                                c = (c >> 8) | (c << 8);
1.119     drochner 1330:                        *s++ = (c < 0x80) ? c : '?';
1.107     augustss 1331:                }
1.119     drochner 1332:                *s++ = 0;
1.105     augustss 1333:        }
1.115     pavel    1334: #endif
1.162.2.9  skrll    1335:        return USBD_NORMAL_COMPLETION;
1.105     augustss 1336: }

CVSweb <webmaster@jp.NetBSD.org>