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