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