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