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>