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