usbdi.c revision 1.39 1 /* $NetBSD: usbdi.c,v 1.39 1999/09/13 19:18:17 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 DPRINTFN(2,("usbd_ar_pipe: pipe=%p\n", pipe));
685 #ifdef USB_DEBUG
686 if (usbdebug > 5)
687 usbd_dump_queue(pipe);
688 #endif
689 while ((reqh = SIMPLEQ_FIRST(&pipe->queue))) {
690 DPRINTFN(2,("usbd_ar_pipe: pipe=%p reqh=%p (methods=%p)\n",
691 pipe, reqh, pipe->methods));
692 /* Make the HC abort it (and invoke the callback). */
693 pipe->methods->abort(reqh);
694 /* XXX only for non-0 usbd_clear_endpoint_stall(pipe); */
695 }
696 return (USBD_NORMAL_COMPLETION);
697 }
698
699 static int usbd_global_init_done = 0;
700
701 void
702 usbd_init()
703 {
704 #if defined(__FreeBSD__)
705 dev_t dev;
706 #endif
707
708 if (!usbd_global_init_done) {
709 usbd_global_init_done = 1;
710 SIMPLEQ_INIT(&usbd_free_requests);
711
712 #if defined(__FreeBSD__)
713 dev = makedev(USB_CDEV_MAJOR, 0);
714 cdevsw_add(&dev, &usb_cdevsw, NULL);
715 #endif
716 }
717 }
718
719 void
720 usb_transfer_complete(reqh)
721 usbd_request_handle reqh;
722 {
723 usbd_pipe_handle pipe = reqh->pipe;
724 usb_dma_t *dmap = &reqh->dmabuf;
725 int polling;
726
727 DPRINTFN(5, ("usb_transfer_complete: pipe=%p reqh=%p actlen=%d\n",
728 pipe, reqh, reqh->actlen));
729
730 #ifdef DIAGNOSTIC
731 if (!pipe) {
732 printf("usbd_transfer_cb: pipe==0, reqh=%p\n", reqh);
733 return;
734 }
735 #endif
736 polling = pipe->device->bus->use_polling;
737 /* XXXX */
738 if (polling)
739 pipe->running = 0;
740
741 if (!(reqh->flags & USBD_NO_COPY) && reqh->actlen != 0 &&
742 usbd_reqh_isread(reqh))
743 memcpy(reqh->buffer, KERNADDR(dmap), reqh->actlen);
744
745 /* if we allocated the buffer in usbd_transfer() we free it here. */
746 if (reqh->rqflags & URQ_AUTO_DMABUF) {
747 if (!pipe->repeat) {
748 struct usbd_bus *bus = pipe->device->bus;
749 bus->methods->freem(bus, dmap);
750 reqh->rqflags &= ~URQ_AUTO_DMABUF;
751 }
752 }
753
754 if (pipe->methods->done)
755 pipe->methods->done(reqh);
756
757 /* Remove request from queue. */
758 SIMPLEQ_REMOVE_HEAD(&pipe->queue, reqh, next);
759
760 /* Count completed transfers. */
761 ++pipe->device->bus->stats.requests
762 [pipe->endpoint->edesc->bmAttributes & UE_XFERTYPE];
763
764 reqh->done = 1;
765 if (reqh->status == USBD_NORMAL_COMPLETION &&
766 reqh->actlen < reqh->length &&
767 !(reqh->flags & USBD_SHORT_XFER_OK)) {
768 DPRINTFN(-1, ("usbd_transfer_cb: short xfer %d<%d (bytes)\n",
769 reqh->actlen, reqh->length));
770 reqh->status = USBD_SHORT_XFER;
771 }
772
773 if (reqh->callback)
774 reqh->callback(reqh, reqh->priv, reqh->status);
775
776 if ((reqh->flags & USBD_SYNCHRONOUS) && !polling)
777 wakeup(reqh);
778
779 if (!pipe->repeat &&
780 reqh->status != USBD_CANCELLED && reqh->status != USBD_TIMEOUT)
781 usbd_start_next(pipe);
782 }
783
784 usbd_status
785 usb_insert_transfer(reqh)
786 usbd_request_handle reqh;
787 {
788 usbd_pipe_handle pipe = reqh->pipe;
789 usbd_status r;
790 int s;
791
792 DPRINTFN(5,("usb_insert_transfer: pipe=%p running=%d\n", pipe,
793 pipe->running));
794 s = splusb();
795 SIMPLEQ_INSERT_TAIL(&pipe->queue, reqh, next);
796 if (pipe->running)
797 r = USBD_IN_PROGRESS;
798 else {
799 pipe->running = 1;
800 r = USBD_NORMAL_COMPLETION;
801 }
802 splx(s);
803 return (r);
804 }
805
806 void
807 usbd_start_next(pipe)
808 usbd_pipe_handle pipe;
809 {
810 usbd_request_handle reqh;
811 usbd_status r;
812
813 DPRINTFN(10, ("usbd_start_next: pipe=%p\n", pipe));
814
815 #ifdef DIAGNOSTIC
816 if (!pipe) {
817 printf("usbd_start_next: pipe == 0\n");
818 return;
819 }
820 if (!pipe->methods || !pipe->methods->start) {
821 printf("usbd_start_next: no start method\n");
822 return;
823 }
824 #endif
825
826 /* Get next request in queue. */
827 reqh = SIMPLEQ_FIRST(&pipe->queue);
828 DPRINTFN(5, ("usbd_start_next: pipe=%p start reqh=%p\n", pipe, reqh));
829 if (!reqh)
830 pipe->running = 0;
831 else {
832 r = pipe->methods->start(reqh);
833 if (r != USBD_IN_PROGRESS) {
834 printf("usbd_start_next: error=%d\n", r);
835 pipe->running = 0;
836 /* XXX do what? */
837 }
838 }
839 }
840
841 usbd_status
842 usbd_do_request(dev, req, data)
843 usbd_device_handle dev;
844 usb_device_request_t *req;
845 void *data;
846 {
847 return (usbd_do_request_flags(dev, req, data, 0, 0));
848 }
849
850 usbd_status
851 usbd_do_request_flags(dev, req, data, flags, actlen)
852 usbd_device_handle dev;
853 usb_device_request_t *req;
854 void *data;
855 u_int16_t flags;
856 int *actlen;
857 {
858 usbd_request_handle reqh;
859 usbd_status r;
860
861 #ifdef DIAGNOSTIC
862 if (dev->bus->intr_context) {
863 printf("usbd_do_request: not in process context\n");
864 return (USBD_INVAL);
865 }
866 #endif
867
868 reqh = usbd_alloc_request(dev);
869 if (reqh == 0)
870 return (USBD_NOMEM);
871 usbd_setup_default_request(reqh, dev, 0, USBD_DEFAULT_TIMEOUT, req,
872 data, UGETW(req->wLength), flags, 0);
873 r = usbd_sync_transfer(reqh);
874 #if defined(USB_DEBUG) || defined(DIAGNOSTIC)
875 if (reqh->actlen > reqh->length)
876 DPRINTF(("usbd_do_request: overrun addr=%d type=0x%02x req=0x"
877 "%02x val=%d index=%d rlen=%d length=%d actlen=%d\n",
878 dev->address, reqh->request.bmRequestType,
879 reqh->request.bRequest, UGETW(reqh->request.wValue),
880 UGETW(reqh->request.wIndex),
881 UGETW(reqh->request.wLength),
882 reqh->length, reqh->actlen));
883 #endif
884 if (actlen)
885 *actlen = reqh->actlen;
886 if (r == USBD_STALLED) {
887 /*
888 * The control endpoint has stalled. Control endpoints
889 * should not halt, but some may do so anyway so clear
890 * any halt condition.
891 */
892 usb_device_request_t treq;
893 usb_status_t status;
894 u_int16_t s;
895 usbd_status nr;
896
897 treq.bmRequestType = UT_READ_ENDPOINT;
898 treq.bRequest = UR_GET_STATUS;
899 USETW(treq.wValue, 0);
900 USETW(treq.wIndex, 0);
901 USETW(treq.wLength, sizeof(usb_status_t));
902 usbd_setup_default_request(reqh, dev, 0, USBD_DEFAULT_TIMEOUT,
903 &treq, &status,sizeof(usb_status_t),
904 0, 0);
905 nr = usbd_sync_transfer(reqh);
906 if (nr != USBD_NORMAL_COMPLETION)
907 goto bad;
908 s = UGETW(status.wStatus);
909 DPRINTF(("usbd_do_request: status = 0x%04x\n", s));
910 if (!(s & UES_HALT))
911 goto bad;
912 treq.bmRequestType = UT_WRITE_ENDPOINT;
913 treq.bRequest = UR_CLEAR_FEATURE;
914 USETW(treq.wValue, UF_ENDPOINT_HALT);
915 USETW(treq.wIndex, 0);
916 USETW(treq.wLength, 0);
917 usbd_setup_default_request(reqh, dev, 0, USBD_DEFAULT_TIMEOUT,
918 &treq, &status, 0, 0, 0);
919 nr = usbd_sync_transfer(reqh);
920 if (nr != USBD_NORMAL_COMPLETION)
921 goto bad;
922 }
923
924 bad:
925 usbd_free_request(reqh);
926 return (r);
927 }
928
929 void
930 usbd_do_request_async_cb(reqh, priv, status)
931 usbd_request_handle reqh;
932 usbd_private_handle priv;
933 usbd_status status;
934 {
935 #if defined(USB_DEBUG) || defined(DIAGNOSTIC)
936 if (reqh->actlen > reqh->length)
937 DPRINTF(("usbd_do_request: overrun addr=%d type=0x%02x req=0x"
938 "%02x val=%d index=%d rlen=%d length=%d actlen=%d\n",
939 reqh->pipe->device->address,
940 reqh->request.bmRequestType,
941 reqh->request.bRequest, UGETW(reqh->request.wValue),
942 UGETW(reqh->request.wIndex),
943 UGETW(reqh->request.wLength),
944 reqh->length, reqh->actlen));
945 #endif
946 usbd_free_request(reqh);
947 }
948
949 /*
950 * Execute a request without waiting for completion.
951 * Can be used from interrupt context.
952 */
953 usbd_status
954 usbd_do_request_async(dev, req, data)
955 usbd_device_handle dev;
956 usb_device_request_t *req;
957 void *data;
958 {
959 usbd_request_handle reqh;
960 usbd_status r;
961
962 reqh = usbd_alloc_request(dev);
963 if (reqh == 0)
964 return (USBD_NOMEM);
965 usbd_setup_default_request(reqh, dev, 0, USBD_DEFAULT_TIMEOUT, req, data,
966 UGETW(req->wLength), 0,
967 usbd_do_request_async_cb);
968 r = usbd_transfer(reqh);
969 if (r != USBD_IN_PROGRESS) {
970 usbd_free_request(reqh);
971 return (r);
972 }
973 return (USBD_NORMAL_COMPLETION);
974 }
975
976 struct usbd_quirks *
977 usbd_get_quirks(dev)
978 usbd_device_handle dev;
979 {
980 return (dev->quirks);
981 }
982
983 /* XXX do periodic free() of free list */
984
985 /*
986 * Called from keyboard driver when in polling mode.
987 */
988 void
989 usbd_dopoll(iface)
990 usbd_interface_handle iface;
991 {
992 iface->device->bus->methods->do_poll(iface->device->bus);
993 }
994
995 void
996 usbd_set_polling(iface, on)
997 usbd_interface_handle iface;
998 int on;
999 {
1000 iface->device->bus->use_polling = on;
1001 }
1002
1003
1004 usb_endpoint_descriptor_t *
1005 usbd_get_endpoint_descriptor(iface, address)
1006 usbd_interface_handle iface;
1007 u_int8_t address;
1008 {
1009 struct usbd_endpoint *ep;
1010 int i;
1011
1012 for (i = 0; i < iface->idesc->bNumEndpoints; i++) {
1013 ep = &iface->endpoints[i];
1014 if (ep->edesc->bEndpointAddress == address)
1015 return (iface->endpoints[i].edesc);
1016 }
1017 return (0);
1018 }
1019
1020 #if defined(__FreeBSD__)
1021 void
1022 usbd_print_child(device_t parent, device_t child)
1023 {
1024 /*
1025 struct usb_softc *sc = device_get_softc(child);
1026 */
1027
1028 printf(" at %s%d", device_get_name(parent), device_get_unit(parent));
1029
1030 /* XXX How do we get to the usbd_device_handle???
1031 usbd_device_handle dev = invalidadosch;
1032
1033 printf(" addr %d", dev->addr);
1034
1035 if (bootverbose) {
1036 if (dev->lowspeed)
1037 printf(", lowspeed");
1038 if (dev->self_powered)
1039 printf(", self powered");
1040 else
1041 printf(", %dmA", dev->power);
1042 printf(", config %d", dev->config);
1043 }
1044 */
1045 }
1046
1047 /* Reconfigure all the USB busses in the system. */
1048 int
1049 usbd_driver_load(module_t mod, int what, void *arg)
1050 {
1051 devclass_t usb_devclass = devclass_find("usb");
1052 devclass_t ugen_devclass = devclass_find("ugen");
1053 device_t *devlist;
1054 int devcount;
1055 int error;
1056
1057 switch (what) {
1058 case MOD_LOAD:
1059 case MOD_UNLOAD:
1060 if (!usb_devclass)
1061 return 0; /* just ignore call */
1062
1063 if (ugen_devclass) {
1064 /* detach devices from generic driver if possible */
1065 error = devclass_get_devices(ugen_devclass, &devlist,
1066 &devcount);
1067 if (!error)
1068 for (devcount--; devcount >= 0; devcount--)
1069 (void)DEVICE_DETACH(devlist[devcount]);
1070 }
1071
1072 error = devclass_get_devices(usb_devclass, &devlist, &devcount);
1073 if (error)
1074 return 0; /* XXX maybe transient, or error? */
1075
1076 for (devcount--; devcount >= 0; devcount--)
1077 USB_RECONFIGURE(devlist[devcount]);
1078
1079 free(devlist, M_TEMP);
1080 return 0;
1081 }
1082
1083 return 0; /* nothing to do by us */
1084 }
1085
1086 /* Set the description of the device including a malloc and copy. */
1087 void
1088 usbd_device_set_desc(device_t device, char *devinfo)
1089 {
1090 size_t l;
1091 char *desc;
1092
1093 if ( devinfo ) {
1094 l = strlen(devinfo);
1095 desc = malloc(l+1, M_USB, M_NOWAIT);
1096 if (desc)
1097 memcpy(desc, devinfo, l+1);
1098 } else
1099 desc = NULL;
1100
1101 device_set_desc(device, desc);
1102 }
1103
1104 char *
1105 usbd_devname(device_t bdev)
1106 {
1107 static char buf[20];
1108 /*
1109 * A static buffer is a loss if this routine is used from an interrupt,
1110 * but it's not fatal.
1111 */
1112
1113 sprintf(buf, "%s%d", device_get_name(bdev), device_get_unit(bdev));
1114 return (buf);
1115 }
1116
1117 #endif
1118