usbdi.c revision 1.59 1 /* $NetBSD: usbdi.c,v 1.59 2000/01/18 20:23:42 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 xfer->device = dev;
370 DPRINTFN(5,("usbd_alloc_xfer() = %p\n", xfer));
371 return (xfer);
372 }
373
374 usbd_status
375 usbd_free_xfer(xfer)
376 usbd_xfer_handle xfer;
377 {
378 DPRINTFN(5,("usbd_free_xfer: %p\n", xfer));
379 if (xfer->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF))
380 usbd_free_buffer(xfer);
381 xfer->device->bus->methods->freex(xfer->device->bus, xfer);
382 return (USBD_NORMAL_COMPLETION);
383 }
384
385 void
386 usbd_setup_xfer(xfer, pipe, priv, buffer, length, flags, timeout, callback)
387 usbd_xfer_handle xfer;
388 usbd_pipe_handle pipe;
389 usbd_private_handle priv;
390 void *buffer;
391 u_int32_t length;
392 u_int16_t flags;
393 u_int32_t timeout;
394 void (*callback) __P((usbd_xfer_handle,
395 usbd_private_handle,
396 usbd_status));
397 {
398 xfer->pipe = pipe;
399 xfer->priv = priv;
400 xfer->buffer = buffer;
401 xfer->length = length;
402 xfer->actlen = 0;
403 xfer->flags = flags;
404 xfer->timeout = timeout;
405 xfer->status = USBD_NOT_STARTED;
406 xfer->callback = callback;
407 xfer->rqflags &= ~URQ_REQUEST;
408 xfer->nframes = 0;
409 }
410
411 void
412 usbd_setup_default_xfer(xfer, dev, priv, timeout, req, buffer,
413 length, flags, callback)
414 usbd_xfer_handle xfer;
415 usbd_device_handle dev;
416 usbd_private_handle priv;
417 u_int32_t timeout;
418 usb_device_request_t *req;
419 void *buffer;
420 u_int32_t length;
421 u_int16_t flags;
422 void (*callback) __P((usbd_xfer_handle,
423 usbd_private_handle,
424 usbd_status));
425 {
426 xfer->pipe = dev->default_pipe;
427 xfer->priv = priv;
428 xfer->buffer = buffer;
429 xfer->length = length;
430 xfer->actlen = 0;
431 xfer->flags = flags;
432 xfer->timeout = timeout;
433 xfer->status = USBD_NOT_STARTED;
434 xfer->callback = callback;
435 xfer->request = *req;
436 xfer->rqflags |= URQ_REQUEST;
437 xfer->nframes = 0;
438 }
439
440 void
441 usbd_setup_isoc_xfer(xfer, pipe, priv, frlengths, nframes, flags, callback)
442 usbd_xfer_handle xfer;
443 usbd_pipe_handle pipe;
444 usbd_private_handle priv;
445 u_int16_t *frlengths;
446 u_int32_t nframes;
447 u_int16_t flags;
448 usbd_callback callback;
449 {
450 xfer->pipe = pipe;
451 xfer->priv = priv;
452 xfer->buffer = 0;
453 xfer->length = 0;
454 xfer->actlen = 0;
455 xfer->flags = flags;
456 xfer->timeout = USBD_NO_TIMEOUT;
457 xfer->status = USBD_NOT_STARTED;
458 xfer->callback = callback;
459 xfer->rqflags &= ~URQ_REQUEST;
460 xfer->frlengths = frlengths;
461 xfer->nframes = nframes;
462 }
463
464 void
465 usbd_get_xfer_status(xfer, priv, buffer, count, status)
466 usbd_xfer_handle xfer;
467 usbd_private_handle *priv;
468 void **buffer;
469 u_int32_t *count;
470 usbd_status *status;
471 {
472 if (priv != NULL)
473 *priv = xfer->priv;
474 if (buffer != NULL)
475 *buffer = xfer->buffer;
476 if (count != NULL)
477 *count = xfer->actlen;
478 if (status != NULL)
479 *status = xfer->status;
480 }
481
482 usb_config_descriptor_t *
483 usbd_get_config_descriptor(dev)
484 usbd_device_handle dev;
485 {
486 #ifdef DIAGNOSTIC
487 if (dev == NULL) {
488 printf("usbd_get_config_descriptor: dev == NULL\n");
489 return (NULL);
490 }
491 #endif
492 return (dev->cdesc);
493 }
494
495 usb_interface_descriptor_t *
496 usbd_get_interface_descriptor(iface)
497 usbd_interface_handle iface;
498 {
499 #ifdef DIAGNOSTIC
500 if (iface == NULL) {
501 printf("usbd_get_interface_descriptor: dev == NULL\n");
502 return (NULL);
503 }
504 #endif
505 return (iface->idesc);
506 }
507
508 usb_device_descriptor_t *
509 usbd_get_device_descriptor(dev)
510 usbd_device_handle dev;
511 {
512 return (&dev->ddesc);
513 }
514
515 usb_endpoint_descriptor_t *
516 usbd_interface2endpoint_descriptor(iface, index)
517 usbd_interface_handle iface;
518 u_int8_t index;
519 {
520 if (index >= iface->idesc->bNumEndpoints)
521 return (0);
522 return (iface->endpoints[index].edesc);
523 }
524
525 usbd_status
526 usbd_abort_pipe(pipe)
527 usbd_pipe_handle pipe;
528 {
529 usbd_status err;
530 int s;
531
532 #ifdef DIAGNOSTIC
533 if (pipe == NULL) {
534 printf("usbd_close_pipe: pipe==NULL\n");
535 return (USBD_NORMAL_COMPLETION);
536 }
537 #endif
538 s = splusb();
539 err = usbd_ar_pipe(pipe);
540 splx(s);
541 return (err);
542 }
543
544 usbd_status
545 usbd_clear_endpoint_stall(pipe)
546 usbd_pipe_handle pipe;
547 {
548 usbd_device_handle dev = pipe->device;
549 usb_device_request_t req;
550 usbd_status err;
551
552 DPRINTFN(8, ("usbd_clear_endpoint_stall\n"));
553
554 /*
555 * Clearing en endpoint stall resets the enpoint toggle, so
556 * do the same to the HC toggle.
557 */
558 pipe->methods->cleartoggle(pipe);
559
560 req.bmRequestType = UT_WRITE_ENDPOINT;
561 req.bRequest = UR_CLEAR_FEATURE;
562 USETW(req.wValue, UF_ENDPOINT_HALT);
563 USETW(req.wIndex, pipe->endpoint->edesc->bEndpointAddress);
564 USETW(req.wLength, 0);
565 err = usbd_do_request(dev, &req, 0);
566 #if 0
567 XXX should we do this?
568 if (!err) {
569 pipe->state = USBD_PIPE_ACTIVE;
570 /* XXX activate pipe */
571 }
572 #endif
573 return (err);
574 }
575
576 usbd_status
577 usbd_clear_endpoint_stall_async(pipe)
578 usbd_pipe_handle pipe;
579 {
580 usbd_device_handle dev = pipe->device;
581 usb_device_request_t req;
582 usbd_status err;
583
584 pipe->methods->cleartoggle(pipe);
585
586 req.bmRequestType = UT_WRITE_ENDPOINT;
587 req.bRequest = UR_CLEAR_FEATURE;
588 USETW(req.wValue, UF_ENDPOINT_HALT);
589 USETW(req.wIndex, pipe->endpoint->edesc->bEndpointAddress);
590 USETW(req.wLength, 0);
591 err = usbd_do_request_async(dev, &req, 0);
592 return (err);
593 }
594
595 usbd_status
596 usbd_endpoint_count(iface, count)
597 usbd_interface_handle iface;
598 u_int8_t *count;
599 {
600 *count = iface->idesc->bNumEndpoints;
601 return (USBD_NORMAL_COMPLETION);
602 }
603
604 usbd_status
605 usbd_interface_count(dev, count)
606 usbd_device_handle dev;
607 u_int8_t *count;
608 {
609 if (dev->cdesc == NULL)
610 return (USBD_NOT_CONFIGURED);
611 *count = dev->cdesc->bNumInterface;
612 return (USBD_NORMAL_COMPLETION);
613 }
614
615 usbd_status
616 usbd_interface2device_handle(iface, dev)
617 usbd_interface_handle iface;
618 usbd_device_handle *dev;
619 {
620 *dev = iface->device;
621 return (USBD_NORMAL_COMPLETION);
622 }
623
624 usbd_status
625 usbd_device2interface_handle(dev, ifaceno, iface)
626 usbd_device_handle dev;
627 u_int8_t ifaceno;
628 usbd_interface_handle *iface;
629 {
630 if (dev->cdesc == NULL)
631 return (USBD_NOT_CONFIGURED);
632 if (ifaceno >= dev->cdesc->bNumInterface)
633 return (USBD_INVAL);
634 *iface = &dev->ifaces[ifaceno];
635 return (USBD_NORMAL_COMPLETION);
636 }
637
638 usbd_device_handle
639 usbd_pipe2device_handle(pipe)
640 usbd_pipe_handle pipe;
641 {
642 return (pipe->device);
643 }
644
645 /* XXXX use altno */
646 usbd_status
647 usbd_set_interface(iface, altidx)
648 usbd_interface_handle iface;
649 int altidx;
650 {
651 usb_device_request_t req;
652 usbd_status err;
653
654 if (LIST_FIRST(&iface->pipes) != 0)
655 return (USBD_IN_USE);
656
657 if (iface->endpoints)
658 free(iface->endpoints, M_USB);
659 iface->endpoints = 0;
660 iface->idesc = 0;
661
662 err = usbd_fill_iface_data(iface->device, iface->index, altidx);
663 if (err)
664 return (err);
665
666 req.bmRequestType = UT_WRITE_INTERFACE;
667 req.bRequest = UR_SET_INTERFACE;
668 USETW(req.wValue, iface->idesc->bAlternateSetting);
669 USETW(req.wIndex, iface->idesc->bInterfaceNumber);
670 USETW(req.wLength, 0);
671 return (usbd_do_request(iface->device, &req, 0));
672 }
673
674 int
675 usbd_get_no_alts(cdesc, ifaceno)
676 usb_config_descriptor_t *cdesc;
677 int ifaceno;
678 {
679 char *p = (char *)cdesc;
680 char *end = p + UGETW(cdesc->wTotalLength);
681 usb_interface_descriptor_t *d;
682 int n;
683
684 for (n = 0; p < end; p += d->bLength) {
685 d = (usb_interface_descriptor_t *)p;
686 if (p + d->bLength <= end &&
687 d->bDescriptorType == UDESC_INTERFACE &&
688 d->bInterfaceNumber == ifaceno)
689 n++;
690 }
691 return (n);
692 }
693
694 int
695 usbd_get_interface_altindex(iface)
696 usbd_interface_handle iface;
697 {
698 return (iface->altindex);
699 }
700
701 usbd_status
702 usbd_get_interface(iface, aiface)
703 usbd_interface_handle iface;
704 u_int8_t *aiface;
705 {
706 usb_device_request_t req;
707
708 req.bmRequestType = UT_READ_INTERFACE;
709 req.bRequest = UR_GET_INTERFACE;
710 USETW(req.wValue, 0);
711 USETW(req.wIndex, iface->idesc->bInterfaceNumber);
712 USETW(req.wLength, 1);
713 return (usbd_do_request(iface->device, &req, aiface));
714 }
715
716 /*** Internal routines ***/
717
718 /* Dequeue all pipe operations, called at splusb(). */
719 static usbd_status
720 usbd_ar_pipe(pipe)
721 usbd_pipe_handle pipe;
722 {
723 usbd_xfer_handle xfer;
724
725 SPLUSBCHECK;
726
727 DPRINTFN(2,("usbd_ar_pipe: pipe=%p\n", pipe));
728 #ifdef USB_DEBUG
729 if (usbdebug > 5)
730 usbd_dump_queue(pipe);
731 #endif
732 pipe->repeat = 0;
733 while ((xfer = SIMPLEQ_FIRST(&pipe->queue)) != NULL) {
734 DPRINTFN(2,("usbd_ar_pipe: pipe=%p xfer=%p (methods=%p)\n",
735 pipe, xfer, pipe->methods));
736 /* Make the HC abort it (and invoke the callback). */
737 pipe->methods->abort(xfer);
738 /* XXX only for non-0 usbd_clear_endpoint_stall(pipe); */
739 }
740 return (USBD_NORMAL_COMPLETION);
741 }
742
743 /* Called at splusb() */
744 void
745 usb_transfer_complete(xfer)
746 usbd_xfer_handle xfer;
747 {
748 usbd_pipe_handle pipe = xfer->pipe;
749 usb_dma_t *dmap = &xfer->dmabuf;
750 int repeat = pipe->repeat;
751 int polling;
752
753 SPLUSBCHECK;
754
755 DPRINTFN(5, ("usb_transfer_complete: pipe=%p xfer=%p status=%d "
756 "actlen=%d\n", pipe, xfer, xfer->status, xfer->actlen));
757
758 #ifdef DIAGNOSTIC
759 if (pipe == NULL) {
760 printf("usbd_transfer_cb: pipe==0, xfer=%p\n", xfer);
761 return;
762 }
763 #endif
764 polling = pipe->device->bus->use_polling;
765 /* XXXX */
766 if (polling)
767 pipe->running = 0;
768
769 if (!(xfer->flags & USBD_NO_COPY) && xfer->actlen != 0 &&
770 usbd_xfer_isread(xfer)) {
771 #ifdef DIAGNOSTIC
772 if (xfer->actlen > xfer->length) {
773 printf("usb_transfer_complete: actlen > len %d > %d\n",
774 xfer->actlen, xfer->length);
775 xfer->actlen = xfer->length;
776 }
777 #endif
778 memcpy(xfer->buffer, KERNADDR(dmap), xfer->actlen);
779 }
780
781 /* if we allocated the buffer in usbd_transfer() we free it here. */
782 if (xfer->rqflags & URQ_AUTO_DMABUF) {
783 if (!repeat) {
784 struct usbd_bus *bus = pipe->device->bus;
785 bus->methods->freem(bus, dmap);
786 xfer->rqflags &= ~URQ_AUTO_DMABUF;
787 }
788 }
789
790 if (pipe->methods->done != NULL)
791 pipe->methods->done(xfer);
792
793 if (!repeat) {
794 /* Remove request from queue. */
795 #ifdef DIAGNOSTIC
796 if (xfer != SIMPLEQ_FIRST(&pipe->queue))
797 printf("usb_transfer_complete: bad dequeue %p != %p\n",
798 xfer, SIMPLEQ_FIRST(&pipe->queue));
799 #endif
800 SIMPLEQ_REMOVE_HEAD(&pipe->queue, xfer, next);
801 }
802
803 /* Count completed transfers. */
804 ++pipe->device->bus->stats.requests
805 [pipe->endpoint->edesc->bmAttributes & UE_XFERTYPE];
806
807 xfer->done = 1;
808 if (!xfer->status && xfer->actlen < xfer->length &&
809 !(xfer->flags & USBD_SHORT_XFER_OK)) {
810 DPRINTFN(-1,("usbd_transfer_cb: short transfer %d<%d\n",
811 xfer->actlen, xfer->length));
812 xfer->status = USBD_SHORT_XFER;
813 }
814
815 if (xfer->callback)
816 xfer->callback(xfer, xfer->priv, xfer->status);
817
818 if ((xfer->flags & USBD_SYNCHRONOUS) && !polling)
819 wakeup(xfer);
820
821 if (!repeat) {
822 /* XXX should we stop the queue on all errors? */
823 if (xfer->status == USBD_CANCELLED ||
824 xfer->status == USBD_TIMEOUT)
825 pipe->running = 0;
826 else
827 usbd_start_next(pipe);
828 }
829 }
830
831 usbd_status
832 usb_insert_transfer(xfer)
833 usbd_xfer_handle xfer;
834 {
835 usbd_pipe_handle pipe = xfer->pipe;
836 usbd_status err;
837 int s;
838
839 DPRINTFN(5,("usb_insert_transfer: pipe=%p running=%d timeout=%d\n",
840 pipe, pipe->running, xfer->timeout));
841 s = splusb();
842 SIMPLEQ_INSERT_TAIL(&pipe->queue, xfer, next);
843 if (pipe->running)
844 err = USBD_IN_PROGRESS;
845 else {
846 pipe->running = 1;
847 err = USBD_NORMAL_COMPLETION;
848 }
849 splx(s);
850 return (err);
851 }
852
853 /* Called at splusb() */
854 void
855 usbd_start_next(pipe)
856 usbd_pipe_handle pipe;
857 {
858 usbd_xfer_handle xfer;
859 usbd_status err;
860
861 SPLUSBCHECK;
862
863 #ifdef DIAGNOSTIC
864 if (pipe == NULL) {
865 printf("usbd_start_next: pipe == NULL\n");
866 return;
867 }
868 if (pipe->methods == NULL || pipe->methods->start == NULL) {
869 printf("usbd_start_next: pipe=%p no start method\n", pipe);
870 return;
871 }
872 #endif
873
874 /* Get next request in queue. */
875 xfer = SIMPLEQ_FIRST(&pipe->queue);
876 DPRINTFN(5, ("usbd_start_next: pipe=%p, xfer=%p\n", pipe, xfer));
877 if (xfer == NULL) {
878 pipe->running = 0;
879 } else {
880 err = pipe->methods->start(xfer);
881 if (err != USBD_IN_PROGRESS) {
882 printf("usbd_start_next: error=%d\n", err);
883 pipe->running = 0;
884 /* XXX do what? */
885 }
886 }
887 }
888
889 usbd_status
890 usbd_do_request(dev, req, data)
891 usbd_device_handle dev;
892 usb_device_request_t *req;
893 void *data;
894 {
895 return (usbd_do_request_flags(dev, req, data, 0, 0));
896 }
897
898 usbd_status
899 usbd_do_request_flags(dev, req, data, flags, actlen)
900 usbd_device_handle dev;
901 usb_device_request_t *req;
902 void *data;
903 u_int16_t flags;
904 int *actlen;
905 {
906 usbd_xfer_handle xfer;
907 usbd_status err;
908
909 #ifdef DIAGNOSTIC
910 #if defined(__i386__) && defined(__FreeBSD__)
911 KASSERT(intr_nesting_level == 0,
912 ("ohci_abort_req in interrupt context"));
913 #endif
914 if (dev->bus->intr_context) {
915 printf("usbd_do_request: not in process context\n");
916 return (USBD_INVAL);
917 }
918 #endif
919
920 xfer = usbd_alloc_xfer(dev);
921 if (xfer == NULL)
922 return (USBD_NOMEM);
923 usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT, req,
924 data, UGETW(req->wLength), flags, 0);
925 err = usbd_sync_transfer(xfer);
926 #if defined(USB_DEBUG) || defined(DIAGNOSTIC)
927 if (xfer->actlen > xfer->length)
928 DPRINTF(("usbd_do_request: overrun addr=%d type=0x%02x req=0x"
929 "%02x val=%d index=%d rlen=%d length=%d actlen=%d\n",
930 dev->address, xfer->request.bmRequestType,
931 xfer->request.bRequest, UGETW(xfer->request.wValue),
932 UGETW(xfer->request.wIndex),
933 UGETW(xfer->request.wLength),
934 xfer->length, xfer->actlen));
935 #endif
936 if (actlen != NULL)
937 *actlen = xfer->actlen;
938 if (err == USBD_STALLED) {
939 /*
940 * The control endpoint has stalled. Control endpoints
941 * should not halt, but some may do so anyway so clear
942 * any halt condition.
943 */
944 usb_device_request_t treq;
945 usb_status_t status;
946 u_int16_t s;
947 usbd_status nerr;
948
949 treq.bmRequestType = UT_READ_ENDPOINT;
950 treq.bRequest = UR_GET_STATUS;
951 USETW(treq.wValue, 0);
952 USETW(treq.wIndex, 0);
953 USETW(treq.wLength, sizeof(usb_status_t));
954 usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT,
955 &treq, &status,sizeof(usb_status_t),
956 0, 0);
957 nerr = usbd_sync_transfer(xfer);
958 if (nerr)
959 goto bad;
960 s = UGETW(status.wStatus);
961 DPRINTF(("usbd_do_request: status = 0x%04x\n", s));
962 if (!(s & UES_HALT))
963 goto bad;
964 treq.bmRequestType = UT_WRITE_ENDPOINT;
965 treq.bRequest = UR_CLEAR_FEATURE;
966 USETW(treq.wValue, UF_ENDPOINT_HALT);
967 USETW(treq.wIndex, 0);
968 USETW(treq.wLength, 0);
969 usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT,
970 &treq, &status, 0, 0, 0);
971 nerr = usbd_sync_transfer(xfer);
972 if (nerr)
973 goto bad;
974 }
975
976 bad:
977 usbd_free_xfer(xfer);
978 return (err);
979 }
980
981 void
982 usbd_do_request_async_cb(xfer, priv, status)
983 usbd_xfer_handle xfer;
984 usbd_private_handle priv;
985 usbd_status status;
986 {
987 #if defined(USB_DEBUG) || defined(DIAGNOSTIC)
988 if (xfer->actlen > xfer->length)
989 DPRINTF(("usbd_do_request: overrun addr=%d type=0x%02x req=0x"
990 "%02x val=%d index=%d rlen=%d length=%d actlen=%d\n",
991 xfer->pipe->device->address,
992 xfer->request.bmRequestType,
993 xfer->request.bRequest, UGETW(xfer->request.wValue),
994 UGETW(xfer->request.wIndex),
995 UGETW(xfer->request.wLength),
996 xfer->length, xfer->actlen));
997 #endif
998 usbd_free_xfer(xfer);
999 }
1000
1001 /*
1002 * Execute a request without waiting for completion.
1003 * Can be used from interrupt context.
1004 */
1005 usbd_status
1006 usbd_do_request_async(dev, req, data)
1007 usbd_device_handle dev;
1008 usb_device_request_t *req;
1009 void *data;
1010 {
1011 usbd_xfer_handle xfer;
1012 usbd_status err;
1013
1014 xfer = usbd_alloc_xfer(dev);
1015 if (xfer == NULL)
1016 return (USBD_NOMEM);
1017 usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT, req,
1018 data, UGETW(req->wLength), 0, usbd_do_request_async_cb);
1019 err = usbd_transfer(xfer);
1020 if (err != USBD_IN_PROGRESS) {
1021 usbd_free_xfer(xfer);
1022 return (err);
1023 }
1024 return (USBD_NORMAL_COMPLETION);
1025 }
1026
1027 struct usbd_quirks *
1028 usbd_get_quirks(dev)
1029 usbd_device_handle dev;
1030 {
1031 return (dev->quirks);
1032 }
1033
1034 /* XXX do periodic free() of free list */
1035
1036 /*
1037 * Called from keyboard driver when in polling mode.
1038 */
1039 void
1040 usbd_dopoll(iface)
1041 usbd_interface_handle iface;
1042 {
1043 iface->device->bus->methods->do_poll(iface->device->bus);
1044 }
1045
1046 void
1047 usbd_set_polling(dev, on)
1048 usbd_device_handle dev;
1049 int on;
1050 {
1051 if (on)
1052 dev->bus->use_polling++;
1053 else
1054 dev->bus->use_polling--;
1055 }
1056
1057
1058 usb_endpoint_descriptor_t *
1059 usbd_get_endpoint_descriptor(iface, address)
1060 usbd_interface_handle iface;
1061 u_int8_t address;
1062 {
1063 struct usbd_endpoint *ep;
1064 int i;
1065
1066 for (i = 0; i < iface->idesc->bNumEndpoints; i++) {
1067 ep = &iface->endpoints[i];
1068 if (ep->edesc->bEndpointAddress == address)
1069 return (iface->endpoints[i].edesc);
1070 }
1071 return (0);
1072 }
1073
1074 #if defined(__FreeBSD__)
1075 int
1076 usbd_driver_load(module_t mod, int what, void *arg)
1077 {
1078 /* XXX should implement something like a function that removes all generic devices */
1079
1080 return (0);
1081 }
1082
1083 #endif
1084