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