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