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