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