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