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