Remove the priority part of the priority|flags argument to tsleep(). Only
[dragonfly.git] / sys / bus / usb / usbdi.c
1 /*      $NetBSD: usbdi.c,v 1.60 2000/01/19 00:23:58 augustss Exp $      */
2 /*      $FreeBSD: src/sys/dev/usb/usbdi.c,v 1.34.2.7 2002/11/06 14:03:37 joe Exp $      */
3 /*      $DragonFly: src/sys/bus/usb/usbdi.c,v 1.4 2003/07/19 21:14:30 dillon Exp $      */
4
5 /*
6  * Copyright (c) 1998 The NetBSD Foundation, Inc.
7  * All rights reserved.
8  *
9  * This code is derived from software contributed to The NetBSD Foundation
10  * by Lennart Augustsson (lennart@augustsson.net) at
11  * Carlstedt Research & Technology.
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  * 1. Redistributions of source code must retain the above copyright
17  *    notice, this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in the
20  *    documentation and/or other materials provided with the distribution.
21  * 3. All advertising materials mentioning features or use of this software
22  *    must display the following acknowledgement:
23  *        This product includes software developed by the NetBSD
24  *        Foundation, Inc. and its contributors.
25  * 4. Neither the name of The NetBSD Foundation nor the names of its
26  *    contributors may be used to endorse or promote products derived
27  *    from this software without specific prior written permission.
28  *
29  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
30  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
31  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
32  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
33  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
34  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
35  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
36  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
37  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39  * POSSIBILITY OF SUCH DAMAGE.
40  */
41
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #if defined(__NetBSD__) || defined(__OpenBSD__)
45 #include <sys/device.h>
46 #elif defined(__FreeBSD__)
47 #include <sys/module.h>
48 #include <sys/bus.h>
49 #include "usb_if.h"
50 #if defined(DIAGNOSTIC) && defined(__i386__)
51 #include <machine/cpu.h>
52 #endif
53 #endif
54 #include <sys/malloc.h>
55 #include <sys/proc.h>
56
57 #include <machine/bus.h>
58
59 #include <dev/usb/usb.h>
60 #include <dev/usb/usbdi.h>
61 #include <dev/usb/usbdi_util.h>
62 #include <dev/usb/usbdivar.h>
63 #include <dev/usb/usb_mem.h>
64
65 #if defined(__FreeBSD__)
66 #include "usb_if.h"
67 #include <machine/clock.h>
68 #define delay(d)        DELAY(d)
69 #endif
70
71 #ifdef USB_DEBUG
72 #define DPRINTF(x)      if (usbdebug) logprintf x
73 #define DPRINTFN(n,x)   if (usbdebug>(n)) logprintf x
74 extern int usbdebug;
75 #else
76 #define DPRINTF(x)
77 #define DPRINTFN(n,x)
78 #endif
79
80 Static usbd_status usbd_ar_pipe(usbd_pipe_handle pipe);
81 Static void usbd_do_request_async_cb 
82     (usbd_xfer_handle, usbd_private_handle, usbd_status);
83 Static void usbd_start_next(usbd_pipe_handle pipe);
84 Static usbd_status usbd_open_pipe_ival
85     (usbd_interface_handle, u_int8_t, u_int8_t, usbd_pipe_handle *, int);
86
87 Static int usbd_nbuses = 0;
88
89 void
90 usbd_init(void)
91 {
92         usbd_nbuses++;
93 }
94
95 void
96 usbd_finish(void)
97 {
98         --usbd_nbuses;
99 }
100
101 Static __inline int usbd_xfer_isread(usbd_xfer_handle xfer);
102 Static __inline int
103 usbd_xfer_isread(xfer)
104         usbd_xfer_handle xfer;
105 {
106         if (xfer->rqflags & URQ_REQUEST)
107                 return (xfer->request.bmRequestType & UT_READ);
108         else
109                 return (xfer->pipe->endpoint->edesc->bEndpointAddress &
110                         UE_DIR_IN);
111 }
112
113 #ifdef USB_DEBUG
114 void
115 usbd_dump_queue(usbd_pipe_handle);
116
117 void
118 usbd_dump_queue(usbd_pipe_handle pipe)
119 {
120         usbd_xfer_handle xfer;
121
122         printf("usbd_dump_queue: pipe=%p\n", pipe);
123         for (xfer = SIMPLEQ_FIRST(&pipe->queue);
124              xfer;
125              xfer = SIMPLEQ_NEXT(xfer, next)) {
126                 printf("  xfer=%p\n", xfer);
127         }
128 }
129 #endif
130
131 usbd_status 
132 usbd_open_pipe(usbd_interface_handle iface, u_int8_t address,
133                u_int8_t flags, usbd_pipe_handle *pipe)
134
135         return (usbd_open_pipe_ival(iface, address, flags, pipe, 
136                                     USBD_DEFAULT_INTERVAL));
137 }
138
139 usbd_status 
140 usbd_open_pipe_ival(usbd_interface_handle iface, u_int8_t address,
141                     u_int8_t flags, usbd_pipe_handle *pipe, int ival)
142
143         usbd_pipe_handle p;
144         struct usbd_endpoint *ep;
145         usbd_status err;
146         int i;
147
148         DPRINTFN(3,("usbd_open_pipe: iface=%p address=0x%x flags=0x%x\n",
149                     iface, address, flags));
150
151         for (i = 0; i < iface->idesc->bNumEndpoints; i++) {
152                 ep = &iface->endpoints[i];
153                 if (ep->edesc == NULL)
154                         return (USBD_IOERROR);
155                 if (ep->edesc->bEndpointAddress == address)
156                         goto found;
157         }
158         return (USBD_BAD_ADDRESS);
159  found:
160         if ((flags & USBD_EXCLUSIVE_USE) && ep->refcnt != 0)
161                 return (USBD_IN_USE);
162         err = usbd_setup_pipe(iface->device, iface, ep, ival, &p);
163         if (err)
164                 return (err);
165         LIST_INSERT_HEAD(&iface->pipes, p, next);
166         *pipe = p;
167         return (USBD_NORMAL_COMPLETION);
168 }
169
170 usbd_status 
171 usbd_open_pipe_intr(usbd_interface_handle iface, u_int8_t address,
172                     u_int8_t flags, usbd_pipe_handle *pipe,
173                     usbd_private_handle priv, void *buffer, u_int32_t len,
174                     usbd_callback cb, int ival)
175 {
176         usbd_status err;
177         usbd_xfer_handle xfer;
178         usbd_pipe_handle ipipe;
179
180         DPRINTFN(3,("usbd_open_pipe_intr: address=0x%x flags=0x%x len=%d\n",
181                     address, flags, len));
182
183         err = usbd_open_pipe_ival(iface, address, USBD_EXCLUSIVE_USE, 
184                                   &ipipe, ival);
185         if (err)
186                 return (err);
187         xfer = usbd_alloc_xfer(iface->device);
188         if (xfer == NULL) {
189                 err = USBD_NOMEM;
190                 goto bad1;
191         }
192         usbd_setup_xfer(xfer, ipipe, priv, buffer, len, flags,
193             USBD_NO_TIMEOUT, cb);
194         ipipe->intrxfer = xfer;
195         ipipe->repeat = 1;
196         err = usbd_transfer(xfer);
197         *pipe = ipipe;
198         if (err != USBD_IN_PROGRESS)
199                 goto bad2;
200         return (USBD_NORMAL_COMPLETION);
201
202  bad2:
203         ipipe->intrxfer = NULL;
204         ipipe->repeat = 0;
205         usbd_free_xfer(xfer);
206  bad1:
207         usbd_close_pipe(ipipe);
208         return (err);
209 }
210
211 usbd_status
212 usbd_close_pipe(usbd_pipe_handle pipe)
213 {
214 #ifdef DIAGNOSTIC
215         if (pipe == NULL) {
216                 printf("usbd_close_pipe: pipe==NULL\n");
217                 return (USBD_NORMAL_COMPLETION);
218         }
219 #endif
220
221         if (--pipe->refcnt != 0)
222                 return (USBD_NORMAL_COMPLETION);
223         if (SIMPLEQ_FIRST(&pipe->queue) != 0)
224                 return (USBD_PENDING_REQUESTS);
225         LIST_REMOVE(pipe, next);
226         pipe->endpoint->refcnt--;
227         pipe->methods->close(pipe);
228         if (pipe->intrxfer != NULL)
229                 usbd_free_xfer(pipe->intrxfer);
230         free(pipe, M_USB);
231         return (USBD_NORMAL_COMPLETION);
232 }
233
234 usbd_status
235 usbd_transfer(usbd_xfer_handle xfer)
236 {
237         usbd_pipe_handle pipe = xfer->pipe;
238         usb_dma_t *dmap = &xfer->dmabuf;
239         usbd_status err;
240         u_int size;
241         int s;
242
243         DPRINTFN(5,("usbd_transfer: xfer=%p, flags=%d, pipe=%p, running=%d\n",
244                     xfer, xfer->flags, pipe, pipe->running));
245 #ifdef USB_DEBUG
246         if (usbdebug > 5)
247                 usbd_dump_queue(pipe);
248 #endif
249         xfer->done = 0;
250
251         size = xfer->length;
252         /* If there is no buffer, allocate one. */
253         if (!(xfer->rqflags & URQ_DEV_DMABUF) && size != 0) {
254                 struct usbd_bus *bus = pipe->device->bus;
255
256 #ifdef DIAGNOSTIC
257                 if (xfer->rqflags & URQ_AUTO_DMABUF)
258                         printf("usbd_transfer: has old buffer!\n");
259 #endif
260                 err = bus->methods->allocm(bus, dmap, size);
261                 if (err)
262                         return (err);
263                 xfer->rqflags |= URQ_AUTO_DMABUF;
264         }
265
266         /* Copy data if going out. */
267         if (!(xfer->flags & USBD_NO_COPY) && size != 0 && 
268             !usbd_xfer_isread(xfer))
269                 memcpy(KERNADDR(dmap, 0), xfer->buffer, size);
270
271         err = pipe->methods->transfer(xfer);
272
273         if (err != USBD_IN_PROGRESS && err) {
274                 /* The transfer has not been queued, so free buffer. */
275                 if (xfer->rqflags & URQ_AUTO_DMABUF) {
276                         struct usbd_bus *bus = pipe->device->bus;
277
278                         bus->methods->freem(bus, &xfer->dmabuf);
279                         xfer->rqflags &= ~URQ_AUTO_DMABUF;
280                 }
281         }
282
283         if (!(xfer->flags & USBD_SYNCHRONOUS))
284                 return (err);
285
286         /* Sync transfer, wait for completion. */
287         if (err != USBD_IN_PROGRESS)
288                 return (err);
289         s = splusb();
290         if (!xfer->done) {
291                 if (pipe->device->bus->use_polling)
292                         panic("usbd_transfer: not done\n");
293                 /* XXX Temporary hack XXX */
294                 if (xfer->flags & USBD_NO_TSLEEP) {
295                         int i;
296                         usbd_bus_handle bus = pipe->device->bus;
297                         int to = xfer->timeout * 1000;
298                         for (i = 0; i < to; i += 10) {
299                                 delay(10);
300                                 bus->methods->do_poll(bus);
301                                 if (xfer->done)
302                                         break;
303                         }
304                         if (!xfer->done)
305                                 pipe->methods->abort(xfer);
306                 } else
307                 /* XXX End hack XXX */
308                         tsleep(xfer, 0, "usbsyn", 0);
309         }
310         splx(s);
311         return (xfer->status);
312 }
313
314 /* Like usbd_transfer(), but waits for completion. */
315 usbd_status
316 usbd_sync_transfer(usbd_xfer_handle xfer)
317 {
318         xfer->flags |= USBD_SYNCHRONOUS;
319         return (usbd_transfer(xfer));
320 }
321
322 void *
323 usbd_alloc_buffer(usbd_xfer_handle xfer, u_int32_t size)
324 {
325         struct usbd_bus *bus = xfer->device->bus;
326         usbd_status err;
327
328         err = bus->methods->allocm(bus, &xfer->dmabuf, size);
329         if (err)
330                 return (0);
331         xfer->rqflags |= URQ_DEV_DMABUF;
332         return (KERNADDR(&xfer->dmabuf, 0));
333 }
334
335 void
336 usbd_free_buffer(usbd_xfer_handle xfer)
337 {
338 #ifdef DIAGNOSTIC
339         if (!(xfer->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF))) {
340                 printf("usbd_free_buffer: no buffer\n");
341                 return;
342         }
343 #endif
344         xfer->rqflags &= ~(URQ_DEV_DMABUF | URQ_AUTO_DMABUF);
345         xfer->device->bus->methods->freem(xfer->device->bus, &xfer->dmabuf);
346 }
347
348 void *
349 usbd_get_buffer(usbd_xfer_handle xfer)
350 {
351         if (!(xfer->rqflags & URQ_DEV_DMABUF))
352                 return (0);
353         return (KERNADDR(&xfer->dmabuf, 0));
354 }
355
356 usbd_xfer_handle 
357 usbd_alloc_xfer(usbd_device_handle dev)
358 {
359         usbd_xfer_handle xfer;
360
361         xfer = dev->bus->methods->allocx(dev->bus);
362         if (xfer == NULL)
363                 return (NULL);
364         xfer->device = dev;
365         DPRINTFN(5,("usbd_alloc_xfer() = %p\n", xfer));
366         return (xfer);
367 }
368
369 usbd_status 
370 usbd_free_xfer(usbd_xfer_handle xfer)
371 {
372         DPRINTFN(5,("usbd_free_xfer: %p\n", xfer));
373         if (xfer->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF))
374                 usbd_free_buffer(xfer);
375         xfer->device->bus->methods->freex(xfer->device->bus, xfer);
376         return (USBD_NORMAL_COMPLETION);
377 }
378
379 void
380 usbd_setup_xfer(usbd_xfer_handle xfer, usbd_pipe_handle pipe,
381                 usbd_private_handle priv, void *buffer, u_int32_t length,
382                 u_int16_t flags, u_int32_t timeout,
383                 usbd_callback callback)
384 {
385         xfer->pipe = pipe;
386         xfer->priv = priv;
387         xfer->buffer = buffer;
388         xfer->length = length;
389         xfer->actlen = 0;
390         xfer->flags = flags;
391         xfer->timeout = timeout;
392         xfer->status = USBD_NOT_STARTED;
393         xfer->callback = callback;
394         xfer->rqflags &= ~URQ_REQUEST;
395         xfer->nframes = 0;
396 }
397
398 void
399 usbd_setup_default_xfer(usbd_xfer_handle xfer, usbd_device_handle dev,
400                         usbd_private_handle priv, u_int32_t timeout,
401                         usb_device_request_t *req, void *buffer,
402                         u_int32_t length, u_int16_t flags,
403                         usbd_callback callback)
404 {
405         xfer->pipe = dev->default_pipe;
406         xfer->priv = priv;
407         xfer->buffer = buffer;
408         xfer->length = length;
409         xfer->actlen = 0;
410         xfer->flags = flags;
411         xfer->timeout = timeout;
412         xfer->status = USBD_NOT_STARTED;
413         xfer->callback = callback;
414         xfer->request = *req;
415         xfer->rqflags |= URQ_REQUEST;
416         xfer->nframes = 0;
417 }
418
419 void
420 usbd_setup_isoc_xfer(usbd_xfer_handle xfer, usbd_pipe_handle pipe,
421                      usbd_private_handle priv, u_int16_t *frlengths,
422                      u_int32_t nframes, u_int16_t flags, usbd_callback callback)
423 {
424         xfer->pipe = pipe;
425         xfer->priv = priv;
426         xfer->buffer = 0;
427         xfer->length = 0;
428         xfer->actlen = 0;
429         xfer->flags = flags;
430         xfer->timeout = USBD_NO_TIMEOUT;
431         xfer->status = USBD_NOT_STARTED;
432         xfer->callback = callback;
433         xfer->rqflags &= ~URQ_REQUEST;
434         xfer->frlengths = frlengths;
435         xfer->nframes = nframes;
436 }
437
438 void
439 usbd_get_xfer_status(usbd_xfer_handle xfer, usbd_private_handle *priv,
440                      void **buffer, u_int32_t *count, usbd_status *status)
441 {
442         if (priv != NULL)
443                 *priv = xfer->priv;
444         if (buffer != NULL)
445                 *buffer = xfer->buffer;
446         if (count != NULL)
447                 *count = xfer->actlen;
448         if (status != NULL)
449                 *status = xfer->status;
450 }
451
452 usb_config_descriptor_t *
453 usbd_get_config_descriptor(usbd_device_handle dev)
454 {
455 #ifdef DIAGNOSTIC
456         if (dev == NULL) {
457                 printf("usbd_get_config_descriptor: dev == NULL\n");
458                 return (NULL);
459         }
460 #endif
461         return (dev->cdesc);
462 }
463
464 usb_interface_descriptor_t *
465 usbd_get_interface_descriptor(usbd_interface_handle iface)
466 {
467 #ifdef DIAGNOSTIC
468         if (iface == NULL) {
469                 printf("usbd_get_interface_descriptor: dev == NULL\n");
470                 return (NULL);
471         }
472 #endif
473         return (iface->idesc);
474 }
475
476 usb_device_descriptor_t *
477 usbd_get_device_descriptor(usbd_device_handle dev)
478 {
479         return (&dev->ddesc);
480 }
481
482 usb_endpoint_descriptor_t *
483 usbd_interface2endpoint_descriptor(usbd_interface_handle iface, u_int8_t index)
484 {
485         if (index >= iface->idesc->bNumEndpoints)
486                 return (0);
487         return (iface->endpoints[index].edesc);
488 }
489
490 usbd_status 
491 usbd_abort_pipe(usbd_pipe_handle pipe)
492 {
493         usbd_status err;
494         int s;
495
496 #ifdef DIAGNOSTIC
497         if (pipe == NULL) {
498                 printf("usbd_close_pipe: pipe==NULL\n");
499                 return (USBD_NORMAL_COMPLETION);
500         }
501 #endif
502         s = splusb();
503         err = usbd_ar_pipe(pipe);
504         splx(s);
505         return (err);
506 }
507         
508 usbd_status 
509 usbd_clear_endpoint_stall(usbd_pipe_handle pipe)
510 {
511         usbd_device_handle dev = pipe->device;
512         usb_device_request_t req;
513         usbd_status err;
514
515         DPRINTFN(8, ("usbd_clear_endpoint_stall\n"));
516
517         /* 
518          * Clearing en endpoint stall resets the enpoint toggle, so
519          * do the same to the HC toggle.
520          */
521         pipe->methods->cleartoggle(pipe);
522
523         req.bmRequestType = UT_WRITE_ENDPOINT;
524         req.bRequest = UR_CLEAR_FEATURE;
525         USETW(req.wValue, UF_ENDPOINT_HALT);
526         USETW(req.wIndex, pipe->endpoint->edesc->bEndpointAddress);
527         USETW(req.wLength, 0);
528         err = usbd_do_request(dev, &req, 0);
529 #if 0
530 XXX should we do this?
531         if (!err) {
532                 pipe->state = USBD_PIPE_ACTIVE;
533                 /* XXX activate pipe */
534         }
535 #endif
536         return (err);
537 }
538
539 usbd_status 
540 usbd_clear_endpoint_stall_async(usbd_pipe_handle pipe)
541 {
542         usbd_device_handle dev = pipe->device;
543         usb_device_request_t req;
544         usbd_status err;
545
546         pipe->methods->cleartoggle(pipe);
547
548         req.bmRequestType = UT_WRITE_ENDPOINT;
549         req.bRequest = UR_CLEAR_FEATURE;
550         USETW(req.wValue, UF_ENDPOINT_HALT);
551         USETW(req.wIndex, pipe->endpoint->edesc->bEndpointAddress);
552         USETW(req.wLength, 0);
553         err = usbd_do_request_async(dev, &req, 0);
554         return (err);
555 }
556
557 void
558 usbd_clear_endpoint_toggle(usbd_pipe_handle pipe)
559 {
560         pipe->methods->cleartoggle(pipe);
561 }
562
563
564 usbd_status 
565 usbd_endpoint_count(usbd_interface_handle iface, u_int8_t *count)
566 {
567         *count = iface->idesc->bNumEndpoints;
568         return (USBD_NORMAL_COMPLETION);
569 }
570
571 usbd_status 
572 usbd_interface_count(usbd_device_handle dev, u_int8_t *count)
573 {
574         if (dev->cdesc == NULL)
575                 return (USBD_NOT_CONFIGURED);
576         *count = dev->cdesc->bNumInterface;
577         return (USBD_NORMAL_COMPLETION);
578 }
579
580 usbd_status 
581 usbd_interface2device_handle(usbd_interface_handle iface,
582                              usbd_device_handle *dev)
583 {
584         *dev = iface->device;
585         return (USBD_NORMAL_COMPLETION);
586 }
587
588 usbd_status 
589 usbd_device2interface_handle(usbd_device_handle dev,
590                              u_int8_t ifaceno, usbd_interface_handle *iface)
591 {
592         if (dev->cdesc == NULL)
593                 return (USBD_NOT_CONFIGURED);
594         if (ifaceno >= dev->cdesc->bNumInterface)
595                 return (USBD_INVAL);
596         *iface = &dev->ifaces[ifaceno];
597         return (USBD_NORMAL_COMPLETION);
598 }
599
600 usbd_device_handle
601 usbd_pipe2device_handle(usbd_pipe_handle pipe)
602 {
603         return (pipe->device);
604 }
605
606 /* XXXX use altno */
607 usbd_status
608 usbd_set_interface(usbd_interface_handle iface, int altidx)
609 {
610         usb_device_request_t req;
611         usbd_status err;
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         err = usbd_fill_iface_data(iface->device, iface->index, altidx);
622         if (err)
623                 return (err);
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(usb_config_descriptor_t *cdesc, int ifaceno)
635 {
636         char *p = (char *)cdesc;
637         char *end = p + UGETW(cdesc->wTotalLength);
638         usb_interface_descriptor_t *d;
639         int n;
640
641         for (n = 0; p < end; p += d->bLength) {
642                 d = (usb_interface_descriptor_t *)p;
643                 if (p + d->bLength <= end && 
644                     d->bDescriptorType == UDESC_INTERFACE &&
645                     d->bInterfaceNumber == ifaceno)
646                         n++;
647         }
648         return (n);
649 }
650
651 int
652 usbd_get_interface_altindex(usbd_interface_handle iface)
653 {
654         return (iface->altindex);
655 }
656
657 usbd_status
658 usbd_get_interface(usbd_interface_handle iface, u_int8_t *aiface)
659 {
660         usb_device_request_t req;
661
662         req.bmRequestType = UT_READ_INTERFACE;
663         req.bRequest = UR_GET_INTERFACE;
664         USETW(req.wValue, 0);
665         USETW(req.wIndex, iface->idesc->bInterfaceNumber);
666         USETW(req.wLength, 1);
667         return (usbd_do_request(iface->device, &req, aiface));
668 }
669
670 /*** Internal routines ***/
671
672 /* Dequeue all pipe operations, called at splusb(). */
673 Static usbd_status
674 usbd_ar_pipe(usbd_pipe_handle pipe)
675 {
676         usbd_xfer_handle xfer;
677
678         SPLUSBCHECK;
679
680         DPRINTFN(2,("usbd_ar_pipe: pipe=%p\n", pipe));
681 #ifdef USB_DEBUG
682         if (usbdebug > 5)
683                 usbd_dump_queue(pipe);
684 #endif
685         pipe->repeat = 0;
686         while ((xfer = SIMPLEQ_FIRST(&pipe->queue)) != NULL) {
687                 DPRINTFN(2,("usbd_ar_pipe: pipe=%p xfer=%p (methods=%p)\n", 
688                             pipe, xfer, pipe->methods));
689                 /* Make the HC abort it (and invoke the callback). */
690                 pipe->methods->abort(xfer);
691                 /* XXX only for non-0 usbd_clear_endpoint_stall(pipe); */
692         }
693         return (USBD_NORMAL_COMPLETION);
694 }
695
696 /* Called at splusb() */
697 void
698 usb_transfer_complete(usbd_xfer_handle xfer)
699 {
700         usbd_pipe_handle pipe = xfer->pipe;
701         usb_dma_t *dmap = &xfer->dmabuf;
702         int repeat = pipe->repeat;
703         int polling;
704
705         SPLUSBCHECK;
706
707         DPRINTFN(5, ("usb_transfer_complete: pipe=%p xfer=%p status=%d "
708                      "actlen=%d\n", pipe, xfer, xfer->status, xfer->actlen));
709
710 #ifdef DIAGNOSTIC
711         if (pipe == NULL) {
712                 printf("usbd_transfer_cb: pipe==0, xfer=%p\n", xfer);
713                 return;
714         }
715 #endif
716         polling = pipe->device->bus->use_polling;
717         /* XXXX */
718         if (polling)
719                 pipe->running = 0;
720
721         if (!(xfer->flags & USBD_NO_COPY) && xfer->actlen != 0 &&
722             usbd_xfer_isread(xfer)) {
723 #ifdef DIAGNOSTIC
724                 if (xfer->actlen > xfer->length) {
725                         printf("usb_transfer_complete: actlen > len %d > %d\n",
726                                xfer->actlen, xfer->length);
727                         xfer->actlen = xfer->length;
728                 }
729 #endif
730                 memcpy(xfer->buffer, KERNADDR(dmap, 0), xfer->actlen);
731         }
732
733         /* if we allocated the buffer in usbd_transfer() we free it here. */
734         if (xfer->rqflags & URQ_AUTO_DMABUF) {
735                 if (!repeat) {
736                         struct usbd_bus *bus = pipe->device->bus;
737                         bus->methods->freem(bus, dmap);
738                         xfer->rqflags &= ~URQ_AUTO_DMABUF;
739                 }
740         }
741
742         if (pipe->methods->done != NULL)
743                 pipe->methods->done(xfer);
744
745         if (!repeat) {
746                 /* Remove request from queue. */
747 #ifdef DIAGNOSTIC
748                 if (xfer != SIMPLEQ_FIRST(&pipe->queue))
749                         printf("usb_transfer_complete: bad dequeue %p != %p\n",
750                                xfer, SIMPLEQ_FIRST(&pipe->queue));
751 #endif
752                 SIMPLEQ_REMOVE_HEAD(&pipe->queue, xfer, next);
753         }
754
755         /* Count completed transfers. */
756         ++pipe->device->bus->stats.uds_requests
757                 [pipe->endpoint->edesc->bmAttributes & UE_XFERTYPE];
758
759         xfer->done = 1;
760         if (!xfer->status && xfer->actlen < xfer->length &&
761             !(xfer->flags & USBD_SHORT_XFER_OK)) {
762                 DPRINTFN(-1,("usbd_transfer_cb: short transfer %d<%d\n",
763                              xfer->actlen, xfer->length));
764                 xfer->status = USBD_SHORT_XFER;
765         }
766
767         if (xfer->callback)
768                 xfer->callback(xfer, xfer->priv, xfer->status);
769
770         if ((xfer->flags & USBD_SYNCHRONOUS) && !polling)
771                 wakeup(xfer);
772
773         if (!repeat) {
774                 /* XXX should we stop the queue on all errors? */
775                 if ((xfer->status == USBD_CANCELLED
776                      || xfer->status == USBD_TIMEOUT)
777                     && pipe->iface != NULL)             /* not control pipe */
778                         pipe->running = 0;
779                 else
780                         usbd_start_next(pipe);
781         }
782 }
783
784 usbd_status
785 usb_insert_transfer(usbd_xfer_handle xfer)
786 {
787         usbd_pipe_handle pipe = xfer->pipe;
788         usbd_status err;
789         int s;
790
791         DPRINTFN(5,("usb_insert_transfer: pipe=%p running=%d timeout=%d\n", 
792                     pipe, pipe->running, xfer->timeout));
793         s = splusb();
794         SIMPLEQ_INSERT_TAIL(&pipe->queue, xfer, next);
795         if (pipe->running)
796                 err = USBD_IN_PROGRESS;
797         else {
798                 pipe->running = 1;
799                 err = USBD_NORMAL_COMPLETION;
800         }
801         splx(s);
802         return (err);
803 }
804
805 /* Called at splusb() */
806 void
807 usbd_start_next(usbd_pipe_handle pipe)
808 {
809         usbd_xfer_handle xfer;
810         usbd_status err;
811
812         SPLUSBCHECK;
813
814 #ifdef DIAGNOSTIC
815         if (pipe == NULL) {
816                 printf("usbd_start_next: pipe == NULL\n");
817                 return;
818         }
819         if (pipe->methods == NULL || pipe->methods->start == NULL) {
820                 printf("usbd_start_next: pipe=%p no start method\n", pipe);
821                 return;
822         }
823 #endif
824
825         /* Get next request in queue. */
826         xfer = SIMPLEQ_FIRST(&pipe->queue);
827         DPRINTFN(5, ("usbd_start_next: pipe=%p, xfer=%p\n", pipe, xfer));
828         if (xfer == NULL) {
829                 pipe->running = 0;
830         } else {
831                 err = pipe->methods->start(xfer);
832                 if (err != USBD_IN_PROGRESS) {
833                         printf("usbd_start_next: error=%d\n", err);
834                         pipe->running = 0;
835                         /* XXX do what? */
836                 }
837         }
838 }
839
840 usbd_status
841 usbd_do_request(usbd_device_handle dev, usb_device_request_t *req, void *data)
842 {
843         return (usbd_do_request_flags(dev, req, data, 0, 0));
844 }
845
846 usbd_status
847 usbd_do_request_flags(usbd_device_handle dev,
848         usb_device_request_t *req, void *data, u_int16_t flags, int *actlen)
849 {
850         usbd_xfer_handle xfer;
851         usbd_status err;
852
853 #ifdef DIAGNOSTIC
854 #if defined(__FreeBSD__)
855         KASSERT(mycpu->gd_intr_nesting_level == 0,
856                 ("usbd_do_request: in interrupt context"));
857 #endif
858         if (dev->bus->intr_context) {
859                 printf("usbd_do_request: not in process context\n");
860                 return (USBD_INVAL);
861         }
862 #endif
863
864         xfer = usbd_alloc_xfer(dev);
865         if (xfer == NULL)
866                 return (USBD_NOMEM);
867         usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT, req,
868                                    data, UGETW(req->wLength), flags, 0);
869         err = usbd_sync_transfer(xfer);
870 #if defined(USB_DEBUG) || defined(DIAGNOSTIC)
871         if (xfer->actlen > xfer->length)
872                 DPRINTF(("usbd_do_request: overrun addr=%d type=0x%02x req=0x"
873                          "%02x val=%d index=%d rlen=%d length=%d actlen=%d\n",
874                          dev->address, xfer->request.bmRequestType,
875                          xfer->request.bRequest, UGETW(xfer->request.wValue),
876                          UGETW(xfer->request.wIndex), 
877                          UGETW(xfer->request.wLength), 
878                          xfer->length, xfer->actlen));
879 #endif
880         if (actlen != NULL)
881                 *actlen = xfer->actlen;
882         if (err == USBD_STALLED) {
883                 /* 
884                  * The control endpoint has stalled.  Control endpoints
885                  * should not halt, but some may do so anyway so clear
886                  * any halt condition.
887                  */
888                 usb_device_request_t treq;
889                 usb_status_t status;
890                 u_int16_t s;
891                 usbd_status nerr;
892
893                 treq.bmRequestType = UT_READ_ENDPOINT;
894                 treq.bRequest = UR_GET_STATUS;
895                 USETW(treq.wValue, 0);
896                 USETW(treq.wIndex, 0);
897                 USETW(treq.wLength, sizeof(usb_status_t));
898                 usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT,
899                                            &treq, &status,sizeof(usb_status_t),
900                                            0, 0);
901                 nerr = usbd_sync_transfer(xfer);
902                 if (nerr)
903                         goto bad;
904                 s = UGETW(status.wStatus);
905                 DPRINTF(("usbd_do_request: status = 0x%04x\n", s));
906                 if (!(s & UES_HALT))
907                         goto bad;
908                 treq.bmRequestType = UT_WRITE_ENDPOINT;
909                 treq.bRequest = UR_CLEAR_FEATURE;
910                 USETW(treq.wValue, UF_ENDPOINT_HALT);
911                 USETW(treq.wIndex, 0);
912                 USETW(treq.wLength, 0);
913                 usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT,
914                                            &treq, &status, 0, 0, 0);
915                 nerr = usbd_sync_transfer(xfer);
916                 if (nerr)
917                         goto bad;
918         }
919
920  bad:
921         usbd_free_xfer(xfer);
922         return (err);
923 }
924
925 void
926 usbd_do_request_async_cb(usbd_xfer_handle xfer, usbd_private_handle priv,
927                          usbd_status status)
928 {
929 #if defined(USB_DEBUG) || defined(DIAGNOSTIC)
930         if (xfer->actlen > xfer->length)
931                 DPRINTF(("usbd_do_request: overrun addr=%d type=0x%02x req=0x"
932                          "%02x val=%d index=%d rlen=%d length=%d actlen=%d\n",
933                          xfer->pipe->device->address, 
934                          xfer->request.bmRequestType,
935                          xfer->request.bRequest, UGETW(xfer->request.wValue),
936                          UGETW(xfer->request.wIndex), 
937                          UGETW(xfer->request.wLength), 
938                          xfer->length, xfer->actlen));
939 #endif
940         usbd_free_xfer(xfer);
941 }
942
943 /*
944  * Execute a request without waiting for completion.
945  * Can be used from interrupt context.
946  */
947 usbd_status
948 usbd_do_request_async(usbd_device_handle dev, usb_device_request_t *req,
949                       void *data)
950 {
951         usbd_xfer_handle xfer;
952         usbd_status err;
953
954         xfer = usbd_alloc_xfer(dev);
955         if (xfer == NULL)
956                 return (USBD_NOMEM);
957         usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT, req,
958             data, UGETW(req->wLength), 0, usbd_do_request_async_cb);
959         err = usbd_transfer(xfer);
960         if (err != USBD_IN_PROGRESS) {
961                 usbd_free_xfer(xfer);
962                 return (err);
963         }
964         return (USBD_NORMAL_COMPLETION);
965 }
966
967 struct usbd_quirks *
968 usbd_get_quirks(usbd_device_handle dev)
969 {
970         return (dev->quirks);
971 }
972
973 /* XXX do periodic free() of free list */
974
975 /*
976  * Called from keyboard driver when in polling mode.
977  */
978 void
979 usbd_dopoll(usbd_interface_handle iface)
980 {
981         iface->device->bus->methods->do_poll(iface->device->bus);
982 }
983
984 void
985 usbd_set_polling(usbd_interface_handle iface, int on)
986 {
987         if (on)
988                 iface->device->bus->use_polling++;
989         else
990                 iface->device->bus->use_polling--;
991 }
992
993
994 usb_endpoint_descriptor_t *
995 usbd_get_endpoint_descriptor(usbd_interface_handle iface, 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 /*
1009  * Search for a vendor/product pair in an array.  The item size is
1010  * given as an argument.
1011  */
1012 const struct usb_devno *
1013 usb_match_device(const struct usb_devno *tbl, u_int nentries, u_int sz,
1014                  u_int16_t vendor, u_int16_t product)
1015 {
1016         while (nentries-- > 0) {
1017                 if (tbl->ud_vendor == vendor && tbl->ud_product == product)
1018                         return (tbl);
1019                 tbl = (const struct usb_devno *)((const char *)tbl + sz);
1020         }
1021         return (NULL);
1022 }
1023
1024 #if defined(__FreeBSD__)
1025 int
1026 usbd_driver_load(module_t mod, int what, void *arg)
1027 {
1028         /* XXX should implement something like a function that removes all generic devices */
1029  
1030         return (0);
1031 }
1032
1033 #endif