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