usbdi.c revision 1.33 1 /* $NetBSD: usbdi.c,v 1.33 1999/08/28 10:04:01 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 #else
46 #include <sys/module.h>
47 #include <sys/bus.h>
48 #include <sys/conf.h>
49 #endif
50 #include <sys/malloc.h>
51 #include <sys/proc.h>
52
53 #include <dev/usb/usb.h>
54
55 #include <dev/usb/usbdi.h>
56 #include <dev/usb/usbdi_util.h>
57 #include <dev/usb/usbdivar.h>
58
59 #if defined(__FreeBSD__)
60 #include "usb_if.h"
61 #endif
62
63 #ifdef USB_DEBUG
64 #define DPRINTF(x) if (usbdebug) logprintf x
65 #define DPRINTFN(n,x) if (usbdebug>(n)) logprintf x
66 extern int usbdebug;
67 #else
68 #define DPRINTF(x)
69 #define DPRINTFN(n,x)
70 #endif
71
72 static usbd_status usbd_ar_pipe __P((usbd_pipe_handle pipe));
73 void usbd_do_request_async_cb
74 __P((usbd_request_handle, usbd_private_handle, usbd_status));
75 void usbd_start_next __P((usbd_pipe_handle pipe));
76
77 static SIMPLEQ_HEAD(, usbd_request) usbd_free_requests;
78
79 #if defined(__FreeBSD__)
80 #define USB_CDEV_MAJOR 108
81
82 extern struct cdevsw usb_cdevsw;
83 #endif
84
85 #ifdef USB_DEBUG
86 void usbd_dump_queue __P((usbd_pipe_handle));
87
88 void
89 usbd_dump_queue(pipe)
90 usbd_pipe_handle pipe;
91 {
92 usbd_request_handle reqh;
93
94 printf("usbd_dump_queue: pipe=%p\n", pipe);
95 for (reqh = SIMPLEQ_FIRST(&pipe->queue);
96 reqh;
97 reqh = SIMPLEQ_NEXT(reqh, next)) {
98 printf(" reqh=%p\n", reqh);
99 }
100 }
101 #endif
102
103 usbd_status
104 usbd_open_pipe(iface, address, flags, pipe)
105 usbd_interface_handle iface;
106 u_int8_t address;
107 u_int8_t flags;
108 usbd_pipe_handle *pipe;
109 {
110 usbd_pipe_handle p;
111 struct usbd_endpoint *ep;
112 usbd_status r;
113 int i;
114
115 for (i = 0; i < iface->idesc->bNumEndpoints; i++) {
116 ep = &iface->endpoints[i];
117 if (ep->edesc->bEndpointAddress == address)
118 goto found;
119 }
120 return (USBD_BAD_ADDRESS);
121 found:
122 if ((flags & USBD_EXCLUSIVE_USE) &&
123 ep->refcnt != 0)
124 return (USBD_IN_USE);
125 r = usbd_setup_pipe(iface->device, iface, ep, &p);
126 if (r != USBD_NORMAL_COMPLETION)
127 return (r);
128 LIST_INSERT_HEAD(&iface->pipes, p, next);
129 *pipe = p;
130 return (USBD_NORMAL_COMPLETION);
131 }
132
133 usbd_status
134 usbd_open_pipe_intr(iface, address, flags, pipe, priv, buffer, length, cb)
135 usbd_interface_handle iface;
136 u_int8_t address;
137 u_int8_t flags;
138 usbd_pipe_handle *pipe;
139 usbd_private_handle priv;
140 void *buffer;
141 u_int32_t length;
142 usbd_callback cb;
143 {
144 usbd_status r;
145 usbd_request_handle reqh;
146 usbd_pipe_handle ipipe;
147
148 reqh = usbd_alloc_request();
149 if (reqh == 0)
150 return (USBD_NOMEM);
151 r = usbd_open_pipe(iface, address, USBD_EXCLUSIVE_USE, &ipipe);
152 if (r != USBD_NORMAL_COMPLETION)
153 goto bad1;
154 r = usbd_setup_request(reqh, ipipe, priv, buffer, length,
155 USBD_XFER_IN | flags, USBD_NO_TIMEOUT, cb);
156 if (r != USBD_NORMAL_COMPLETION)
157 goto bad2;
158 ipipe->intrreqh = reqh;
159 ipipe->repeat = 1;
160 r = usbd_transfer(reqh);
161 *pipe = ipipe;
162 if (r != USBD_IN_PROGRESS)
163 goto bad3;
164 return (USBD_NORMAL_COMPLETION);
165
166 bad3:
167 ipipe->intrreqh = 0;
168 ipipe->repeat = 0;
169 bad2:
170 usbd_close_pipe(ipipe);
171 bad1:
172 usbd_free_request(reqh);
173 return r;
174 }
175
176 usbd_status
177 usbd_open_pipe_iso(iface, address, flags, pipe, priv, bufsize, nbuf)
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 u_int32_t bufsize;
184 u_int32_t nbuf;
185 {
186 usbd_status r;
187 usbd_pipe_handle p;
188
189 r = usbd_open_pipe(iface, address, USBD_EXCLUSIVE_USE, &p);
190 if (r != USBD_NORMAL_COMPLETION)
191 return (r);
192 if (!p->methods->isobuf) {
193 usbd_close_pipe(p);
194 return (USBD_INVAL);
195 }
196 r = p->methods->isobuf(p, bufsize, nbuf);
197 if (r != USBD_NORMAL_COMPLETION) {
198 usbd_close_pipe(p);
199 return (r);
200 }
201 *pipe = p;
202 return r;
203 }
204
205 usbd_status
206 usbd_close_pipe(pipe)
207 usbd_pipe_handle pipe;
208 {
209 #ifdef DIAGNOSTIC
210 if (pipe == 0) {
211 printf("usbd_close_pipe: pipe==NULL\n");
212 return (USBD_NORMAL_COMPLETION);
213 }
214 #endif
215
216 if (--pipe->refcnt != 0)
217 return (USBD_NORMAL_COMPLETION);
218 if (SIMPLEQ_FIRST(&pipe->queue) != 0)
219 return (USBD_PENDING_REQUESTS);
220 LIST_REMOVE(pipe, next);
221 pipe->endpoint->refcnt--;
222 pipe->methods->close(pipe);
223 if (pipe->intrreqh)
224 usbd_free_request(pipe->intrreqh);
225 free(pipe, M_USB);
226 return (USBD_NORMAL_COMPLETION);
227 }
228
229 usbd_status
230 usbd_transfer(reqh)
231 usbd_request_handle reqh;
232 {
233 usbd_pipe_handle pipe = reqh->pipe;
234 usbd_status r;
235 int s;
236
237 DPRINTFN(5,("usbd_transfer: reqh=%p, flags=%d, pipe=%p, running=%d\n",
238 reqh, reqh->flags, pipe, pipe->running));
239 #ifdef USB_DEBUG
240 if (usbdebug > 5)
241 usbd_dump_queue(pipe);
242 #endif
243 reqh->done = 0;
244
245 r = pipe->methods->transfer(reqh);
246 if (!(reqh->flags & USBD_SYNCHRONOUS))
247 return r;
248
249 /* Sync transfer, wait for completion. */
250 if (r != USBD_IN_PROGRESS)
251 return (r);
252 s = splusb();
253 if (!reqh->done) {
254 if (reqh->pipe->device->bus->use_polling)
255 panic("usbd_transfer: not done\n");
256 tsleep(reqh, PRIBIO, "usbsyn", 0);
257 }
258 splx(s);
259 return (reqh->status);
260 }
261
262 /* Like usbd_transfer(), but waits for completion. */
263 usbd_status
264 usbd_sync_transfer(reqh)
265 usbd_request_handle reqh;
266 {
267 reqh->flags |= USBD_SYNCHRONOUS;
268 return (usbd_transfer(reqh));
269 }
270
271 usbd_request_handle
272 usbd_alloc_request()
273 {
274 usbd_request_handle reqh;
275
276 reqh = SIMPLEQ_FIRST(&usbd_free_requests);
277 if (reqh)
278 SIMPLEQ_REMOVE_HEAD(&usbd_free_requests, reqh, next);
279 else
280 reqh = malloc(sizeof(*reqh), M_USB, M_NOWAIT);
281 if (!reqh)
282 return (0);
283 memset(reqh, 0, sizeof *reqh);
284 DPRINTFN(1,("usbd_alloc_request() = %p\n", reqh));
285 return (reqh);
286 }
287
288 usbd_status
289 usbd_free_request(reqh)
290 usbd_request_handle reqh;
291 {
292 DPRINTFN(1,("usbd_free_request: %p\n", reqh));
293 SIMPLEQ_INSERT_HEAD(&usbd_free_requests, reqh, next);
294 return (USBD_NORMAL_COMPLETION);
295 }
296
297 usbd_status
298 usbd_setup_request(reqh, pipe, priv, buffer, length, flags, timeout, callback)
299 usbd_request_handle reqh;
300 usbd_pipe_handle pipe;
301 usbd_private_handle priv;
302 void *buffer;
303 u_int32_t length;
304 u_int16_t flags;
305 u_int32_t timeout;
306 void (*callback) __P((usbd_request_handle,
307 usbd_private_handle,
308 usbd_status));
309 {
310 reqh->pipe = pipe;
311 reqh->priv = priv;
312 reqh->buffer = buffer;
313 reqh->length = length;
314 reqh->actlen = 0;
315 reqh->flags = flags;
316 reqh->timeout = timeout;
317 reqh->status = USBD_NOT_STARTED;
318 reqh->callback = callback;
319 reqh->isreq = 0;
320 return (USBD_NORMAL_COMPLETION);
321 }
322
323 usbd_status
324 usbd_setup_default_request(reqh, dev, priv, timeout, req, buffer,
325 length, flags, callback)
326 usbd_request_handle reqh;
327 usbd_device_handle dev;
328 usbd_private_handle priv;
329 u_int32_t timeout;
330 usb_device_request_t *req;
331 void *buffer;
332 u_int32_t length;
333 u_int16_t flags;
334 void (*callback) __P((usbd_request_handle,
335 usbd_private_handle,
336 usbd_status));
337 {
338 reqh->pipe = dev->default_pipe;
339 reqh->priv = priv;
340 reqh->buffer = buffer;
341 reqh->length = length;
342 reqh->actlen = 0;
343 reqh->flags = flags;
344 reqh->timeout = timeout;
345 reqh->status = USBD_NOT_STARTED;
346 reqh->callback = callback;
347 reqh->request = *req;
348 reqh->isreq = 1;
349 return (USBD_NORMAL_COMPLETION);
350 }
351
352 void
353 usbd_get_request_status(reqh, priv, buffer, count, status)
354 usbd_request_handle reqh;
355 usbd_private_handle *priv;
356 void **buffer;
357 u_int32_t *count;
358 usbd_status *status;
359 {
360 if (priv)
361 *priv = reqh->priv;
362 if (buffer)
363 *buffer = reqh->buffer;
364 if (count)
365 *count = reqh->actlen;
366 if (status)
367 *status = reqh->status;
368 }
369
370 usb_config_descriptor_t *
371 usbd_get_config_descriptor(dev)
372 usbd_device_handle dev;
373 {
374 return (dev->cdesc);
375 }
376
377 usb_interface_descriptor_t *
378 usbd_get_interface_descriptor(iface)
379 usbd_interface_handle iface;
380 {
381 return (iface->idesc);
382 }
383
384 usb_device_descriptor_t *
385 usbd_get_device_descriptor(dev)
386 usbd_device_handle dev;
387 {
388 return (&dev->ddesc);
389 }
390
391 usb_endpoint_descriptor_t *
392 usbd_interface2endpoint_descriptor(iface, index)
393 usbd_interface_handle iface;
394 u_int8_t index;
395 {
396 if (index >= iface->idesc->bNumEndpoints)
397 return (0);
398 return (iface->endpoints[index].edesc);
399 }
400
401 usbd_status
402 usbd_abort_pipe(pipe)
403 usbd_pipe_handle pipe;
404 {
405 usbd_status r;
406 int s;
407
408 #ifdef DIAGNOSTIC
409 if (pipe == 0) {
410 printf("usbd_close_pipe: pipe==NULL\n");
411 return (USBD_NORMAL_COMPLETION);
412 }
413 #endif
414 s = splusb();
415 r = usbd_ar_pipe(pipe);
416 splx(s);
417 return (r);
418 }
419
420 usbd_status
421 usbd_clear_endpoint_stall(pipe)
422 usbd_pipe_handle pipe;
423 {
424 usbd_device_handle dev = pipe->device;
425 usb_device_request_t req;
426 usbd_status r;
427
428 DPRINTFN(8, ("usbd_clear_endpoint_stall\n"));
429
430 /*
431 * Clearing en endpoint stall resets the enpoint toggle, so
432 * do the same to the HC toggle.
433 */
434 pipe->methods->cleartoggle(pipe);
435
436 req.bmRequestType = UT_WRITE_ENDPOINT;
437 req.bRequest = UR_CLEAR_FEATURE;
438 USETW(req.wValue, UF_ENDPOINT_HALT);
439 USETW(req.wIndex, pipe->endpoint->edesc->bEndpointAddress);
440 USETW(req.wLength, 0);
441 r = usbd_do_request(dev, &req, 0);
442 #if 0
443 XXX should we do this?
444 if (r == USBD_NORMAL_COMPLETION) {
445 pipe->state = USBD_PIPE_ACTIVE;
446 /* XXX activate pipe */
447 }
448 #endif
449 return (r);
450 }
451
452 usbd_status
453 usbd_clear_endpoint_stall_async(pipe)
454 usbd_pipe_handle pipe;
455 {
456 usbd_device_handle dev = pipe->device;
457 usb_device_request_t req;
458 usbd_status r;
459
460 pipe->methods->cleartoggle(pipe);
461
462 req.bmRequestType = UT_WRITE_ENDPOINT;
463 req.bRequest = UR_CLEAR_FEATURE;
464 USETW(req.wValue, UF_ENDPOINT_HALT);
465 USETW(req.wIndex, pipe->endpoint->edesc->bEndpointAddress);
466 USETW(req.wLength, 0);
467 r = usbd_do_request_async(dev, &req, 0);
468 return (r);
469 }
470
471 usbd_status
472 usbd_endpoint_count(iface, count)
473 usbd_interface_handle iface;
474 u_int8_t *count;
475 {
476 *count = iface->idesc->bNumEndpoints;
477 return (USBD_NORMAL_COMPLETION);
478 }
479
480 usbd_status
481 usbd_interface_count(dev, count)
482 usbd_device_handle dev;
483 u_int8_t *count;
484 {
485 if (!dev->cdesc)
486 return (USBD_NOT_CONFIGURED);
487 *count = dev->cdesc->bNumInterface;
488 return (USBD_NORMAL_COMPLETION);
489 }
490
491 usbd_status
492 usbd_interface2device_handle(iface, dev)
493 usbd_interface_handle iface;
494 usbd_device_handle *dev;
495 {
496 *dev = iface->device;
497 return (USBD_NORMAL_COMPLETION);
498 }
499
500 usbd_status
501 usbd_device2interface_handle(dev, ifaceno, iface)
502 usbd_device_handle dev;
503 u_int8_t ifaceno;
504 usbd_interface_handle *iface;
505 {
506 if (!dev->cdesc)
507 return (USBD_NOT_CONFIGURED);
508 if (ifaceno >= dev->cdesc->bNumInterface)
509 return (USBD_INVAL);
510 *iface = &dev->ifaces[ifaceno];
511 return (USBD_NORMAL_COMPLETION);
512 }
513
514 /* XXXX use altno */
515 usbd_status
516 usbd_set_interface(iface, altidx)
517 usbd_interface_handle iface;
518 int altidx;
519 {
520 usb_device_request_t req;
521 usbd_status r;
522
523 if (LIST_FIRST(&iface->pipes) != 0)
524 return (USBD_IN_USE);
525
526 if (iface->endpoints)
527 free(iface->endpoints, M_USB);
528 iface->endpoints = 0;
529 iface->idesc = 0;
530
531 r = usbd_fill_iface_data(iface->device, iface->index, altidx);
532 if (r != USBD_NORMAL_COMPLETION)
533 return (r);
534
535 req.bmRequestType = UT_WRITE_INTERFACE;
536 req.bRequest = UR_SET_INTERFACE;
537 USETW(req.wValue, iface->idesc->bAlternateSetting);
538 USETW(req.wIndex, iface->idesc->bInterfaceNumber);
539 USETW(req.wLength, 0);
540 return usbd_do_request(iface->device, &req, 0);
541 }
542
543 int
544 usbd_get_no_alts(cdesc, ifaceno)
545 usb_config_descriptor_t *cdesc;
546 int ifaceno;
547 {
548 char *p = (char *)cdesc;
549 char *end = p + UGETW(cdesc->wTotalLength);
550 usb_interface_descriptor_t *d;
551 int n;
552
553 for (n = 0; p < end; p += d->bLength) {
554 d = (usb_interface_descriptor_t *)p;
555 if (p + d->bLength <= end &&
556 d->bDescriptorType == UDESC_INTERFACE &&
557 d->bInterfaceNumber == ifaceno)
558 n++;
559 }
560 return (n);
561 }
562
563 int
564 usbd_get_interface_altindex(iface)
565 usbd_interface_handle iface;
566 {
567 return (iface->altindex);
568 }
569
570 usbd_status
571 usbd_get_interface(iface, aiface)
572 usbd_interface_handle iface;
573 u_int8_t *aiface;
574 {
575 usb_device_request_t req;
576
577 req.bmRequestType = UT_READ_INTERFACE;
578 req.bRequest = UR_GET_INTERFACE;
579 USETW(req.wValue, 0);
580 USETW(req.wIndex, iface->idesc->bInterfaceNumber);
581 USETW(req.wLength, 1);
582 return usbd_do_request(iface->device, &req, aiface);
583 }
584
585 /*** Internal routines ***/
586
587 /* Dequeue all pipe operations, called at splusb(). */
588 static usbd_status
589 usbd_ar_pipe(pipe)
590 usbd_pipe_handle pipe;
591 {
592 usbd_request_handle reqh;
593
594 DPRINTFN(2,("usbd_ar_pipe: pipe=%p\n", pipe));
595 #ifdef USB_DEBUG
596 if (usbdebug > 5)
597 usbd_dump_queue(pipe);
598 #endif
599 while ((reqh = SIMPLEQ_FIRST(&pipe->queue))) {
600 DPRINTFN(2,("usbd_ar_pipe: pipe=%p reqh=%p (methods=%p)\n",
601 pipe, reqh, pipe->methods));
602 /* Make the HC abort it (and invoke the callback). */
603 pipe->methods->abort(reqh);
604 /* XXX only for non-0 usbd_clear_endpoint_stall(pipe); */
605 }
606 return (USBD_NORMAL_COMPLETION);
607 }
608
609 static int usbd_global_init_done = 0;
610
611 void
612 usbd_init()
613 {
614 #if defined(__FreeBSD__)
615 dev_t dev;
616 #endif
617
618 if (!usbd_global_init_done) {
619 usbd_global_init_done = 1;
620 SIMPLEQ_INIT(&usbd_free_requests);
621
622 #if defined(__FreeBSD__)
623 dev = makedev(USB_CDEV_MAJOR, 0);
624 cdevsw_add(&dev, &usb_cdevsw, NULL);
625 #endif
626 }
627 }
628
629 void
630 usb_transfer_complete(reqh)
631 usbd_request_handle reqh;
632 {
633 usbd_pipe_handle pipe = reqh->pipe;
634 int polling;
635
636 DPRINTFN(5, ("usb_transfer_complete: pipe=%p reqh=%p actlen=%d\n",
637 pipe, reqh, reqh->actlen));
638
639 #ifdef DIAGNOSTIC
640 if (!pipe) {
641 printf("usbd_transfer_cb: pipe==0, reqh=%p\n", reqh);
642 return;
643 }
644 #endif
645 polling = reqh->pipe->device->bus->use_polling;
646 /* XXXX */
647 if (polling)
648 pipe->running = 0;
649
650 if (reqh->pipe->methods->done)
651 reqh->pipe->methods->done(reqh);
652
653 /* Remove request from queue. */
654 SIMPLEQ_REMOVE_HEAD(&pipe->queue, reqh, next);
655
656 /* Count completed transfers. */
657 ++pipe->device->bus->stats.requests
658 [pipe->endpoint->edesc->bmAttributes & UE_XFERTYPE];
659
660 reqh->done = 1;
661 if (reqh->status == USBD_NORMAL_COMPLETION &&
662 reqh->actlen < reqh->length &&
663 !(reqh->flags & USBD_SHORT_XFER_OK)) {
664 DPRINTFN(-1, ("usbd_transfer_cb: short xfer %d<%d (bytes)\n",
665 reqh->actlen, reqh->length));
666 reqh->status = USBD_SHORT_XFER;
667 }
668
669 if (reqh->callback)
670 reqh->callback(reqh, reqh->priv, reqh->status);
671
672 if ((reqh->flags & USBD_SYNCHRONOUS) && !polling)
673 wakeup(reqh);
674
675 if (!pipe->repeat &&
676 reqh->status != USBD_CANCELLED && reqh->status != USBD_TIMEOUT)
677 usbd_start_next(pipe);
678 }
679
680 usbd_status
681 usb_insert_transfer(reqh)
682 usbd_request_handle reqh;
683 {
684 usbd_pipe_handle pipe = reqh->pipe;
685
686 DPRINTFN(5,("usb_insert_transfer: pipe=%p running=%d\n", pipe,
687 pipe->running));
688 SIMPLEQ_INSERT_TAIL(&pipe->queue, reqh, next);
689 if (pipe->running)
690 return (USBD_IN_PROGRESS);
691 pipe->running = 1;
692 return (USBD_NORMAL_COMPLETION);
693 }
694
695 void
696 usbd_start_next(pipe)
697 usbd_pipe_handle pipe;
698 {
699 usbd_request_handle reqh;
700 usbd_status r;
701
702 DPRINTFN(10, ("usbd_start_next: pipe=%p\n", pipe));
703
704 #ifdef DIAGNOSTIC
705 if (!pipe) {
706 printf("usbd_start_next: pipe == 0\n");
707 return;
708 }
709 if (!pipe->methods || !pipe->methods->start) {
710 printf("usbd_start_next: no start method\n");
711 return;
712 }
713 #endif
714
715 /* Get next request in queue. */
716 reqh = SIMPLEQ_FIRST(&pipe->queue);
717 DPRINTFN(5, ("usbd_start_next: pipe=%p start reqh=%p\n", pipe, reqh));
718 if (!reqh)
719 pipe->running = 0;
720 else {
721 r = pipe->methods->start(reqh);
722 if (r != USBD_IN_PROGRESS) {
723 printf("usbd_start_next: error=%d\n", r);
724 pipe->running = 0;
725 /* XXX do what? */
726 }
727 }
728 }
729
730 usbd_status
731 usbd_do_request(dev, req, data)
732 usbd_device_handle dev;
733 usb_device_request_t *req;
734 void *data;
735 {
736 return (usbd_do_request_flags(dev, req, data, 0, 0));
737 }
738
739 usbd_status
740 usbd_do_request_flags(dev, req, data, flags, actlen)
741 usbd_device_handle dev;
742 usb_device_request_t *req;
743 void *data;
744 u_int16_t flags;
745 int *actlen;
746 {
747 usbd_request_handle reqh;
748 usbd_status r;
749
750 #ifdef DIAGNOSTIC
751 if (!curproc) {
752 printf("usbd_do_request: not in process context\n");
753 return (USBD_XXX);
754 }
755 #endif
756
757 reqh = usbd_alloc_request();
758 if (reqh == 0)
759 return (USBD_NOMEM);
760 r = usbd_setup_default_request(
761 reqh, dev, 0, USBD_DEFAULT_TIMEOUT, req, data,
762 UGETW(req->wLength), flags, 0);
763 if (r != USBD_NORMAL_COMPLETION)
764 goto bad;
765 r = usbd_sync_transfer(reqh);
766 #if defined(USB_DEBUG) || defined(DIAGNOSTIC)
767 if (reqh->actlen > reqh->length)
768 printf("usbd_do_request: overrun addr=%d type=0x%02x req=0x"
769 "%02x val=%d index=%d rlen=%d length=%d actlen=%d\n",
770 dev->address, reqh->request.bmRequestType,
771 reqh->request.bRequest, UGETW(reqh->request.wValue),
772 UGETW(reqh->request.wIndex),
773 UGETW(reqh->request.wLength),
774 reqh->length, reqh->actlen);
775 #endif
776 if (actlen)
777 *actlen = reqh->actlen;
778 if (r == USBD_STALLED) {
779 /*
780 * The control endpoint has stalled. Control endpoints
781 * should not halt, but some may do so anyway so clear
782 * any halt condition.
783 */
784 usb_device_request_t treq;
785 usb_status_t status;
786 u_int16_t s;
787 usbd_status nr;
788
789 treq.bmRequestType = UT_READ_ENDPOINT;
790 treq.bRequest = UR_GET_STATUS;
791 USETW(treq.wValue, 0);
792 USETW(treq.wIndex, 0);
793 USETW(treq.wLength, sizeof(usb_status_t));
794 nr = usbd_setup_default_request(
795 reqh, dev, 0, USBD_DEFAULT_TIMEOUT, &treq, &status,
796 sizeof(usb_status_t), 0, 0);
797 if (nr != USBD_NORMAL_COMPLETION)
798 goto bad;
799 nr = usbd_sync_transfer(reqh);
800 if (nr != USBD_NORMAL_COMPLETION)
801 goto bad;
802 s = UGETW(status.wStatus);
803 DPRINTF(("usbd_do_request: status = 0x%04x\n", s));
804 if (!(s & UES_HALT))
805 goto bad;
806 treq.bmRequestType = UT_WRITE_ENDPOINT;
807 treq.bRequest = UR_CLEAR_FEATURE;
808 USETW(treq.wValue, UF_ENDPOINT_HALT);
809 USETW(treq.wIndex, 0);
810 USETW(treq.wLength, 0);
811 nr = usbd_setup_default_request(
812 reqh, dev, 0, USBD_DEFAULT_TIMEOUT, &treq, &status,
813 0, 0, 0);
814 if (nr != USBD_NORMAL_COMPLETION)
815 goto bad;
816 nr = usbd_sync_transfer(reqh);
817 if (nr != USBD_NORMAL_COMPLETION)
818 goto bad;
819 }
820
821 bad:
822 usbd_free_request(reqh);
823 return (r);
824 }
825
826 void
827 usbd_do_request_async_cb(reqh, priv, status)
828 usbd_request_handle reqh;
829 usbd_private_handle priv;
830 usbd_status status;
831 {
832 #if defined(USB_DEBUG) || defined(DIAGNOSTIC)
833 if (reqh->actlen > reqh->length)
834 printf("usbd_do_request: overrun addr=%d type=0x%02x req=0x"
835 "%02x val=%d index=%d rlen=%d length=%d actlen=%d\n",
836 reqh->pipe->device->address,
837 reqh->request.bmRequestType,
838 reqh->request.bRequest, UGETW(reqh->request.wValue),
839 UGETW(reqh->request.wIndex),
840 UGETW(reqh->request.wLength),
841 reqh->length, reqh->actlen);
842 #endif
843 usbd_free_request(reqh);
844 }
845
846 /*
847 * Execute a request without waiting for completion.
848 * Can be used from interrupt context.
849 */
850 usbd_status
851 usbd_do_request_async(dev, req, data)
852 usbd_device_handle dev;
853 usb_device_request_t *req;
854 void *data;
855 {
856 usbd_request_handle reqh;
857 usbd_status r;
858
859 reqh = usbd_alloc_request();
860 if (reqh == 0)
861 return (USBD_NOMEM);
862 r = usbd_setup_default_request(
863 reqh, dev, 0, USBD_DEFAULT_TIMEOUT, req, data,
864 UGETW(req->wLength), 0, usbd_do_request_async_cb);
865 if (r != USBD_NORMAL_COMPLETION) {
866 usbd_free_request(reqh);
867 return (r);
868 }
869 r = usbd_transfer(reqh);
870 if (r != USBD_IN_PROGRESS)
871 return (r);
872 return (USBD_NORMAL_COMPLETION);
873 }
874
875 struct usbd_quirks *
876 usbd_get_quirks(dev)
877 usbd_device_handle dev;
878 {
879 return (dev->quirks);
880 }
881
882 /* XXX do periodic free() of free list */
883
884 /*
885 * Called from keyboard driver when in polling mode.
886 */
887 void
888 usbd_dopoll(iface)
889 usbd_interface_handle iface;
890 {
891 iface->device->bus->do_poll(iface->device->bus);
892 }
893
894 void
895 usbd_set_polling(iface, on)
896 usbd_interface_handle iface;
897 int on;
898 {
899 iface->device->bus->use_polling = on;
900 }
901
902
903 usb_endpoint_descriptor_t *
904 usbd_get_endpoint_descriptor(iface, address)
905 usbd_interface_handle iface;
906 u_int8_t address;
907 {
908 struct usbd_endpoint *ep;
909 int i;
910
911 for (i = 0; i < iface->idesc->bNumEndpoints; i++) {
912 ep = &iface->endpoints[i];
913 if (ep->edesc->bEndpointAddress == address)
914 return (iface->endpoints[i].edesc);
915 }
916 return (0);
917 }
918
919 #if defined(__FreeBSD__)
920 void
921 usbd_print_child(device_t parent, device_t child)
922 {
923 /*
924 struct usb_softc *sc = device_get_softc(child);
925 */
926
927 printf(" at %s%d", device_get_name(parent), device_get_unit(parent));
928
929 /* XXX How do we get to the usbd_device_handle???
930 usbd_device_handle dev = invalidadosch;
931
932 printf(" addr %d", dev->addr);
933
934 if (bootverbose) {
935 if (dev->lowspeed)
936 printf(", lowspeed");
937 if (dev->self_powered)
938 printf(", self powered");
939 else
940 printf(", %dmA", dev->power);
941 printf(", config %d", dev->config);
942 }
943 */
944 }
945
946 /* Reconfigure all the USB busses in the system. */
947 int
948 usbd_driver_load(module_t mod, int what, void *arg)
949 {
950 devclass_t usb_devclass = devclass_find("usb");
951 devclass_t ugen_devclass = devclass_find("ugen");
952 device_t *devlist;
953 int devcount;
954 int error;
955
956 switch (what) {
957 case MOD_LOAD:
958 case MOD_UNLOAD:
959 if (!usb_devclass)
960 return 0; /* just ignore call */
961
962 if (ugen_devclass) {
963 /* detach devices from generic driver if possible */
964 error = devclass_get_devices(ugen_devclass, &devlist,
965 &devcount);
966 if (!error)
967 for (devcount--; devcount >= 0; devcount--)
968 (void)DEVICE_DETACH(devlist[devcount]);
969 }
970
971 error = devclass_get_devices(usb_devclass, &devlist, &devcount);
972 if (error)
973 return 0; /* XXX maybe transient, or error? */
974
975 for (devcount--; devcount >= 0; devcount--)
976 USB_RECONFIGURE(devlist[devcount]);
977
978 free(devlist, M_TEMP);
979 return 0;
980 }
981
982 return 0; /* nothing to do by us */
983 }
984
985 /* Set the description of the device including a malloc and copy. */
986 void
987 usbd_device_set_desc(device_t device, char *devinfo)
988 {
989 size_t l;
990 char *desc;
991
992 if ( devinfo ) {
993 l = strlen(devinfo);
994 desc = malloc(l+1, M_USB, M_NOWAIT);
995 if (desc)
996 memcpy(desc, devinfo, l+1);
997 } else
998 desc = NULL;
999
1000 device_set_desc(device, desc);
1001 }
1002
1003 char *
1004 usbd_devname(bdevice *bdev)
1005 {
1006 static char buf[20];
1007 /*
1008 * A static buffer is a loss if this routine is used from an interrupt,
1009 * but it's not fatal.
1010 */
1011
1012 sprintf(buf, "%s%d", device_get_name(*bdev), device_get_unit(*bdev));
1013 return (buf);
1014 }
1015
1016 #endif
1017