usbdi.c revision 1.46 1 /* $NetBSD: usbdi.c,v 1.46 1999/10/13 14:28:07 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 while ((reqh = SIMPLEQ_FIRST(&pipe->queue))) {
709 DPRINTFN(2,("usbd_ar_pipe: pipe=%p reqh=%p (methods=%p)\n",
710 pipe, reqh, pipe->methods));
711 /* Make the HC abort it (and invoke the callback). */
712 pipe->methods->abort(reqh);
713 /* XXX only for non-0 usbd_clear_endpoint_stall(pipe); */
714 }
715 return (USBD_NORMAL_COMPLETION);
716 }
717
718 /* Called at splusb() */
719 void
720 usb_transfer_complete(reqh)
721 usbd_request_handle reqh;
722 {
723 usbd_pipe_handle pipe = reqh->pipe;
724 usb_dma_t *dmap = &reqh->dmabuf;
725 int polling;
726
727 SPLUSBCHECK;
728
729 DPRINTFN(5, ("usb_transfer_complete: pipe=%p reqh=%p status=%d actlen=%d\n",
730 pipe, reqh, reqh->status, reqh->actlen));
731
732 #ifdef DIAGNOSTIC
733 if (!pipe) {
734 printf("usbd_transfer_cb: pipe==0, reqh=%p\n", reqh);
735 return;
736 }
737 #endif
738 polling = pipe->device->bus->use_polling;
739 /* XXXX */
740 if (polling)
741 pipe->running = 0;
742
743 if (!(reqh->flags & USBD_NO_COPY) && reqh->actlen != 0 &&
744 usbd_reqh_isread(reqh)) {
745 #ifdef DIAGNOSTIC
746 if (reqh->actlen > reqh->length) {
747 printf("usb_transfer_complete: actlen > len %d > %d\n",
748 reqh->actlen, reqh->length);
749 reqh->actlen = reqh->length;
750 }
751 #endif
752 memcpy(reqh->buffer, KERNADDR(dmap), reqh->actlen);
753 }
754
755 /* if we allocated the buffer in usbd_transfer() we free it here. */
756 if (reqh->rqflags & URQ_AUTO_DMABUF) {
757 if (!pipe->repeat) {
758 struct usbd_bus *bus = pipe->device->bus;
759 bus->methods->freem(bus, dmap);
760 reqh->rqflags &= ~URQ_AUTO_DMABUF;
761 }
762 }
763
764 if (pipe->methods->done)
765 pipe->methods->done(reqh);
766
767 /* Remove request from queue. */
768 #ifdef DIAGNOSTICx
769 if (reqh != SIMPLEQ_FIRST(&pipe->queue))
770 printf("usb_transfer_complete: bad dequeue\n");
771 #endif
772 SIMPLEQ_REMOVE_HEAD(&pipe->queue, reqh, next);
773
774 /* Count completed transfers. */
775 ++pipe->device->bus->stats.requests
776 [pipe->endpoint->edesc->bmAttributes & UE_XFERTYPE];
777
778 reqh->done = 1;
779 if (reqh->status == USBD_NORMAL_COMPLETION &&
780 reqh->actlen < reqh->length &&
781 !(reqh->flags & USBD_SHORT_XFER_OK)) {
782 DPRINTFN(-1, ("usbd_transfer_cb: short xfer %d<%d (bytes)\n",
783 reqh->actlen, reqh->length));
784 reqh->status = USBD_SHORT_XFER;
785 }
786
787 if (reqh->callback)
788 reqh->callback(reqh, reqh->priv, reqh->status);
789
790 if ((reqh->flags & USBD_SYNCHRONOUS) && !polling)
791 wakeup(reqh);
792
793 if (!pipe->repeat) {
794 /* XXX should we stop the queue on all errors? */
795 if (reqh->status == USBD_CANCELLED ||
796 reqh->status == USBD_TIMEOUT)
797 pipe->running = 0;
798 else
799 usbd_start_next(pipe);
800 }
801 }
802
803 usbd_status
804 usb_insert_transfer(reqh)
805 usbd_request_handle reqh;
806 {
807 usbd_pipe_handle pipe = reqh->pipe;
808 usbd_status r;
809 int s;
810
811 DPRINTFN(5,("usb_insert_transfer: pipe=%p running=%d timeout=%d\n",
812 pipe, pipe->running, reqh->timeout));
813 s = splusb();
814 SIMPLEQ_INSERT_TAIL(&pipe->queue, reqh, next);
815 if (pipe->running)
816 r = USBD_IN_PROGRESS;
817 else {
818 pipe->running = 1;
819 r = USBD_NORMAL_COMPLETION;
820 }
821 splx(s);
822 return (r);
823 }
824
825 /* Called at splusb() */
826 void
827 usbd_start_next(pipe)
828 usbd_pipe_handle pipe;
829 {
830 usbd_request_handle reqh;
831 usbd_status r;
832
833 SPLUSBCHECK;
834
835 DPRINTFN(10, ("usbd_start_next: pipe=%p\n", pipe));
836
837 #ifdef DIAGNOSTIC
838 if (!pipe) {
839 printf("usbd_start_next: pipe == 0\n");
840 return;
841 }
842 if (!pipe->methods || !pipe->methods->start) {
843 printf("usbd_start_next: no start method\n");
844 return;
845 }
846 #endif
847
848 /* Get next request in queue. */
849 reqh = SIMPLEQ_FIRST(&pipe->queue);
850 DPRINTFN(5, ("usbd_start_next: pipe=%p start reqh=%p\n", pipe, reqh));
851 if (!reqh)
852 pipe->running = 0;
853 else {
854 r = pipe->methods->start(reqh);
855 if (r != USBD_IN_PROGRESS) {
856 printf("usbd_start_next: error=%d\n", r);
857 pipe->running = 0;
858 /* XXX do what? */
859 }
860 }
861 }
862
863 usbd_status
864 usbd_do_request(dev, req, data)
865 usbd_device_handle dev;
866 usb_device_request_t *req;
867 void *data;
868 {
869 return (usbd_do_request_flags(dev, req, data, 0, 0));
870 }
871
872 usbd_status
873 usbd_do_request_flags(dev, req, data, flags, actlen)
874 usbd_device_handle dev;
875 usb_device_request_t *req;
876 void *data;
877 u_int16_t flags;
878 int *actlen;
879 {
880 usbd_request_handle reqh;
881 usbd_status r;
882
883 #ifdef DIAGNOSTIC
884 if (dev->bus->intr_context) {
885 printf("usbd_do_request: not in process context\n");
886 return (USBD_INVAL);
887 }
888 #endif
889
890 reqh = usbd_alloc_request(dev);
891 if (reqh == 0)
892 return (USBD_NOMEM);
893 usbd_setup_default_request(reqh, dev, 0, USBD_DEFAULT_TIMEOUT, req,
894 data, UGETW(req->wLength), flags, 0);
895 r = usbd_sync_transfer(reqh);
896 #if defined(USB_DEBUG) || defined(DIAGNOSTIC)
897 if (reqh->actlen > reqh->length)
898 DPRINTF(("usbd_do_request: overrun addr=%d type=0x%02x req=0x"
899 "%02x val=%d index=%d rlen=%d length=%d actlen=%d\n",
900 dev->address, reqh->request.bmRequestType,
901 reqh->request.bRequest, UGETW(reqh->request.wValue),
902 UGETW(reqh->request.wIndex),
903 UGETW(reqh->request.wLength),
904 reqh->length, reqh->actlen));
905 #endif
906 if (actlen)
907 *actlen = reqh->actlen;
908 if (r == USBD_STALLED) {
909 /*
910 * The control endpoint has stalled. Control endpoints
911 * should not halt, but some may do so anyway so clear
912 * any halt condition.
913 */
914 usb_device_request_t treq;
915 usb_status_t status;
916 u_int16_t s;
917 usbd_status nr;
918
919 treq.bmRequestType = UT_READ_ENDPOINT;
920 treq.bRequest = UR_GET_STATUS;
921 USETW(treq.wValue, 0);
922 USETW(treq.wIndex, 0);
923 USETW(treq.wLength, sizeof(usb_status_t));
924 usbd_setup_default_request(reqh, dev, 0, USBD_DEFAULT_TIMEOUT,
925 &treq, &status,sizeof(usb_status_t),
926 0, 0);
927 nr = usbd_sync_transfer(reqh);
928 if (nr != USBD_NORMAL_COMPLETION)
929 goto bad;
930 s = UGETW(status.wStatus);
931 DPRINTF(("usbd_do_request: status = 0x%04x\n", s));
932 if (!(s & UES_HALT))
933 goto bad;
934 treq.bmRequestType = UT_WRITE_ENDPOINT;
935 treq.bRequest = UR_CLEAR_FEATURE;
936 USETW(treq.wValue, UF_ENDPOINT_HALT);
937 USETW(treq.wIndex, 0);
938 USETW(treq.wLength, 0);
939 usbd_setup_default_request(reqh, dev, 0, USBD_DEFAULT_TIMEOUT,
940 &treq, &status, 0, 0, 0);
941 nr = usbd_sync_transfer(reqh);
942 if (nr != USBD_NORMAL_COMPLETION)
943 goto bad;
944 }
945
946 bad:
947 usbd_free_request(reqh);
948 return (r);
949 }
950
951 void
952 usbd_do_request_async_cb(reqh, priv, status)
953 usbd_request_handle reqh;
954 usbd_private_handle priv;
955 usbd_status status;
956 {
957 #if defined(USB_DEBUG) || defined(DIAGNOSTIC)
958 if (reqh->actlen > reqh->length)
959 DPRINTF(("usbd_do_request: overrun addr=%d type=0x%02x req=0x"
960 "%02x val=%d index=%d rlen=%d length=%d actlen=%d\n",
961 reqh->pipe->device->address,
962 reqh->request.bmRequestType,
963 reqh->request.bRequest, UGETW(reqh->request.wValue),
964 UGETW(reqh->request.wIndex),
965 UGETW(reqh->request.wLength),
966 reqh->length, reqh->actlen));
967 #endif
968 usbd_free_request(reqh);
969 }
970
971 /*
972 * Execute a request without waiting for completion.
973 * Can be used from interrupt context.
974 */
975 usbd_status
976 usbd_do_request_async(dev, req, data)
977 usbd_device_handle dev;
978 usb_device_request_t *req;
979 void *data;
980 {
981 usbd_request_handle reqh;
982 usbd_status r;
983
984 reqh = usbd_alloc_request(dev);
985 if (reqh == 0)
986 return (USBD_NOMEM);
987 usbd_setup_default_request(reqh, dev, 0, USBD_DEFAULT_TIMEOUT, req, data,
988 UGETW(req->wLength), 0,
989 usbd_do_request_async_cb);
990 r = usbd_transfer(reqh);
991 if (r != USBD_IN_PROGRESS) {
992 usbd_free_request(reqh);
993 return (r);
994 }
995 return (USBD_NORMAL_COMPLETION);
996 }
997
998 struct usbd_quirks *
999 usbd_get_quirks(dev)
1000 usbd_device_handle dev;
1001 {
1002 return (dev->quirks);
1003 }
1004
1005 /* XXX do periodic free() of free list */
1006
1007 /*
1008 * Called from keyboard driver when in polling mode.
1009 */
1010 void
1011 usbd_dopoll(iface)
1012 usbd_interface_handle iface;
1013 {
1014 iface->device->bus->methods->do_poll(iface->device->bus);
1015 }
1016
1017 void
1018 usbd_set_polling(iface, on)
1019 usbd_interface_handle iface;
1020 int on;
1021 {
1022 if (on)
1023 iface->device->bus->use_polling++;
1024 else
1025 iface->device->bus->use_polling--;
1026 }
1027
1028
1029 usb_endpoint_descriptor_t *
1030 usbd_get_endpoint_descriptor(iface, address)
1031 usbd_interface_handle iface;
1032 u_int8_t address;
1033 {
1034 struct usbd_endpoint *ep;
1035 int i;
1036
1037 for (i = 0; i < iface->idesc->bNumEndpoints; i++) {
1038 ep = &iface->endpoints[i];
1039 if (ep->edesc->bEndpointAddress == address)
1040 return (iface->endpoints[i].edesc);
1041 }
1042 return (0);
1043 }
1044
1045 #if defined(__FreeBSD__)
1046 int
1047 usbd_driver_load(module_t mod, int what, void *arg)
1048 {
1049 /* XXX should implement something like a function that removes all generic devices */
1050
1051 return 0;
1052 }
1053
1054 #endif
1055