Merge from vendor branch LESS:
[dragonfly.git] / sys / dev / usbmisc / ugen / ugen.c
1 /*
2  * $NetBSD: ugen.c,v 1.27 1999/10/28 12:08:38 augustss Exp $
3  * $NetBSD: ugen.c,v 1.59 2002/07/11 21:14:28 augustss Exp $
4  * $FreeBSD: src/sys/dev/usb/ugen.c,v 1.81 2003/11/09 09:17:22 tanimura Exp $
5  * $DragonFly: src/sys/dev/usbmisc/ugen/ugen.c,v 1.33 2007/11/06 07:37:01 hasso Exp $
6  */
7
8 /* 
9  * Also already merged from NetBSD:
10  *      $NetBSD: ugen.c,v 1.61 2002/09/23 05:51:20 simonb Exp $
11  *      $NetBSD: ugen.c,v 1.64 2003/06/28 14:21:46 darrenr Exp $
12  *      $NetBSD: ugen.c,v 1.65 2003/06/29 22:30:56 fvdl Exp $
13  */
14
15 /*
16  * Copyright (c) 1998 The NetBSD Foundation, Inc.
17  * All rights reserved.
18  *
19  * This code is derived from software contributed to The NetBSD Foundation
20  * by Lennart Augustsson (lennart@augustsson.net) at
21  * Carlstedt Research & Technology.
22  *
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  * 1. Redistributions of source code must retain the above copyright
27  *    notice, this list of conditions and the following disclaimer.
28  * 2. Redistributions in binary form must reproduce the above copyright
29  *    notice, this list of conditions and the following disclaimer in the
30  *    documentation and/or other materials provided with the distribution.
31  * 3. All advertising materials mentioning features or use of this software
32  *    must display the following acknowledgement:
33  *        This product includes software developed by the NetBSD
34  *        Foundation, Inc. and its contributors.
35  * 4. Neither the name of The NetBSD Foundation nor the names of its
36  *    contributors may be used to endorse or promote products derived
37  *    from this software without specific prior written permission.
38  *
39  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
40  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
41  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
43  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
44  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
45  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
46  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
47  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
49  * POSSIBILITY OF SUCH DAMAGE.
50  */
51
52
53 #include <sys/param.h>
54 #include <sys/systm.h>
55 #include <sys/kernel.h>
56 #include <sys/malloc.h>
57 #include <sys/module.h>
58 #include <sys/bus.h>
59 #include <sys/ioccom.h>
60 #include <sys/conf.h>
61 #include <sys/fcntl.h>
62 #include <sys/filio.h>
63 #include <sys/tty.h>
64 #include <sys/file.h>
65 #include <sys/select.h>
66 #include <sys/vnode.h>
67 #include <sys/poll.h>
68 #include <sys/sysctl.h>
69 #include <sys/thread2.h>
70
71 #include <bus/usb/usb.h>
72 #include <bus/usb/usbdi.h>
73 #include <bus/usb/usbdi_util.h>
74
75 #include "ugenbuf.h"
76
77 SYSCTL_NODE(_hw_usb, OID_AUTO, ugen, CTLFLAG_RW, 0, "USB ugen");
78
79 #ifdef USB_DEBUG
80 #define DPRINTF(x)      if (ugendebug) kprintf x
81 #define DPRINTFN(n,x)   if (ugendebug>(n)) kprintf x
82 int     ugendebug = 0;
83 SYSCTL_INT(_hw_usb_ugen, OID_AUTO, debug, CTLFLAG_RW,
84            &ugendebug, 0, "ugen debug level");
85 #else
86 #define DPRINTF(x)
87 #define DPRINTFN(n,x)
88 #endif
89
90 static int ugen_bufsize = 16384;
91 SYSCTL_INT(_hw_usb_ugen, OID_AUTO, bufsize, CTLFLAG_RW,
92            &ugen_bufsize, 0, "ugen temporary buffer size");
93
94 #define UGEN_CHUNK      128     /* chunk size for read */
95 #define UGEN_IBSIZE     1020    /* buffer size */
96
97 #define UGEN_NISOFRAMES 500     /* 0.5 seconds worth */
98 #define UGEN_NISOREQS   6       /* number of outstanding xfer requests */
99 #define UGEN_NISORFRMS  4       /* number of frames (miliseconds) per req */
100
101 struct ugen_endpoint {
102         struct ugen_softc *sc;
103         cdev_t dev;
104         usb_endpoint_descriptor_t *edesc;
105         usbd_interface_handle iface;
106         int state;
107 #define UGEN_ASLP       0x02    /* waiting for data */
108 #define UGEN_SHORT_OK   0x04    /* short xfers are OK */
109         usbd_pipe_handle pipeh;
110         struct clist q;
111         struct selinfo rsel;
112         u_char *ibuf;           /* start of buffer (circular for isoc) */
113         u_char *fill;           /* location for input (isoc) */
114         u_char *limit;          /* end of circular buffer (isoc) */
115         u_char *cur;            /* current read location (isoc) */
116         u_int32_t timeout;
117         struct isoreq {
118                 struct ugen_endpoint *sce;
119                 usbd_xfer_handle xfer;
120                 void *dmabuf;
121                 u_int16_t sizes[UGEN_NISORFRMS];
122         } isoreqs[UGEN_NISOREQS];
123 };
124
125 struct ugen_softc {
126         device_t sc_dev;                /* base device */
127         usbd_device_handle sc_udev;
128
129         char sc_is_open[USB_MAX_ENDPOINTS];
130         struct ugen_endpoint sc_endpoints[USB_MAX_ENDPOINTS][2];
131 #define OUT 0
132 #define IN  1
133
134         int sc_refcnt;
135         u_char sc_dying;
136 };
137
138 d_open_t  ugenopen;
139 d_close_t ugenclose;
140 d_read_t  ugenread;
141 d_write_t ugenwrite;
142 d_ioctl_t ugenioctl;
143 d_poll_t  ugenpoll;
144
145 #define UGEN_CDEV_MAJOR 114
146
147 static struct dev_ops ugen_ops = {
148         { "ugen", UGEN_CDEV_MAJOR, 0 },
149         .d_open =       ugenopen,
150         .d_close =      ugenclose,
151         .d_read =       ugenread,
152         .d_write =      ugenwrite,
153         .d_ioctl =      ugenioctl,
154         .d_poll =       ugenpoll,
155 };
156
157 static void ugenintr(usbd_xfer_handle xfer, usbd_private_handle addr,
158                             usbd_status status);
159 static void ugen_isoc_rintr(usbd_xfer_handle xfer, usbd_private_handle addr,
160                             usbd_status status);
161 static int ugen_do_read(struct ugen_softc *, int, struct uio *, int);
162 static int ugen_do_write(struct ugen_softc *, int, struct uio *, int);
163 static int ugen_do_ioctl(struct ugen_softc *, int, u_long,
164                             caddr_t, int);
165 static void ugen_make_devnodes(struct ugen_softc *sc);
166 static void ugen_destroy_devnodes(struct ugen_softc *sc);
167 static int ugen_set_config(struct ugen_softc *sc, int configno);
168 static usb_config_descriptor_t *ugen_get_cdesc(struct ugen_softc *sc,
169                                                 int index, int *lenp);
170 static usbd_status ugen_set_interface(struct ugen_softc *, int, int);
171 static int ugen_get_alt_index(struct ugen_softc *sc, int ifaceidx);
172
173 #define UGENUNIT(n) ((lminor(n) >> 4) & 0xff)
174 #define UGENENDPOINT(n) (minor(n) & 0xf)
175 #define UGENMINOR(u, e) (((u & 0xf) << 4) | ((u & 0xf0) << 12) | (e))
176 #define UGENUNITMASK    0xffff00f0
177
178 static device_probe_t ugen_match;
179 static device_attach_t ugen_attach;
180 static device_detach_t ugen_detach;
181
182 static devclass_t ugen_devclass;
183
184 static kobj_method_t ugen_methods[] = {
185         DEVMETHOD(device_probe, ugen_match),
186         DEVMETHOD(device_attach, ugen_attach),
187         DEVMETHOD(device_detach, ugen_detach),
188         {0,0}
189 };
190
191 static driver_t ugen_driver = {
192         "ugen",
193         ugen_methods,
194         sizeof(struct ugen_softc)
195 };
196
197 MODULE_DEPEND(ugen, usb, 1, 1, 1);
198
199 static int
200 ugen_match(device_t self)
201 {
202         struct usb_attach_arg *uaa = device_get_ivars(self);
203
204 #if 0
205         if (uaa->matchlvl)
206                 return (uaa->matchlvl);
207 #endif
208         if (uaa->usegeneric)
209                 return (UMATCH_GENERIC);
210         else
211                 return (UMATCH_NONE);
212 }
213
214 static int
215 ugen_attach(device_t self)
216 {
217         struct ugen_softc *sc = device_get_softc(self);
218         struct usb_attach_arg *uaa = device_get_ivars(self);
219         usbd_device_handle udev;
220         usbd_status err;
221         int conf;
222
223         sc->sc_dev = self;
224         sc->sc_udev = udev = uaa->device;
225
226         memset(sc->sc_endpoints, 0, sizeof sc->sc_endpoints);
227
228         /* First set configuration index 0, the default one for ugen. */
229         err = usbd_set_config_index(udev, 0, 0);
230         if (err) {
231                 kprintf("%s: setting configuration index 0 failed\n",
232                        device_get_nameunit(sc->sc_dev));
233                 sc->sc_dying = 1;
234                 return ENXIO;
235         }
236         conf = usbd_get_config_descriptor(udev)->bConfigurationValue;
237
238         /* Set up all the local state for this configuration. */
239         err = ugen_set_config(sc, conf);
240         if (err) {
241                 kprintf("%s: setting configuration %d failed\n",
242                        device_get_nameunit(sc->sc_dev), conf);
243                 sc->sc_dying = 1;
244                 return ENXIO;
245         }
246
247         /* the main device, ctrl endpoint */
248         dev_ops_add(&ugen_ops, 
249                     UGENUNITMASK, UGENMINOR(device_get_unit(sc->sc_dev), 0));
250         make_dev(&ugen_ops, UGENMINOR(device_get_unit(sc->sc_dev), 0),
251                 UID_ROOT, GID_OPERATOR, 0644, "%s", device_get_nameunit(sc->sc_dev));
252
253         return 0;
254 }
255
256 static void
257 ugen_make_devnodes(struct ugen_softc *sc)
258 {
259         int endptno;
260         cdev_t dev;
261
262         for (endptno = 1; endptno < USB_MAX_ENDPOINTS; endptno++) {
263                 if (sc->sc_endpoints[endptno][IN].sc != NULL ||
264                     sc->sc_endpoints[endptno][OUT].sc != NULL ) {
265                         /* endpt can be 0x81 and 0x01, representing
266                          * endpoint address 0x01 and IN/OUT directions.
267                          * We map both endpts to the same device,
268                          * IN is reading from it, OUT is writing to it.
269                          *
270                          * In the if clause above we check whether one
271                          * of the structs is populated.
272                          */
273                         dev = make_dev(&ugen_ops,
274                                 UGENMINOR(device_get_unit(sc->sc_dev), endptno),
275                                 UID_ROOT, GID_OPERATOR, 0644,
276                                 "%s.%d",
277                                 device_get_nameunit(sc->sc_dev), endptno);
278                         if (sc->sc_endpoints[endptno][IN].sc != NULL) {
279                                 reference_dev(dev);
280                                 if (sc->sc_endpoints[endptno][IN].dev)
281                                         release_dev(sc->sc_endpoints[endptno][IN].dev);
282                                 sc->sc_endpoints[endptno][IN].dev = dev;
283                         }
284                         if (sc->sc_endpoints[endptno][OUT].sc != NULL) {
285                                 reference_dev(dev);
286                                 if (sc->sc_endpoints[endptno][OUT].dev)
287                                         release_dev(sc->sc_endpoints[endptno][OUT].dev);
288                                 sc->sc_endpoints[endptno][OUT].dev = dev;
289                         }
290                 }
291         }
292 }
293
294 static void
295 ugen_destroy_devnodes(struct ugen_softc *sc)
296 {
297         int endptno;
298         cdev_t dev;
299
300         /* destroy all devices for the other (existing) endpoints as well */
301         for (endptno = 1; endptno < USB_MAX_ENDPOINTS; endptno++) {
302                 if (sc->sc_endpoints[endptno][IN].sc != NULL ||
303                     sc->sc_endpoints[endptno][OUT].sc != NULL ) {
304                         /* endpt can be 0x81 and 0x01, representing
305                          * endpoint address 0x01 and IN/OUT directions.
306                          * We map both endpoint addresses to the same device,
307                          * IN is reading from it, OUT is writing to it.
308                          *
309                          * In the if clause above we check whether one
310                          * of the structs is populated.
311                          */
312                         dev = sc->sc_endpoints[endptno][IN].dev;
313                         if (dev != NULL) {
314                                 destroy_dev(dev);
315                                 sc->sc_endpoints[endptno][IN].dev = NULL;
316                         }
317                         dev = sc->sc_endpoints[endptno][OUT].dev;
318                         if (dev != NULL) {
319                                 destroy_dev(dev);
320                                 sc->sc_endpoints[endptno][OUT].dev = NULL;
321                         }
322                 }
323         }
324 }
325
326 static int
327 ugen_set_config(struct ugen_softc *sc, int configno)
328 {
329         usbd_device_handle dev = sc->sc_udev;
330         usbd_interface_handle iface;
331         usb_endpoint_descriptor_t *ed;
332         struct ugen_endpoint *sce;
333         u_int8_t niface, nendpt;
334         int ifaceno, endptno, endpt;
335         usbd_status err;
336         int dir;
337
338         DPRINTFN(1,("ugen_set_config: %s to configno %d, sc=%p\n",
339                     device_get_nameunit(sc->sc_dev), configno, sc));
340
341         ugen_destroy_devnodes(sc);
342
343         /* We start at 1, not 0, because we don't care whether the
344          * control endpoint is open or not. It is always present.
345          */
346         for (endptno = 1; endptno < USB_MAX_ENDPOINTS; endptno++) {
347                 if (sc->sc_is_open[endptno]) {
348                         DPRINTFN(1,
349                              ("ugen_set_config: %s - endpoint %d is open\n",
350                               device_get_nameunit(sc->sc_dev), endptno));
351                         return (USBD_IN_USE);
352                 }
353         }
354
355         /* Avoid setting the current value. */
356         if (usbd_get_config_descriptor(dev)->bConfigurationValue != configno) {
357                 err = usbd_set_config_no(dev, configno, 1);
358                 if (err)
359                         return (err);
360         }
361
362         err = usbd_interface_count(dev, &niface);
363         if (err)
364                 return (err);
365         memset(sc->sc_endpoints, 0, sizeof sc->sc_endpoints);
366         for (ifaceno = 0; ifaceno < niface; ifaceno++) {
367                 DPRINTFN(1,("ugen_set_config: ifaceno %d\n", ifaceno));
368                 err = usbd_device2interface_handle(dev, ifaceno, &iface);
369                 if (err)
370                         return (err);
371                 err = usbd_endpoint_count(iface, &nendpt);
372                 if (err)
373                         return (err);
374                 for (endptno = 0; endptno < nendpt; endptno++) {
375                         ed = usbd_interface2endpoint_descriptor(iface,endptno);
376                         endpt = ed->bEndpointAddress;
377                         dir = UE_GET_DIR(endpt) == UE_DIR_IN ? IN : OUT;
378                         sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)][dir];
379                         DPRINTFN(1,("ugen_set_config: endptno %d, endpt=0x%02x"
380                                     "(%d,%d), sce=%p\n",
381                                     endptno, endpt, UE_GET_ADDR(endpt),
382                                     UE_GET_DIR(endpt), sce));
383                         sce->sc = sc;
384                         sce->edesc = ed;
385                         sce->iface = iface;
386                 }
387         }
388
389         ugen_make_devnodes(sc);
390
391         return (USBD_NORMAL_COMPLETION);
392 }
393
394 int
395 ugenopen(struct dev_open_args *ap)
396 {
397         cdev_t dev = ap->a_head.a_dev;
398         struct ugen_softc *sc;
399         int unit = UGENUNIT(dev);
400         int endpt = UGENENDPOINT(dev);
401         usb_endpoint_descriptor_t *edesc;
402         struct ugen_endpoint *sce;
403         int dir, isize;
404         usbd_status err;
405         usbd_xfer_handle xfer;
406         void *buf;
407         int i, j;
408
409         sc = devclass_get_softc(ugen_devclass, unit);
410         if (sc == NULL)
411                 return (ENXIO);
412
413         DPRINTFN(5, ("ugenopen: flag=%d, mode=%d, unit=%d endpt=%d\n",
414                      ap->a_oflags, ap->a_devtype, unit, endpt));
415
416         if (sc == NULL || sc->sc_dying)
417                 return (ENXIO);
418
419         if (sc->sc_is_open[endpt])
420                 return (EBUSY);
421
422         if (endpt == USB_CONTROL_ENDPOINT) {
423                 sc->sc_is_open[USB_CONTROL_ENDPOINT] = 1;
424                 return (0);
425         }
426
427         /* Make sure there are pipes for all directions. */
428         for (dir = OUT; dir <= IN; dir++) {
429                 if (ap->a_oflags & (dir == OUT ? FWRITE : FREAD)) {
430                         sce = &sc->sc_endpoints[endpt][dir];
431                         if (sce == 0 || sce->edesc == 0)
432                                 return (ENXIO);
433                 }
434         }
435
436         /* Actually open the pipes. */
437         /* XXX Should back out properly if it fails. */
438         for (dir = OUT; dir <= IN; dir++) {
439                 if (!(ap->a_oflags & (dir == OUT ? FWRITE : FREAD)))
440                         continue;
441                 sce = &sc->sc_endpoints[endpt][dir];
442                 sce->state = 0;
443                 sce->timeout = USBD_NO_TIMEOUT;
444                 DPRINTFN(5, ("ugenopen: sc=%p, endpt=%d, dir=%d, sce=%p\n",
445                              sc, endpt, dir, sce));
446                 edesc = sce->edesc;
447                 switch (edesc->bmAttributes & UE_XFERTYPE) {
448                 case UE_INTERRUPT:
449                         if (dir == OUT) {
450                                 err = usbd_open_pipe(sce->iface,
451                                     edesc->bEndpointAddress, 0, &sce->pipeh);
452                                 if (err)
453                                         return (EIO);
454                                 break;
455                         }
456                         isize = UGETW(edesc->wMaxPacketSize);
457                         if (isize == 0) /* shouldn't happen */
458                                 return (EINVAL);
459                         sce->ibuf = kmalloc(isize, M_USBDEV, M_WAITOK);
460                         DPRINTFN(5, ("ugenopen: intr endpt=%d,isize=%d\n",
461                                      endpt, isize));
462                         if ((clist_alloc_cblocks(&sce->q, UGEN_IBSIZE,
463                                                  UGEN_IBSIZE), 0) == -1)
464                                 return (ENOMEM);
465                         err = usbd_open_pipe_intr(sce->iface,
466                                 edesc->bEndpointAddress,
467                                 USBD_SHORT_XFER_OK, &sce->pipeh, sce,
468                                 sce->ibuf, isize, ugenintr,
469                                 USBD_DEFAULT_INTERVAL);
470                         if (err) {
471                                 kfree(sce->ibuf, M_USBDEV);
472                                 clist_free_cblocks(&sce->q);
473                                 return (EIO);
474                         }
475                         DPRINTFN(5, ("ugenopen: interrupt open done\n"));
476                         break;
477                 case UE_BULK:
478                         err = usbd_open_pipe(sce->iface,
479                                   edesc->bEndpointAddress, 0, &sce->pipeh);
480                         if (err)
481                                 return (EIO);
482                         break;
483                 case UE_ISOCHRONOUS:
484                         if (dir == OUT)
485                                 return (EINVAL);
486                         isize = UGETW(edesc->wMaxPacketSize);
487                         if (isize == 0) /* shouldn't happen */
488                                 return (EINVAL);
489                         sce->ibuf = kmalloc(isize * UGEN_NISOFRAMES,
490                                 M_USBDEV, M_WAITOK);
491                         sce->cur = sce->fill = sce->ibuf;
492                         sce->limit = sce->ibuf + isize * UGEN_NISOFRAMES;
493                         DPRINTFN(5, ("ugenopen: isoc endpt=%d, isize=%d\n",
494                                      endpt, isize));
495                         err = usbd_open_pipe(sce->iface,
496                                   edesc->bEndpointAddress, 0, &sce->pipeh);
497                         if (err) {
498                                 kfree(sce->ibuf, M_USBDEV);
499                                 return (EIO);
500                         }
501                         for(i = 0; i < UGEN_NISOREQS; ++i) {
502                                 sce->isoreqs[i].sce = sce;
503                                 xfer = usbd_alloc_xfer(sc->sc_udev);
504                                 if (xfer == 0)
505                                         goto bad;
506                                 sce->isoreqs[i].xfer = xfer;
507                                 buf = usbd_alloc_buffer
508                                         (xfer, isize * UGEN_NISORFRMS);
509                                 if (buf == 0) {
510                                         i++;
511                                         goto bad;
512                                 }
513                                 sce->isoreqs[i].dmabuf = buf;
514                                 for(j = 0; j < UGEN_NISORFRMS; ++j)
515                                         sce->isoreqs[i].sizes[j] = isize;
516                                 usbd_setup_isoc_xfer
517                                         (xfer, sce->pipeh, &sce->isoreqs[i],
518                                          sce->isoreqs[i].sizes,
519                                          UGEN_NISORFRMS, USBD_NO_COPY,
520                                          ugen_isoc_rintr);
521                                 (void)usbd_transfer(xfer);
522                         }
523                         DPRINTFN(5, ("ugenopen: isoc open done\n"));
524                         break;
525                 bad:
526                         while (--i >= 0) /* implicit buffer free */
527                                 usbd_free_xfer(sce->isoreqs[i].xfer);
528                         return (ENOMEM);
529                 case UE_CONTROL:
530                         sce->timeout = USBD_DEFAULT_TIMEOUT;
531                         return (EINVAL);
532                 }
533         }
534         sc->sc_is_open[endpt] = 1;
535         return (0);
536 }
537
538 int
539 ugenclose(struct dev_close_args *ap)
540 {
541         cdev_t dev = ap->a_head.a_dev;
542         int endpt = UGENENDPOINT(dev);
543         struct ugen_softc *sc;
544         struct ugen_endpoint *sce;
545         int dir;
546         int i;
547
548         sc = devclass_get_softc(ugen_devclass, UGENUNIT(dev));
549
550         DPRINTFN(5, ("ugenclose: flag=%d, mode=%d, unit=%d, endpt=%d\n",
551                      ap->a_fflag, ap->a_devtype, UGENUNIT(dev), endpt));
552
553 #ifdef DIAGNOSTIC
554         if (!sc->sc_is_open[endpt]) {
555                 kprintf("ugenclose: not open\n");
556                 return (EINVAL);
557         }
558 #endif
559
560         if (endpt == USB_CONTROL_ENDPOINT) {
561                 DPRINTFN(5, ("ugenclose: close control\n"));
562                 sc->sc_is_open[endpt] = 0;
563                 return (0);
564         }
565
566         for (dir = OUT; dir <= IN; dir++) {
567                 if (!(ap->a_fflag & (dir == OUT ? FWRITE : FREAD)))
568                         continue;
569                 sce = &sc->sc_endpoints[endpt][dir];
570                 if (sce == NULL || sce->pipeh == NULL)
571                         continue;
572                 DPRINTFN(5, ("ugenclose: endpt=%d dir=%d sce=%p\n",
573                              endpt, dir, sce));
574
575                 usbd_abort_pipe(sce->pipeh);
576                 usbd_close_pipe(sce->pipeh);
577                 sce->pipeh = NULL;
578
579                 switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
580                 case UE_INTERRUPT:
581                         ndflush(&sce->q, sce->q.c_cc);
582                         clist_free_cblocks(&sce->q);
583                         break;
584                 case UE_ISOCHRONOUS:
585                         for (i = 0; i < UGEN_NISOREQS; ++i)
586                                 usbd_free_xfer(sce->isoreqs[i].xfer);
587                 default:
588                         break;
589                 }
590
591                 if (sce->ibuf != NULL) {
592                         kfree(sce->ibuf, M_USBDEV);
593                         sce->ibuf = NULL;
594                         clist_free_cblocks(&sce->q);
595                 }
596         }
597         sc->sc_is_open[endpt] = 0;
598
599         return (0);
600 }
601
602 static int
603 ugen_do_read(struct ugen_softc *sc, int endpt, struct uio *uio, int flag)
604 {
605         struct ugen_endpoint *sce = &sc->sc_endpoints[endpt][IN];
606         u_int32_t n, tn;
607         char *buf;
608         usbd_xfer_handle xfer;
609         usbd_status err;
610         int error = 0;
611         int ugen_bbsize;
612         u_char buffer[UGEN_CHUNK];
613
614         DPRINTFN(5, ("%s: ugenread: %d\n", device_get_nameunit(sc->sc_dev), endpt));
615
616         if (sc->sc_dying)
617                 return (EIO);
618
619         if (endpt == USB_CONTROL_ENDPOINT)
620                 return (ENODEV);
621
622         if (sce == NULL)
623                 return (EINVAL);
624
625         if (sce->edesc == NULL) {
626                 kprintf("ugenread: no edesc\n");
627                 return (EIO);
628         }
629         if (sce->pipeh == NULL) {
630                 kprintf("ugenread: no pipe\n");
631                 return (EIO);
632         }
633
634         buf = getugenbuf(ugen_bufsize, &ugen_bbsize);
635
636         switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
637         case UE_INTERRUPT:
638                 /* Block until activity occurred. */
639                 crit_enter();
640                 while (sce->q.c_cc == 0) {
641                         if (flag & IO_NDELAY) {
642                                 crit_exit();
643                                 error = EWOULDBLOCK;
644                                 goto done;
645                         }
646                         sce->state |= UGEN_ASLP;
647                         DPRINTFN(5, ("ugenread: sleep on %p\n", sce));
648                         error = tsleep(sce, PCATCH, "ugenri", 0);
649                         DPRINTFN(5, ("ugenread: woke, error=%d\n", error));
650                         if (sc->sc_dying)
651                                 error = EIO;
652                         if (error) {
653                                 sce->state &= ~UGEN_ASLP;
654                                 break;
655                         }
656                 }
657                 crit_exit();
658
659                 /* Transfer as many chunks as possible. */
660                 while (sce->q.c_cc > 0 && uio->uio_resid > 0 && !error) {
661                         n = min(sce->q.c_cc, uio->uio_resid);
662                         if (n > sizeof(buffer))
663                                 n = sizeof(buffer);
664
665                         /* Remove a small chunk from the input queue. */
666                         q_to_b(&sce->q, buffer, n);
667                         DPRINTFN(5, ("ugenread: got %d chars\n", n));
668
669                         /* Copy the data to the user process. */
670                         error = uiomove(buffer, n, uio);
671                         if (error)
672                                 break;
673                 }
674                 break;
675         case UE_BULK:
676                 xfer = usbd_alloc_xfer(sc->sc_udev);
677                 if (xfer == 0) {
678                         error = ENOMEM;
679                         goto done;
680                 }
681                 while ((n = min(ugen_bbsize, uio->uio_resid)) != 0) {
682                         DPRINTFN(1, ("ugenread: start transfer %d bytes\n",n));
683                         tn = n;
684                         err = usbd_bulk_transfer(
685                                 xfer, sce->pipeh,
686                                 sce->state & UGEN_SHORT_OK ?
687                                     USBD_SHORT_XFER_OK : 0,
688                                 sce->timeout, buf, &tn, "ugenrb");
689                         if (err) {
690                                 if (err == USBD_INTERRUPTED)
691                                         error = EINTR;
692                                 else if (err == USBD_TIMEOUT)
693                                         error = ETIMEDOUT;
694                                 else
695                                         error = EIO;
696                                 break;
697                         }
698                         DPRINTFN(1, ("ugenread: got %d bytes\n", tn));
699                         error = uiomove(buf, tn, uio);
700                         if (error || tn < n)
701                                 break;
702                 }
703                 usbd_free_xfer(xfer);
704                 break;
705         case UE_ISOCHRONOUS:
706                 crit_enter();
707                 while (sce->cur == sce->fill) {
708                         if (flag & IO_NDELAY) {
709                                 crit_exit();
710                                 error = EWOULDBLOCK;
711                                 goto done;
712                         }
713                         sce->state |= UGEN_ASLP;
714                         DPRINTFN(5, ("ugenread: sleep on %p\n", sce));
715                         error = tsleep(sce, PCATCH, "ugenri", 0);
716                         DPRINTFN(5, ("ugenread: woke, error=%d\n", error));
717                         if (sc->sc_dying)
718                                 error = EIO;
719                         if (error) {
720                                 sce->state &= ~UGEN_ASLP;
721                                 break;
722                         }
723                 }
724
725                 while (sce->cur != sce->fill && uio->uio_resid > 0 && !error) {
726                         if(sce->fill > sce->cur)
727                                 n = min(sce->fill - sce->cur, uio->uio_resid);
728                         else
729                                 n = min(sce->limit - sce->cur, uio->uio_resid);
730
731                         DPRINTFN(5, ("ugenread: isoc got %d chars\n", n));
732
733                         /* Copy the data to the user process. */
734                         error = uiomove(sce->cur, n, uio);
735                         if (error)
736                                 break;
737                         sce->cur += n;
738                         if(sce->cur >= sce->limit)
739                                 sce->cur = sce->ibuf;
740                 }
741                 crit_exit();
742                 break;
743
744
745         default:
746                 error = ENXIO;
747                 break;
748         }
749 done:
750         relugenbuf(buf, ugen_bbsize);
751         return (error);
752 }
753
754 int
755 ugenread(struct dev_read_args *ap)
756 {
757         cdev_t dev = ap->a_head.a_dev;
758         int endpt = UGENENDPOINT(dev);
759         struct ugen_softc *sc;
760         int error;
761
762         sc = devclass_get_softc(ugen_devclass, UGENUNIT(dev));
763
764         sc->sc_refcnt++;
765         error = ugen_do_read(sc, endpt, ap->a_uio, ap->a_ioflag);
766         if (--sc->sc_refcnt < 0)
767                 usb_detach_wakeup(sc->sc_dev);
768         return (error);
769 }
770
771 static int
772 ugen_do_write(struct ugen_softc *sc, int endpt, struct uio *uio, int flag)
773 {
774         struct ugen_endpoint *sce = &sc->sc_endpoints[endpt][OUT];
775         u_int32_t n;
776         int error = 0;
777         int ugen_bbsize;
778         char *buf;
779         usbd_xfer_handle xfer;
780         usbd_status err;
781
782         DPRINTFN(5, ("%s: ugenwrite: %d\n", device_get_nameunit(sc->sc_dev), endpt));
783
784         if (sc->sc_dying)
785                 return (EIO);
786
787         if (endpt == USB_CONTROL_ENDPOINT)
788                 return (ENODEV);
789
790         if (sce == NULL)
791                 return (EINVAL);
792
793         if (sce->edesc == NULL) {
794                 kprintf("ugenwrite: no edesc\n");
795                 return (EIO);
796         }
797         if (sce->pipeh == NULL) {
798                 kprintf("ugenwrite: no pipe\n");
799                 return (EIO);
800         }
801
802         buf = getugenbuf(ugen_bufsize, &ugen_bbsize);
803
804         switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
805         case UE_BULK:
806                 xfer = usbd_alloc_xfer(sc->sc_udev);
807                 if (xfer == 0) {
808                         error = EIO;
809                         goto done;
810                 }
811                 while ((n = min(ugen_bbsize, uio->uio_resid)) != 0) {
812                         error = uiomove(buf, n, uio);
813                         if (error)
814                                 break;
815                         DPRINTFN(1, ("ugenwrite: transfer %d bytes\n", n));
816                         err = usbd_bulk_transfer(xfer, sce->pipeh, 0,
817                                   sce->timeout, buf, &n,"ugenwb");
818                         if (err) {
819                                 if (err == USBD_INTERRUPTED)
820                                         error = EINTR;
821                                 else if (err == USBD_TIMEOUT)
822                                         error = ETIMEDOUT;
823                                 else
824                                         error = EIO;
825                                 break;
826                         }
827                 }
828                 usbd_free_xfer(xfer);
829                 break;
830         case UE_INTERRUPT:
831                 xfer = usbd_alloc_xfer(sc->sc_udev);
832                 if (xfer == 0) {
833                         error = EIO;
834                         goto done;
835                 }
836                 while ((n = min(UGETW(sce->edesc->wMaxPacketSize),
837                     uio->uio_resid)) != 0) {
838                         error = uiomove(buf, n, uio);
839                         if (error)
840                                 break;
841                         DPRINTFN(1, ("ugenwrite: transfer %d bytes\n", n));
842                         err = usbd_intr_transfer(xfer, sce->pipeh, 0,
843                                   sce->timeout, buf, &n,"ugenwi");
844                         if (err) {
845                                 if (err == USBD_INTERRUPTED)
846                                         error = EINTR;
847                                 else if (err == USBD_TIMEOUT)
848                                         error = ETIMEDOUT;
849                                 else
850                                         error = EIO;
851                                 break;
852                         }
853                 }
854                 usbd_free_xfer(xfer);
855                 break;
856         default:
857                 error = ENXIO;
858                 break;
859         }
860 done:
861         relugenbuf(buf, ugen_bbsize);
862         return (error);
863 }
864
865 int
866 ugenwrite(struct dev_write_args *ap)
867 {
868         cdev_t dev = ap->a_head.a_dev;
869         int endpt = UGENENDPOINT(dev);
870         struct ugen_softc *sc;
871         int error;
872
873         sc = devclass_get_softc(ugen_devclass, UGENUNIT(dev));
874
875         sc->sc_refcnt++;
876         error = ugen_do_write(sc, endpt, ap->a_uio, ap->a_ioflag);
877         if (--sc->sc_refcnt < 0)
878                 usb_detach_wakeup(sc->sc_dev);
879         return (error);
880 }
881
882 static int
883 ugen_detach(device_t self)
884 {
885         struct ugen_softc *sc = device_get_softc(self);
886         struct ugen_endpoint *sce;
887         int i, dir;
888
889         DPRINTF(("ugen_detach: sc=%p\n", sc));
890
891         sc->sc_dying = 1;
892         /* Abort all pipes.  Causes processes waiting for transfer to wake. */
893         for (i = 0; i < USB_MAX_ENDPOINTS; i++) {
894                 for (dir = OUT; dir <= IN; dir++) {
895                         sce = &sc->sc_endpoints[i][dir];
896                         if (sce && sce->pipeh)
897                                 usbd_abort_pipe(sce->pipeh);
898                 }
899         }
900         crit_enter();
901         if (--sc->sc_refcnt >= 0) {
902                 /* Wake everyone */
903                 for (i = 0; i < USB_MAX_ENDPOINTS; i++)
904                         wakeup(&sc->sc_endpoints[i][IN]);
905                 /* Wait for processes to go away. */
906                 usb_detach_wait(sc->sc_dev);
907         }
908         crit_exit();
909
910         /* destroy the device for the control endpoint */
911         ugen_destroy_devnodes(sc);
912         dev_ops_remove(&ugen_ops, 
913                     UGENUNITMASK, UGENMINOR(device_get_unit(sc->sc_dev), 0));
914         return (0);
915 }
916
917 static void
918 ugenintr(usbd_xfer_handle xfer, usbd_private_handle addr, usbd_status status)
919 {
920         struct ugen_endpoint *sce = addr;
921         /*struct ugen_softc *sc = sce->sc;*/
922         u_int32_t count;
923         u_char *ibuf;
924
925         if (status == USBD_CANCELLED)
926                 return;
927
928         if (status != USBD_NORMAL_COMPLETION) {
929                 DPRINTF(("ugenintr: status=%d\n", status));
930                 if (status == USBD_STALLED)
931                     usbd_clear_endpoint_stall_async(sce->pipeh);
932                 return;
933         }
934
935         usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
936         ibuf = sce->ibuf;
937
938         DPRINTFN(5, ("ugenintr: xfer=%p status=%d count=%d\n",
939                      xfer, status, count));
940         DPRINTFN(5, ("          data = %02x %02x %02x\n",
941                      ibuf[0], ibuf[1], ibuf[2]));
942
943         (void)b_to_q(ibuf, count, &sce->q);
944
945         if (sce->state & UGEN_ASLP) {
946                 sce->state &= ~UGEN_ASLP;
947                 DPRINTFN(5, ("ugen_intr: waking %p\n", sce));
948                 wakeup(sce);
949         }
950         selwakeup(&sce->rsel);
951 }
952
953 static void
954 ugen_isoc_rintr(usbd_xfer_handle xfer, usbd_private_handle addr,
955                 usbd_status status)
956 {
957         struct isoreq *req = addr;
958         struct ugen_endpoint *sce = req->sce;
959         u_int32_t count, n;
960         int i, isize;
961
962         /* Return if we are aborting. */
963         if (status == USBD_CANCELLED)
964                 return;
965
966         usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
967         DPRINTFN(5,("ugen_isoc_rintr: xfer %d, count=%d\n",
968                     (int)(req - sce->isoreqs),
969                     count));
970
971         /* throw away oldest input if the buffer is full */
972         if(sce->fill < sce->cur && sce->cur <= sce->fill + count) {
973                 sce->cur += count;
974                 if(sce->cur >= sce->limit)
975                         sce->cur = sce->ibuf + (sce->limit - sce->cur);
976                 DPRINTFN(5, ("ugen_isoc_rintr: throwing away %d bytes\n",
977                              count));
978         }
979
980         isize = UGETW(sce->edesc->wMaxPacketSize);
981         for (i = 0; i < UGEN_NISORFRMS; i++) {
982                 u_int32_t actlen = req->sizes[i];
983                 char const *buf = (char const *)req->dmabuf + isize * i;
984
985                 /* copy data to buffer */
986                 while (actlen > 0) {
987                         n = min(actlen, sce->limit - sce->fill);
988                         memcpy(sce->fill, buf, n);
989
990                         buf += n;
991                         actlen -= n;
992                         sce->fill += n;
993                         if(sce->fill == sce->limit)
994                                 sce->fill = sce->ibuf;
995                 }
996
997                 /* setup size for next transfer */
998                 req->sizes[i] = isize;
999         }
1000
1001         usbd_setup_isoc_xfer(xfer, sce->pipeh, req, req->sizes, UGEN_NISORFRMS,
1002                              USBD_NO_COPY, ugen_isoc_rintr);
1003         (void)usbd_transfer(xfer);
1004
1005         if (sce->state & UGEN_ASLP) {
1006                 sce->state &= ~UGEN_ASLP;
1007                 DPRINTFN(5, ("ugen_isoc_rintr: waking %p\n", sce));
1008                 wakeup(sce);
1009         }
1010         selwakeup(&sce->rsel);
1011 }
1012
1013 static usbd_status
1014 ugen_set_interface(struct ugen_softc *sc, int ifaceidx, int altno)
1015 {
1016         usbd_interface_handle iface;
1017         usb_endpoint_descriptor_t *ed;
1018         usbd_status err;
1019         struct ugen_endpoint *sce;
1020         u_int8_t niface, nendpt, endptno, endpt;
1021         int dir;
1022
1023         DPRINTFN(15, ("ugen_set_interface %d %d\n", ifaceidx, altno));
1024
1025         err = usbd_interface_count(sc->sc_udev, &niface);
1026         if (err)
1027                 return (err);
1028         if (ifaceidx < 0 || ifaceidx >= niface)
1029                 return (USBD_INVAL);
1030
1031         err = usbd_device2interface_handle(sc->sc_udev, ifaceidx, &iface);
1032         if (err)
1033                 return (err);
1034         err = usbd_endpoint_count(iface, &nendpt);
1035         if (err)
1036                 return (err);
1037
1038         /* destroy the existing devices, we remake the new ones in a moment */
1039         ugen_destroy_devnodes(sc);
1040
1041         /* XXX should only do this after setting new altno has succeeded */
1042         for (endptno = 0; endptno < nendpt; endptno++) {
1043                 ed = usbd_interface2endpoint_descriptor(iface,endptno);
1044                 endpt = ed->bEndpointAddress;
1045                 dir = UE_GET_DIR(endpt) == UE_DIR_IN ? IN : OUT;
1046                 sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)][dir];
1047                 sce->sc = 0;
1048                 sce->edesc = 0;
1049                 sce->iface = 0;
1050         }
1051
1052         /* change setting */
1053         err = usbd_set_interface(iface, altno);
1054         if (err)
1055                 return (err);
1056
1057         err = usbd_endpoint_count(iface, &nendpt);
1058         if (err)
1059                 return (err);
1060         for (endptno = 0; endptno < nendpt; endptno++) {
1061                 ed = usbd_interface2endpoint_descriptor(iface,endptno);
1062                 endpt = ed->bEndpointAddress;
1063                 dir = UE_GET_DIR(endpt) == UE_DIR_IN ? IN : OUT;
1064                 sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)][dir];
1065                 sce->sc = sc;
1066                 sce->edesc = ed;
1067                 sce->iface = iface;
1068         }
1069
1070         /* make the new devices */
1071         ugen_make_devnodes(sc);
1072
1073         return (0);
1074 }
1075
1076 /* Retrieve a complete descriptor for a certain device and index. */
1077 static usb_config_descriptor_t *
1078 ugen_get_cdesc(struct ugen_softc *sc, int index, int *lenp)
1079 {
1080         usb_config_descriptor_t *cdesc, *tdesc, cdescr;
1081         int len;
1082         usbd_status err;
1083
1084         if (index == USB_CURRENT_CONFIG_INDEX) {
1085                 tdesc = usbd_get_config_descriptor(sc->sc_udev);
1086                 len = UGETW(tdesc->wTotalLength);
1087                 if (lenp)
1088                         *lenp = len;
1089                 cdesc = kmalloc(len, M_TEMP, M_INTWAIT);
1090                 memcpy(cdesc, tdesc, len);
1091                 DPRINTFN(5,("ugen_get_cdesc: current, len=%d\n", len));
1092         } else {
1093                 err = usbd_get_config_desc(sc->sc_udev, index, &cdescr);
1094                 if (err)
1095                         return (0);
1096                 len = UGETW(cdescr.wTotalLength);
1097                 DPRINTFN(5,("ugen_get_cdesc: index=%d, len=%d\n", index, len));
1098                 if (lenp)
1099                         *lenp = len;
1100                 cdesc = kmalloc(len, M_TEMP, M_INTWAIT);
1101                 err = usbd_get_config_desc_full(sc->sc_udev, index, cdesc, len);
1102                 if (err) {
1103                         kfree(cdesc, M_TEMP);
1104                         return (0);
1105                 }
1106         }
1107         return (cdesc);
1108 }
1109
1110 static int
1111 ugen_get_alt_index(struct ugen_softc *sc, int ifaceidx)
1112 {
1113         usbd_interface_handle iface;
1114         usbd_status err;
1115
1116         err = usbd_device2interface_handle(sc->sc_udev, ifaceidx, &iface);
1117         if (err)
1118                 return (-1);
1119         return (usbd_get_interface_altindex(iface));
1120 }
1121
1122 static int
1123 ugen_do_ioctl(struct ugen_softc *sc, int endpt, u_long cmd,
1124               caddr_t addr, int flag)
1125 {
1126         struct ugen_endpoint *sce;
1127         usbd_status err;
1128         usbd_interface_handle iface;
1129         struct usb_config_desc *cd;
1130         usb_config_descriptor_t *cdesc;
1131         struct usb_interface_desc *id;
1132         usb_interface_descriptor_t *idesc;
1133         struct usb_endpoint_desc *ed;
1134         usb_endpoint_descriptor_t *edesc;
1135         struct usb_alt_interface *ai;
1136         struct usb_string_desc *si;
1137         u_int8_t conf, alt;
1138
1139         DPRINTFN(5, ("ugenioctl: cmd=%08lx\n", cmd));
1140         if (sc->sc_dying)
1141                 return (EIO);
1142
1143         switch (cmd) {
1144         case USB_SET_SHORT_XFER:
1145                 /* This flag only affects read */
1146                 if (endpt == USB_CONTROL_ENDPOINT)
1147                         return (EINVAL);
1148                 sce = &sc->sc_endpoints[endpt][IN];
1149                 if (sce == NULL)
1150                         return (EINVAL);
1151
1152                 if (sce->pipeh == NULL) {
1153                         kprintf("ugenioctl: USB_SET_SHORT_XFER, no pipe\n");
1154                         return (EIO);
1155                 }
1156
1157                 if (*(int *)addr)
1158                         sce->state |= UGEN_SHORT_OK;
1159                 else
1160                         sce->state &= ~UGEN_SHORT_OK;
1161                 return (0);
1162         case USB_SET_TIMEOUT:
1163                 sce = &sc->sc_endpoints[endpt][IN];
1164                 if (sce == NULL)
1165                         return (EINVAL);
1166                 sce->timeout = *(int *)addr;
1167                 return (0);
1168         default:
1169                 break;
1170         }
1171
1172         if (endpt != USB_CONTROL_ENDPOINT)
1173                 return (EINVAL);
1174
1175         switch (cmd) {
1176 #ifdef USB_DEBUG
1177         case USB_SETDEBUG:
1178                 ugendebug = *(int *)addr;
1179                 break;
1180 #endif
1181         case USB_GET_CONFIG:
1182                 err = usbd_get_config(sc->sc_udev, &conf);
1183                 if (err)
1184                         return (EIO);
1185                 *(int *)addr = conf;
1186                 break;
1187         case USB_SET_CONFIG:
1188                 if (!(flag & FWRITE))
1189                         return (EPERM);
1190                 err = ugen_set_config(sc, *(int *)addr);
1191                 switch (err) {
1192                 case USBD_NORMAL_COMPLETION:
1193                         break;
1194                 case USBD_IN_USE:
1195                         return (EBUSY);
1196                 default:
1197                         return (EIO);
1198                 }
1199                 break;
1200         case USB_GET_ALTINTERFACE:
1201                 ai = (struct usb_alt_interface *)addr;
1202                 err = usbd_device2interface_handle(sc->sc_udev,
1203                           ai->uai_interface_index, &iface);
1204                 if (err)
1205                         return (EINVAL);
1206                 idesc = usbd_get_interface_descriptor(iface);
1207                 if (idesc == NULL)
1208                         return (EIO);
1209                 ai->uai_alt_no = idesc->bAlternateSetting;
1210                 break;
1211         case USB_SET_ALTINTERFACE:
1212                 if (!(flag & FWRITE))
1213                         return (EPERM);
1214                 ai = (struct usb_alt_interface *)addr;
1215                 err = usbd_device2interface_handle(sc->sc_udev,
1216                           ai->uai_interface_index, &iface);
1217                 if (err)
1218                         return (EINVAL);
1219                 err = ugen_set_interface(sc, ai->uai_interface_index, ai->uai_alt_no);
1220                 if (err)
1221                         return (EINVAL);
1222                 break;
1223         case USB_GET_NO_ALT:
1224                 ai = (struct usb_alt_interface *)addr;
1225                 cdesc = ugen_get_cdesc(sc, ai->uai_config_index, 0);
1226                 if (cdesc == NULL)
1227                         return (EINVAL);
1228                 idesc = usbd_find_idesc(cdesc, ai->uai_interface_index, 0);
1229                 if (idesc == NULL) {
1230                         kfree(cdesc, M_TEMP);
1231                         return (EINVAL);
1232                 }
1233                 ai->uai_alt_no = usbd_get_no_alts(cdesc, idesc->bInterfaceNumber);
1234                 kfree(cdesc, M_TEMP);
1235                 break;
1236         case USB_GET_DEVICE_DESC:
1237                 *(usb_device_descriptor_t *)addr =
1238                         *usbd_get_device_descriptor(sc->sc_udev);
1239                 break;
1240         case USB_GET_CONFIG_DESC:
1241                 cd = (struct usb_config_desc *)addr;
1242                 cdesc = ugen_get_cdesc(sc, cd->ucd_config_index, 0);
1243                 if (cdesc == NULL)
1244                         return (EINVAL);
1245                 cd->ucd_desc = *cdesc;
1246                 kfree(cdesc, M_TEMP);
1247                 break;
1248         case USB_GET_INTERFACE_DESC:
1249                 id = (struct usb_interface_desc *)addr;
1250                 cdesc = ugen_get_cdesc(sc, id->uid_config_index, 0);
1251                 if (cdesc == NULL)
1252                         return (EINVAL);
1253                 if (id->uid_config_index == USB_CURRENT_CONFIG_INDEX &&
1254                     id->uid_alt_index == USB_CURRENT_ALT_INDEX)
1255                         alt = ugen_get_alt_index(sc, id->uid_interface_index);
1256                 else
1257                         alt = id->uid_alt_index;
1258                 idesc = usbd_find_idesc(cdesc, id->uid_interface_index, alt);
1259                 if (idesc == NULL) {
1260                         kfree(cdesc, M_TEMP);
1261                         return (EINVAL);
1262                 }
1263                 id->uid_desc = *idesc;
1264                 kfree(cdesc, M_TEMP);
1265                 break;
1266         case USB_GET_ENDPOINT_DESC:
1267                 ed = (struct usb_endpoint_desc *)addr;
1268                 cdesc = ugen_get_cdesc(sc, ed->ued_config_index, 0);
1269                 if (cdesc == NULL)
1270                         return (EINVAL);
1271                 if (ed->ued_config_index == USB_CURRENT_CONFIG_INDEX &&
1272                     ed->ued_alt_index == USB_CURRENT_ALT_INDEX)
1273                         alt = ugen_get_alt_index(sc, ed->ued_interface_index);
1274                 else
1275                         alt = ed->ued_alt_index;
1276                 edesc = usbd_find_edesc(cdesc, ed->ued_interface_index,
1277                                         alt, ed->ued_endpoint_index);
1278                 if (edesc == NULL) {
1279                         kfree(cdesc, M_TEMP);
1280                         return (EINVAL);
1281                 }
1282                 ed->ued_desc = *edesc;
1283                 kfree(cdesc, M_TEMP);
1284                 break;
1285         case USB_GET_FULL_DESC:
1286         {
1287                 int len;
1288                 struct iovec iov;
1289                 struct uio uio;
1290                 struct usb_full_desc *fd = (struct usb_full_desc *)addr;
1291                 int error;
1292
1293                 cdesc = ugen_get_cdesc(sc, fd->ufd_config_index, &len);
1294                 if (len > fd->ufd_size)
1295                         len = fd->ufd_size;
1296                 iov.iov_base = (caddr_t)fd->ufd_data;
1297                 iov.iov_len = len;
1298                 uio.uio_iov = &iov;
1299                 uio.uio_iovcnt = 1;
1300                 uio.uio_resid = len;
1301                 uio.uio_offset = 0;
1302                 uio.uio_segflg = UIO_USERSPACE;
1303                 uio.uio_rw = UIO_READ;
1304                 uio.uio_td = curthread;
1305                 error = uiomove((void *)cdesc, len, &uio);
1306                 kfree(cdesc, M_TEMP);
1307                 return (error);
1308         }
1309         case USB_GET_STRING_DESC:
1310         {
1311                 int size;
1312
1313                 si = (struct usb_string_desc *)addr;
1314                 err = usbd_get_string_desc(sc->sc_udev, si->usd_string_index,
1315                           si->usd_language_id, &si->usd_desc, &size);
1316                 if (err)
1317                         return (EINVAL);
1318                 break;
1319         }
1320         case USB_DO_REQUEST:
1321         {
1322                 struct usb_ctl_request *ur = (void *)addr;
1323                 int len = UGETW(ur->ucr_request.wLength);
1324                 struct iovec iov;
1325                 struct uio uio;
1326                 void *ptr = 0;
1327                 usbd_status err;
1328                 int error = 0;
1329
1330                 if (!(flag & FWRITE))
1331                         return (EPERM);
1332                 /* Avoid requests that would damage the bus integrity. */
1333                 if ((ur->ucr_request.bmRequestType == UT_WRITE_DEVICE &&
1334                      ur->ucr_request.bRequest == UR_SET_ADDRESS) ||
1335                     (ur->ucr_request.bmRequestType == UT_WRITE_DEVICE &&
1336                      ur->ucr_request.bRequest == UR_SET_CONFIG) ||
1337                     (ur->ucr_request.bmRequestType == UT_WRITE_INTERFACE &&
1338                      ur->ucr_request.bRequest == UR_SET_INTERFACE))
1339                         return (EINVAL);
1340
1341                 if (len < 0 || len > 32767)
1342                         return (EINVAL);
1343                 if (len != 0) {
1344                         iov.iov_base = (caddr_t)ur->ucr_data;
1345                         iov.iov_len = len;
1346                         uio.uio_iov = &iov;
1347                         uio.uio_iovcnt = 1;
1348                         uio.uio_resid = len;
1349                         uio.uio_offset = 0;
1350                         uio.uio_segflg = UIO_USERSPACE;
1351                         uio.uio_rw =
1352                                 ur->ucr_request.bmRequestType & UT_READ ?
1353                                 UIO_READ : UIO_WRITE;
1354                         uio.uio_td = curthread;
1355                         ptr = kmalloc(len, M_TEMP, M_WAITOK);
1356                         if (uio.uio_rw == UIO_WRITE) {
1357                                 error = uiomove(ptr, len, &uio);
1358                                 if (error)
1359                                         goto ret;
1360                         }
1361                 }
1362                 sce = &sc->sc_endpoints[endpt][IN];
1363                 err = usbd_do_request_flags(sc->sc_udev, &ur->ucr_request,
1364                           ptr, ur->ucr_flags, &ur->ucr_actlen, sce->timeout);
1365                 if (err) {
1366                         error = EIO;
1367                         goto ret;
1368                 }
1369                 if (len != 0) {
1370                         if (uio.uio_rw == UIO_READ) {
1371                                 error = uiomove(ptr, len, &uio);
1372                                 if (error)
1373                                         goto ret;
1374                         }
1375                 }
1376         ret:
1377                 if (ptr)
1378                         kfree(ptr, M_TEMP);
1379                 return (error);
1380         }
1381         case USB_GET_DEVICEINFO:
1382                 usbd_fill_deviceinfo(sc->sc_udev,
1383                     (struct usb_device_info *)addr, 1);
1384                 break;
1385         default:
1386                 return (EINVAL);
1387         }
1388         return (0);
1389 }
1390
1391 int
1392 ugenioctl(struct dev_ioctl_args *ap)
1393 {
1394         cdev_t dev = ap->a_head.a_dev;
1395         int endpt = UGENENDPOINT(dev);
1396         struct ugen_softc *sc;
1397         int error;
1398
1399         sc = devclass_get_softc(ugen_devclass, UGENUNIT(dev));
1400
1401         sc->sc_refcnt++;
1402         error = ugen_do_ioctl(sc, endpt, ap->a_cmd, ap->a_data, ap->a_fflag);
1403         if (--sc->sc_refcnt < 0)
1404                 usb_detach_wakeup(sc->sc_dev);
1405         return (error);
1406 }
1407
1408 int
1409 ugenpoll(struct dev_poll_args *ap)
1410 {
1411         cdev_t dev = ap->a_head.a_dev;
1412         struct ugen_softc *sc;
1413         struct ugen_endpoint *sce;
1414         int revents = 0;
1415
1416         sc = devclass_get_softc(ugen_devclass, UGENUNIT(dev));
1417
1418         if (sc->sc_dying)
1419                 return (EIO);
1420
1421         /* XXX always IN */
1422         sce = &sc->sc_endpoints[UGENENDPOINT(dev)][IN];
1423         if (sce == NULL)
1424                 return (EINVAL);
1425
1426         if (!sce->edesc) {
1427                 kprintf("ugenpoll: no edesc\n");
1428                 return (EIO);
1429         }
1430         if (!sce->pipeh) {
1431                 kprintf("ugenpoll: no pipe\n");
1432                 return (EIO);
1433         }
1434
1435         crit_enter();
1436         switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
1437         case UE_INTERRUPT:
1438                 if (ap->a_events & (POLLIN | POLLRDNORM)) {
1439                         if (sce->q.c_cc > 0)
1440                                 revents |= ap->a_events & (POLLIN | POLLRDNORM);
1441                         else
1442                                 selrecord(curthread, &sce->rsel);
1443                 }
1444                 break;
1445         case UE_ISOCHRONOUS:
1446                 if (ap->a_events & (POLLIN | POLLRDNORM)) {
1447                         if (sce->cur != sce->fill)
1448                                 revents |= ap->a_events & (POLLIN | POLLRDNORM);
1449                         else
1450                                 selrecord(curthread, &sce->rsel);
1451                 }
1452                 break;
1453         case UE_BULK:
1454                 /*
1455                  * We have no easy way of determining if a read will
1456                  * yield any data or a write will happen.
1457                  * Pretend they will.
1458                  */
1459                 revents |= ap->a_events &
1460                            (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM);
1461                 break;
1462         default:
1463                 break;
1464         }
1465         crit_exit();
1466         ap->a_events = revents;
1467         return (0);
1468 }
1469
1470 DRIVER_MODULE(ugen, uhub, ugen_driver, ugen_devclass, usbd_driver_load, 0);
1471