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