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