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