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