Merge from vendor branch OPENSSH:
[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.32 2007/07/03 19:28:16 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         char devinfo[1024];
221         usbd_status err;
222         int conf;
223
224         usbd_devinfo(uaa->device, 0, devinfo);
225         sc->sc_dev = self;
226         device_set_desc_copy(self, devinfo);
227         kprintf("%s: %s\n", device_get_nameunit(sc->sc_dev), devinfo);
228
229         sc->sc_udev = udev = uaa->device;
230
231         memset(sc->sc_endpoints, 0, sizeof sc->sc_endpoints);
232
233         /* First set configuration index 0, the default one for ugen. */
234         err = usbd_set_config_index(udev, 0, 0);
235         if (err) {
236                 kprintf("%s: setting configuration index 0 failed\n",
237                        device_get_nameunit(sc->sc_dev));
238                 sc->sc_dying = 1;
239                 return ENXIO;
240         }
241         conf = usbd_get_config_descriptor(udev)->bConfigurationValue;
242
243         /* Set up all the local state for this configuration. */
244         err = ugen_set_config(sc, conf);
245         if (err) {
246                 kprintf("%s: setting configuration %d failed\n",
247                        device_get_nameunit(sc->sc_dev), conf);
248                 sc->sc_dying = 1;
249                 return ENXIO;
250         }
251
252         /* the main device, ctrl endpoint */
253         dev_ops_add(&ugen_ops, 
254                     UGENUNITMASK, UGENMINOR(device_get_unit(sc->sc_dev), 0));
255         make_dev(&ugen_ops, UGENMINOR(device_get_unit(sc->sc_dev), 0),
256                 UID_ROOT, GID_OPERATOR, 0644, "%s", device_get_nameunit(sc->sc_dev));
257
258         return 0;
259 }
260
261 static void
262 ugen_make_devnodes(struct ugen_softc *sc)
263 {
264         int endptno;
265         cdev_t dev;
266
267         for (endptno = 1; endptno < USB_MAX_ENDPOINTS; endptno++) {
268                 if (sc->sc_endpoints[endptno][IN].sc != NULL ||
269                     sc->sc_endpoints[endptno][OUT].sc != NULL ) {
270                         /* endpt can be 0x81 and 0x01, representing
271                          * endpoint address 0x01 and IN/OUT directions.
272                          * We map both endpts to the same device,
273                          * IN is reading from it, OUT is writing to it.
274                          *
275                          * In the if clause above we check whether one
276                          * of the structs is populated.
277                          */
278                         dev = make_dev(&ugen_ops,
279                                 UGENMINOR(device_get_unit(sc->sc_dev), endptno),
280                                 UID_ROOT, GID_OPERATOR, 0644,
281                                 "%s.%d",
282                                 device_get_nameunit(sc->sc_dev), endptno);
283                         if (sc->sc_endpoints[endptno][IN].sc != NULL) {
284                                 reference_dev(dev);
285                                 if (sc->sc_endpoints[endptno][IN].dev)
286                                         release_dev(sc->sc_endpoints[endptno][IN].dev);
287                                 sc->sc_endpoints[endptno][IN].dev = dev;
288                         }
289                         if (sc->sc_endpoints[endptno][OUT].sc != NULL) {
290                                 reference_dev(dev);
291                                 if (sc->sc_endpoints[endptno][OUT].dev)
292                                         release_dev(sc->sc_endpoints[endptno][OUT].dev);
293                                 sc->sc_endpoints[endptno][OUT].dev = dev;
294                         }
295                 }
296         }
297 }
298
299 static void
300 ugen_destroy_devnodes(struct ugen_softc *sc)
301 {
302         int endptno;
303         cdev_t dev;
304
305         /* destroy all devices for the other (existing) endpoints as well */
306         for (endptno = 1; endptno < USB_MAX_ENDPOINTS; endptno++) {
307                 if (sc->sc_endpoints[endptno][IN].sc != NULL ||
308                     sc->sc_endpoints[endptno][OUT].sc != NULL ) {
309                         /* endpt can be 0x81 and 0x01, representing
310                          * endpoint address 0x01 and IN/OUT directions.
311                          * We map both endpoint addresses to the same device,
312                          * IN is reading from it, OUT is writing to it.
313                          *
314                          * In the if clause above we check whether one
315                          * of the structs is populated.
316                          */
317                         dev = sc->sc_endpoints[endptno][IN].dev;
318                         if (dev != NULL) {
319                                 destroy_dev(dev);
320                                 sc->sc_endpoints[endptno][IN].dev = NULL;
321                         }
322                         dev = sc->sc_endpoints[endptno][OUT].dev;
323                         if (dev != NULL) {
324                                 destroy_dev(dev);
325                                 sc->sc_endpoints[endptno][OUT].dev = NULL;
326                         }
327                 }
328         }
329 }
330
331 static int
332 ugen_set_config(struct ugen_softc *sc, int configno)
333 {
334         usbd_device_handle dev = sc->sc_udev;
335         usbd_interface_handle iface;
336         usb_endpoint_descriptor_t *ed;
337         struct ugen_endpoint *sce;
338         u_int8_t niface, nendpt;
339         int ifaceno, endptno, endpt;
340         usbd_status err;
341         int dir;
342
343         DPRINTFN(1,("ugen_set_config: %s to configno %d, sc=%p\n",
344                     device_get_nameunit(sc->sc_dev), configno, sc));
345
346         ugen_destroy_devnodes(sc);
347
348         /* We start at 1, not 0, because we don't care whether the
349          * control endpoint is open or not. It is always present.
350          */
351         for (endptno = 1; endptno < USB_MAX_ENDPOINTS; endptno++) {
352                 if (sc->sc_is_open[endptno]) {
353                         DPRINTFN(1,
354                              ("ugen_set_config: %s - endpoint %d is open\n",
355                               device_get_nameunit(sc->sc_dev), endptno));
356                         return (USBD_IN_USE);
357                 }
358         }
359
360         /* Avoid setting the current value. */
361         if (usbd_get_config_descriptor(dev)->bConfigurationValue != configno) {
362                 err = usbd_set_config_no(dev, configno, 1);
363                 if (err)
364                         return (err);
365         }
366
367         err = usbd_interface_count(dev, &niface);
368         if (err)
369                 return (err);
370         memset(sc->sc_endpoints, 0, sizeof sc->sc_endpoints);
371         for (ifaceno = 0; ifaceno < niface; ifaceno++) {
372                 DPRINTFN(1,("ugen_set_config: ifaceno %d\n", ifaceno));
373                 err = usbd_device2interface_handle(dev, ifaceno, &iface);
374                 if (err)
375                         return (err);
376                 err = usbd_endpoint_count(iface, &nendpt);
377                 if (err)
378                         return (err);
379                 for (endptno = 0; endptno < nendpt; endptno++) {
380                         ed = usbd_interface2endpoint_descriptor(iface,endptno);
381                         endpt = ed->bEndpointAddress;
382                         dir = UE_GET_DIR(endpt) == UE_DIR_IN ? IN : OUT;
383                         sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)][dir];
384                         DPRINTFN(1,("ugen_set_config: endptno %d, endpt=0x%02x"
385                                     "(%d,%d), sce=%p\n",
386                                     endptno, endpt, UE_GET_ADDR(endpt),
387                                     UE_GET_DIR(endpt), sce));
388                         sce->sc = sc;
389                         sce->edesc = ed;
390                         sce->iface = iface;
391                 }
392         }
393
394         ugen_make_devnodes(sc);
395
396         return (USBD_NORMAL_COMPLETION);
397 }
398
399 int
400 ugenopen(struct dev_open_args *ap)
401 {
402         cdev_t dev = ap->a_head.a_dev;
403         struct ugen_softc *sc;
404         int unit = UGENUNIT(dev);
405         int endpt = UGENENDPOINT(dev);
406         usb_endpoint_descriptor_t *edesc;
407         struct ugen_endpoint *sce;
408         int dir, isize;
409         usbd_status err;
410         usbd_xfer_handle xfer;
411         void *buf;
412         int i, j;
413
414         sc = devclass_get_softc(ugen_devclass, unit);
415         if (sc == NULL)
416                 return (ENXIO);
417
418         DPRINTFN(5, ("ugenopen: flag=%d, mode=%d, unit=%d endpt=%d\n",
419                      ap->a_oflags, ap->a_devtype, unit, endpt));
420
421         if (sc == NULL || sc->sc_dying)
422                 return (ENXIO);
423
424         if (sc->sc_is_open[endpt])
425                 return (EBUSY);
426
427         if (endpt == USB_CONTROL_ENDPOINT) {
428                 sc->sc_is_open[USB_CONTROL_ENDPOINT] = 1;
429                 return (0);
430         }
431
432         /* Make sure there are pipes for all directions. */
433         for (dir = OUT; dir <= IN; dir++) {
434                 if (ap->a_oflags & (dir == OUT ? FWRITE : FREAD)) {
435                         sce = &sc->sc_endpoints[endpt][dir];
436                         if (sce == 0 || sce->edesc == 0)
437                                 return (ENXIO);
438                 }
439         }
440
441         /* Actually open the pipes. */
442         /* XXX Should back out properly if it fails. */
443         for (dir = OUT; dir <= IN; dir++) {
444                 if (!(ap->a_oflags & (dir == OUT ? FWRITE : FREAD)))
445                         continue;
446                 sce = &sc->sc_endpoints[endpt][dir];
447                 sce->state = 0;
448                 sce->timeout = USBD_NO_TIMEOUT;
449                 DPRINTFN(5, ("ugenopen: sc=%p, endpt=%d, dir=%d, sce=%p\n",
450                              sc, endpt, dir, sce));
451                 edesc = sce->edesc;
452                 switch (edesc->bmAttributes & UE_XFERTYPE) {
453                 case UE_INTERRUPT:
454                         if (dir == OUT) {
455                                 err = usbd_open_pipe(sce->iface,
456                                     edesc->bEndpointAddress, 0, &sce->pipeh);
457                                 if (err)
458                                         return (EIO);
459                                 break;
460                         }
461                         isize = UGETW(edesc->wMaxPacketSize);
462                         if (isize == 0) /* shouldn't happen */
463                                 return (EINVAL);
464                         sce->ibuf = kmalloc(isize, M_USBDEV, M_WAITOK);
465                         DPRINTFN(5, ("ugenopen: intr endpt=%d,isize=%d\n",
466                                      endpt, isize));
467                         if ((clist_alloc_cblocks(&sce->q, UGEN_IBSIZE,
468                                                  UGEN_IBSIZE), 0) == -1)
469                                 return (ENOMEM);
470                         err = usbd_open_pipe_intr(sce->iface,
471                                 edesc->bEndpointAddress,
472                                 USBD_SHORT_XFER_OK, &sce->pipeh, sce,
473                                 sce->ibuf, isize, ugenintr,
474                                 USBD_DEFAULT_INTERVAL);
475                         if (err) {
476                                 kfree(sce->ibuf, M_USBDEV);
477                                 clist_free_cblocks(&sce->q);
478                                 return (EIO);
479                         }
480                         DPRINTFN(5, ("ugenopen: interrupt open done\n"));
481                         break;
482                 case UE_BULK:
483                         err = usbd_open_pipe(sce->iface,
484                                   edesc->bEndpointAddress, 0, &sce->pipeh);
485                         if (err)
486                                 return (EIO);
487                         break;
488                 case UE_ISOCHRONOUS:
489                         if (dir == OUT)
490                                 return (EINVAL);
491                         isize = UGETW(edesc->wMaxPacketSize);
492                         if (isize == 0) /* shouldn't happen */
493                                 return (EINVAL);
494                         sce->ibuf = kmalloc(isize * UGEN_NISOFRAMES,
495                                 M_USBDEV, M_WAITOK);
496                         sce->cur = sce->fill = sce->ibuf;
497                         sce->limit = sce->ibuf + isize * UGEN_NISOFRAMES;
498                         DPRINTFN(5, ("ugenopen: isoc endpt=%d, isize=%d\n",
499                                      endpt, isize));
500                         err = usbd_open_pipe(sce->iface,
501                                   edesc->bEndpointAddress, 0, &sce->pipeh);
502                         if (err) {
503                                 kfree(sce->ibuf, M_USBDEV);
504                                 return (EIO);
505                         }
506                         for(i = 0; i < UGEN_NISOREQS; ++i) {
507                                 sce->isoreqs[i].sce = sce;
508                                 xfer = usbd_alloc_xfer(sc->sc_udev);
509                                 if (xfer == 0)
510                                         goto bad;
511                                 sce->isoreqs[i].xfer = xfer;
512                                 buf = usbd_alloc_buffer
513                                         (xfer, isize * UGEN_NISORFRMS);
514                                 if (buf == 0) {
515                                         i++;
516                                         goto bad;
517                                 }
518                                 sce->isoreqs[i].dmabuf = buf;
519                                 for(j = 0; j < UGEN_NISORFRMS; ++j)
520                                         sce->isoreqs[i].sizes[j] = isize;
521                                 usbd_setup_isoc_xfer
522                                         (xfer, sce->pipeh, &sce->isoreqs[i],
523                                          sce->isoreqs[i].sizes,
524                                          UGEN_NISORFRMS, USBD_NO_COPY,
525                                          ugen_isoc_rintr);
526                                 (void)usbd_transfer(xfer);
527                         }
528                         DPRINTFN(5, ("ugenopen: isoc open done\n"));
529                         break;
530                 bad:
531                         while (--i >= 0) /* implicit buffer free */
532                                 usbd_free_xfer(sce->isoreqs[i].xfer);
533                         return (ENOMEM);
534                 case UE_CONTROL:
535                         sce->timeout = USBD_DEFAULT_TIMEOUT;
536                         return (EINVAL);
537                 }
538         }
539         sc->sc_is_open[endpt] = 1;
540         return (0);
541 }
542
543 int
544 ugenclose(struct dev_close_args *ap)
545 {
546         cdev_t dev = ap->a_head.a_dev;
547         int endpt = UGENENDPOINT(dev);
548         struct ugen_softc *sc;
549         struct ugen_endpoint *sce;
550         int dir;
551         int i;
552
553         sc = devclass_get_softc(ugen_devclass, UGENUNIT(dev));
554
555         DPRINTFN(5, ("ugenclose: flag=%d, mode=%d, unit=%d, endpt=%d\n",
556                      ap->a_fflag, ap->a_devtype, UGENUNIT(dev), endpt));
557
558 #ifdef DIAGNOSTIC
559         if (!sc->sc_is_open[endpt]) {
560                 kprintf("ugenclose: not open\n");
561                 return (EINVAL);
562         }
563 #endif
564
565         if (endpt == USB_CONTROL_ENDPOINT) {
566                 DPRINTFN(5, ("ugenclose: close control\n"));
567                 sc->sc_is_open[endpt] = 0;
568                 return (0);
569         }
570
571         for (dir = OUT; dir <= IN; dir++) {
572                 if (!(ap->a_fflag & (dir == OUT ? FWRITE : FREAD)))
573                         continue;
574                 sce = &sc->sc_endpoints[endpt][dir];
575                 if (sce == NULL || sce->pipeh == NULL)
576                         continue;
577                 DPRINTFN(5, ("ugenclose: endpt=%d dir=%d sce=%p\n",
578                              endpt, dir, sce));
579
580                 usbd_abort_pipe(sce->pipeh);
581                 usbd_close_pipe(sce->pipeh);
582                 sce->pipeh = NULL;
583
584                 switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
585                 case UE_INTERRUPT:
586                         ndflush(&sce->q, sce->q.c_cc);
587                         clist_free_cblocks(&sce->q);
588                         break;
589                 case UE_ISOCHRONOUS:
590                         for (i = 0; i < UGEN_NISOREQS; ++i)
591                                 usbd_free_xfer(sce->isoreqs[i].xfer);
592                 default:
593                         break;
594                 }
595
596                 if (sce->ibuf != NULL) {
597                         kfree(sce->ibuf, M_USBDEV);
598                         sce->ibuf = NULL;
599                         clist_free_cblocks(&sce->q);
600                 }
601         }
602         sc->sc_is_open[endpt] = 0;
603
604         return (0);
605 }
606
607 static int
608 ugen_do_read(struct ugen_softc *sc, int endpt, struct uio *uio, int flag)
609 {
610         struct ugen_endpoint *sce = &sc->sc_endpoints[endpt][IN];
611         u_int32_t n, tn;
612         char *buf;
613         usbd_xfer_handle xfer;
614         usbd_status err;
615         int error = 0;
616         int ugen_bbsize;
617         u_char buffer[UGEN_CHUNK];
618
619         DPRINTFN(5, ("%s: ugenread: %d\n", device_get_nameunit(sc->sc_dev), endpt));
620
621         if (sc->sc_dying)
622                 return (EIO);
623
624         if (endpt == USB_CONTROL_ENDPOINT)
625                 return (ENODEV);
626
627         if (sce == NULL)
628                 return (EINVAL);
629
630         if (sce->edesc == NULL) {
631                 kprintf("ugenread: no edesc\n");
632                 return (EIO);
633         }
634         if (sce->pipeh == NULL) {
635                 kprintf("ugenread: no pipe\n");
636                 return (EIO);
637         }
638
639         buf = getugenbuf(ugen_bufsize, &ugen_bbsize);
640
641         switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
642         case UE_INTERRUPT:
643                 /* Block until activity occurred. */
644                 crit_enter();
645                 while (sce->q.c_cc == 0) {
646                         if (flag & IO_NDELAY) {
647                                 crit_exit();
648                                 error = EWOULDBLOCK;
649                                 goto done;
650                         }
651                         sce->state |= UGEN_ASLP;
652                         DPRINTFN(5, ("ugenread: sleep on %p\n", sce));
653                         error = tsleep(sce, PCATCH, "ugenri", 0);
654                         DPRINTFN(5, ("ugenread: woke, error=%d\n", error));
655                         if (sc->sc_dying)
656                                 error = EIO;
657                         if (error) {
658                                 sce->state &= ~UGEN_ASLP;
659                                 break;
660                         }
661                 }
662                 crit_exit();
663
664                 /* Transfer as many chunks as possible. */
665                 while (sce->q.c_cc > 0 && uio->uio_resid > 0 && !error) {
666                         n = min(sce->q.c_cc, uio->uio_resid);
667                         if (n > sizeof(buffer))
668                                 n = sizeof(buffer);
669
670                         /* Remove a small chunk from the input queue. */
671                         q_to_b(&sce->q, buffer, n);
672                         DPRINTFN(5, ("ugenread: got %d chars\n", n));
673
674                         /* Copy the data to the user process. */
675                         error = uiomove(buffer, n, uio);
676                         if (error)
677                                 break;
678                 }
679                 break;
680         case UE_BULK:
681                 xfer = usbd_alloc_xfer(sc->sc_udev);
682                 if (xfer == 0) {
683                         error = ENOMEM;
684                         goto done;
685                 }
686                 while ((n = min(ugen_bbsize, uio->uio_resid)) != 0) {
687                         DPRINTFN(1, ("ugenread: start transfer %d bytes\n",n));
688                         tn = n;
689                         err = usbd_bulk_transfer(
690                                 xfer, sce->pipeh,
691                                 sce->state & UGEN_SHORT_OK ?
692                                     USBD_SHORT_XFER_OK : 0,
693                                 sce->timeout, buf, &tn, "ugenrb");
694                         if (err) {
695                                 if (err == USBD_INTERRUPTED)
696                                         error = EINTR;
697                                 else if (err == USBD_TIMEOUT)
698                                         error = ETIMEDOUT;
699                                 else
700                                         error = EIO;
701                                 break;
702                         }
703                         DPRINTFN(1, ("ugenread: got %d bytes\n", tn));
704                         error = uiomove(buf, tn, uio);
705                         if (error || tn < n)
706                                 break;
707                 }
708                 usbd_free_xfer(xfer);
709                 break;
710         case UE_ISOCHRONOUS:
711                 crit_enter();
712                 while (sce->cur == sce->fill) {
713                         if (flag & IO_NDELAY) {
714                                 crit_exit();
715                                 error = EWOULDBLOCK;
716                                 goto done;
717                         }
718                         sce->state |= UGEN_ASLP;
719                         DPRINTFN(5, ("ugenread: sleep on %p\n", sce));
720                         error = tsleep(sce, PCATCH, "ugenri", 0);
721                         DPRINTFN(5, ("ugenread: woke, error=%d\n", error));
722                         if (sc->sc_dying)
723                                 error = EIO;
724                         if (error) {
725                                 sce->state &= ~UGEN_ASLP;
726                                 break;
727                         }
728                 }
729
730                 while (sce->cur != sce->fill && uio->uio_resid > 0 && !error) {
731                         if(sce->fill > sce->cur)
732                                 n = min(sce->fill - sce->cur, uio->uio_resid);
733                         else
734                                 n = min(sce->limit - sce->cur, uio->uio_resid);
735
736                         DPRINTFN(5, ("ugenread: isoc got %d chars\n", n));
737
738                         /* Copy the data to the user process. */
739                         error = uiomove(sce->cur, n, uio);
740                         if (error)
741                                 break;
742                         sce->cur += n;
743                         if(sce->cur >= sce->limit)
744                                 sce->cur = sce->ibuf;
745                 }
746                 crit_exit();
747                 break;
748
749
750         default:
751                 error = ENXIO;
752                 break;
753         }
754 done:
755         relugenbuf(buf, ugen_bbsize);
756         return (error);
757 }
758
759 int
760 ugenread(struct dev_read_args *ap)
761 {
762         cdev_t dev = ap->a_head.a_dev;
763         int endpt = UGENENDPOINT(dev);
764         struct ugen_softc *sc;
765         int error;
766
767         sc = devclass_get_softc(ugen_devclass, UGENUNIT(dev));
768
769         sc->sc_refcnt++;
770         error = ugen_do_read(sc, endpt, ap->a_uio, ap->a_ioflag);
771         if (--sc->sc_refcnt < 0)
772                 usb_detach_wakeup(sc->sc_dev);
773         return (error);
774 }
775
776 static int
777 ugen_do_write(struct ugen_softc *sc, int endpt, struct uio *uio, int flag)
778 {
779         struct ugen_endpoint *sce = &sc->sc_endpoints[endpt][OUT];
780         u_int32_t n;
781         int error = 0;
782         int ugen_bbsize;
783         char *buf;
784         usbd_xfer_handle xfer;
785         usbd_status err;
786
787         DPRINTFN(5, ("%s: ugenwrite: %d\n", device_get_nameunit(sc->sc_dev), endpt));
788
789         if (sc->sc_dying)
790                 return (EIO);
791
792         if (endpt == USB_CONTROL_ENDPOINT)
793                 return (ENODEV);
794
795         if (sce == NULL)
796                 return (EINVAL);
797
798         if (sce->edesc == NULL) {
799                 kprintf("ugenwrite: no edesc\n");
800                 return (EIO);
801         }
802         if (sce->pipeh == NULL) {
803                 kprintf("ugenwrite: no pipe\n");
804                 return (EIO);
805         }
806
807         buf = getugenbuf(ugen_bufsize, &ugen_bbsize);
808
809         switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
810         case UE_BULK:
811                 xfer = usbd_alloc_xfer(sc->sc_udev);
812                 if (xfer == 0) {
813                         error = EIO;
814                         goto done;
815                 }
816                 while ((n = min(ugen_bbsize, uio->uio_resid)) != 0) {
817                         error = uiomove(buf, n, uio);
818                         if (error)
819                                 break;
820                         DPRINTFN(1, ("ugenwrite: transfer %d bytes\n", n));
821                         err = usbd_bulk_transfer(xfer, sce->pipeh, 0,
822                                   sce->timeout, buf, &n,"ugenwb");
823                         if (err) {
824                                 if (err == USBD_INTERRUPTED)
825                                         error = EINTR;
826                                 else if (err == USBD_TIMEOUT)
827                                         error = ETIMEDOUT;
828                                 else
829                                         error = EIO;
830                                 break;
831                         }
832                 }
833                 usbd_free_xfer(xfer);
834                 break;
835         case UE_INTERRUPT:
836                 xfer = usbd_alloc_xfer(sc->sc_udev);
837                 if (xfer == 0) {
838                         error = EIO;
839                         goto done;
840                 }
841                 while ((n = min(UGETW(sce->edesc->wMaxPacketSize),
842                     uio->uio_resid)) != 0) {
843                         error = uiomove(buf, n, uio);
844                         if (error)
845                                 break;
846                         DPRINTFN(1, ("ugenwrite: transfer %d bytes\n", n));
847                         err = usbd_intr_transfer(xfer, sce->pipeh, 0,
848                                   sce->timeout, buf, &n,"ugenwi");
849                         if (err) {
850                                 if (err == USBD_INTERRUPTED)
851                                         error = EINTR;
852                                 else if (err == USBD_TIMEOUT)
853                                         error = ETIMEDOUT;
854                                 else
855                                         error = EIO;
856                                 break;
857                         }
858                 }
859                 usbd_free_xfer(xfer);
860                 break;
861         default:
862                 error = ENXIO;
863                 break;
864         }
865 done:
866         relugenbuf(buf, ugen_bbsize);
867         return (error);
868 }
869
870 int
871 ugenwrite(struct dev_write_args *ap)
872 {
873         cdev_t dev = ap->a_head.a_dev;
874         int endpt = UGENENDPOINT(dev);
875         struct ugen_softc *sc;
876         int error;
877
878         sc = devclass_get_softc(ugen_devclass, UGENUNIT(dev));
879
880         sc->sc_refcnt++;
881         error = ugen_do_write(sc, endpt, ap->a_uio, ap->a_ioflag);
882         if (--sc->sc_refcnt < 0)
883                 usb_detach_wakeup(sc->sc_dev);
884         return (error);
885 }
886
887 static int
888 ugen_detach(device_t self)
889 {
890         struct ugen_softc *sc = device_get_softc(self);
891         struct ugen_endpoint *sce;
892         int i, dir;
893
894         DPRINTF(("ugen_detach: sc=%p\n", sc));
895
896         sc->sc_dying = 1;
897         /* Abort all pipes.  Causes processes waiting for transfer to wake. */
898         for (i = 0; i < USB_MAX_ENDPOINTS; i++) {
899                 for (dir = OUT; dir <= IN; dir++) {
900                         sce = &sc->sc_endpoints[i][dir];
901                         if (sce && sce->pipeh)
902                                 usbd_abort_pipe(sce->pipeh);
903                 }
904         }
905         crit_enter();
906         if (--sc->sc_refcnt >= 0) {
907                 /* Wake everyone */
908                 for (i = 0; i < USB_MAX_ENDPOINTS; i++)
909                         wakeup(&sc->sc_endpoints[i][IN]);
910                 /* Wait for processes to go away. */
911                 usb_detach_wait(sc->sc_dev);
912         }
913         crit_exit();
914
915         /* destroy the device for the control endpoint */
916         ugen_destroy_devnodes(sc);
917         dev_ops_remove(&ugen_ops, 
918                     UGENUNITMASK, UGENMINOR(device_get_unit(sc->sc_dev), 0));
919         return (0);
920 }
921
922 static void
923 ugenintr(usbd_xfer_handle xfer, usbd_private_handle addr, usbd_status status)
924 {
925         struct ugen_endpoint *sce = addr;
926         /*struct ugen_softc *sc = sce->sc;*/
927         u_int32_t count;
928         u_char *ibuf;
929
930         if (status == USBD_CANCELLED)
931                 return;
932
933         if (status != USBD_NORMAL_COMPLETION) {
934                 DPRINTF(("ugenintr: status=%d\n", status));
935                 if (status == USBD_STALLED)
936                     usbd_clear_endpoint_stall_async(sce->pipeh);
937                 return;
938         }
939
940         usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
941         ibuf = sce->ibuf;
942
943         DPRINTFN(5, ("ugenintr: xfer=%p status=%d count=%d\n",
944                      xfer, status, count));
945         DPRINTFN(5, ("          data = %02x %02x %02x\n",
946                      ibuf[0], ibuf[1], ibuf[2]));
947
948         (void)b_to_q(ibuf, count, &sce->q);
949
950         if (sce->state & UGEN_ASLP) {
951                 sce->state &= ~UGEN_ASLP;
952                 DPRINTFN(5, ("ugen_intr: waking %p\n", sce));
953                 wakeup(sce);
954         }
955         selwakeup(&sce->rsel);
956 }
957
958 static void
959 ugen_isoc_rintr(usbd_xfer_handle xfer, usbd_private_handle addr,
960                 usbd_status status)
961 {
962         struct isoreq *req = addr;
963         struct ugen_endpoint *sce = req->sce;
964         u_int32_t count, n;
965         int i, isize;
966
967         /* Return if we are aborting. */
968         if (status == USBD_CANCELLED)
969                 return;
970
971         usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
972         DPRINTFN(5,("ugen_isoc_rintr: xfer %d, count=%d\n",
973                     (int)(req - sce->isoreqs),
974                     count));
975
976         /* throw away oldest input if the buffer is full */
977         if(sce->fill < sce->cur && sce->cur <= sce->fill + count) {
978                 sce->cur += count;
979                 if(sce->cur >= sce->limit)
980                         sce->cur = sce->ibuf + (sce->limit - sce->cur);
981                 DPRINTFN(5, ("ugen_isoc_rintr: throwing away %d bytes\n",
982                              count));
983         }
984
985         isize = UGETW(sce->edesc->wMaxPacketSize);
986         for (i = 0; i < UGEN_NISORFRMS; i++) {
987                 u_int32_t actlen = req->sizes[i];
988                 char const *buf = (char const *)req->dmabuf + isize * i;
989
990                 /* copy data to buffer */
991                 while (actlen > 0) {
992                         n = min(actlen, sce->limit - sce->fill);
993                         memcpy(sce->fill, buf, n);
994
995                         buf += n;
996                         actlen -= n;
997                         sce->fill += n;
998                         if(sce->fill == sce->limit)
999                                 sce->fill = sce->ibuf;
1000                 }
1001
1002                 /* setup size for next transfer */
1003                 req->sizes[i] = isize;
1004         }
1005
1006         usbd_setup_isoc_xfer(xfer, sce->pipeh, req, req->sizes, UGEN_NISORFRMS,
1007                              USBD_NO_COPY, ugen_isoc_rintr);
1008         (void)usbd_transfer(xfer);
1009
1010         if (sce->state & UGEN_ASLP) {
1011                 sce->state &= ~UGEN_ASLP;
1012                 DPRINTFN(5, ("ugen_isoc_rintr: waking %p\n", sce));
1013                 wakeup(sce);
1014         }
1015         selwakeup(&sce->rsel);
1016 }
1017
1018 static usbd_status
1019 ugen_set_interface(struct ugen_softc *sc, int ifaceidx, int altno)
1020 {
1021         usbd_interface_handle iface;
1022         usb_endpoint_descriptor_t *ed;
1023         usbd_status err;
1024         struct ugen_endpoint *sce;
1025         u_int8_t niface, nendpt, endptno, endpt;
1026         int dir;
1027
1028         DPRINTFN(15, ("ugen_set_interface %d %d\n", ifaceidx, altno));
1029
1030         err = usbd_interface_count(sc->sc_udev, &niface);
1031         if (err)
1032                 return (err);
1033         if (ifaceidx < 0 || ifaceidx >= niface)
1034                 return (USBD_INVAL);
1035
1036         err = usbd_device2interface_handle(sc->sc_udev, ifaceidx, &iface);
1037         if (err)
1038                 return (err);
1039         err = usbd_endpoint_count(iface, &nendpt);
1040         if (err)
1041                 return (err);
1042
1043         /* destroy the existing devices, we remake the new ones in a moment */
1044         ugen_destroy_devnodes(sc);
1045
1046         /* XXX should only do this after setting new altno has succeeded */
1047         for (endptno = 0; endptno < nendpt; endptno++) {
1048                 ed = usbd_interface2endpoint_descriptor(iface,endptno);
1049                 endpt = ed->bEndpointAddress;
1050                 dir = UE_GET_DIR(endpt) == UE_DIR_IN ? IN : OUT;
1051                 sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)][dir];
1052                 sce->sc = 0;
1053                 sce->edesc = 0;
1054                 sce->iface = 0;
1055         }
1056
1057         /* change setting */
1058         err = usbd_set_interface(iface, altno);
1059         if (err)
1060                 return (err);
1061
1062         err = usbd_endpoint_count(iface, &nendpt);
1063         if (err)
1064                 return (err);
1065         for (endptno = 0; endptno < nendpt; endptno++) {
1066                 ed = usbd_interface2endpoint_descriptor(iface,endptno);
1067                 endpt = ed->bEndpointAddress;
1068                 dir = UE_GET_DIR(endpt) == UE_DIR_IN ? IN : OUT;
1069                 sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)][dir];
1070                 sce->sc = sc;
1071                 sce->edesc = ed;
1072                 sce->iface = iface;
1073         }
1074
1075         /* make the new devices */
1076         ugen_make_devnodes(sc);
1077
1078         return (0);
1079 }
1080
1081 /* Retrieve a complete descriptor for a certain device and index. */
1082 static usb_config_descriptor_t *
1083 ugen_get_cdesc(struct ugen_softc *sc, int index, int *lenp)
1084 {
1085         usb_config_descriptor_t *cdesc, *tdesc, cdescr;
1086         int len;
1087         usbd_status err;
1088
1089         if (index == USB_CURRENT_CONFIG_INDEX) {
1090                 tdesc = usbd_get_config_descriptor(sc->sc_udev);
1091                 len = UGETW(tdesc->wTotalLength);
1092                 if (lenp)
1093                         *lenp = len;
1094                 cdesc = kmalloc(len, M_TEMP, M_INTWAIT);
1095                 memcpy(cdesc, tdesc, len);
1096                 DPRINTFN(5,("ugen_get_cdesc: current, len=%d\n", len));
1097         } else {
1098                 err = usbd_get_config_desc(sc->sc_udev, index, &cdescr);
1099                 if (err)
1100                         return (0);
1101                 len = UGETW(cdescr.wTotalLength);
1102                 DPRINTFN(5,("ugen_get_cdesc: index=%d, len=%d\n", index, len));
1103                 if (lenp)
1104                         *lenp = len;
1105                 cdesc = kmalloc(len, M_TEMP, M_INTWAIT);
1106                 err = usbd_get_config_desc_full(sc->sc_udev, index, cdesc, len);
1107                 if (err) {
1108                         kfree(cdesc, M_TEMP);
1109                         return (0);
1110                 }
1111         }
1112         return (cdesc);
1113 }
1114
1115 static int
1116 ugen_get_alt_index(struct ugen_softc *sc, int ifaceidx)
1117 {
1118         usbd_interface_handle iface;
1119         usbd_status err;
1120
1121         err = usbd_device2interface_handle(sc->sc_udev, ifaceidx, &iface);
1122         if (err)
1123                 return (-1);
1124         return (usbd_get_interface_altindex(iface));
1125 }
1126
1127 static int
1128 ugen_do_ioctl(struct ugen_softc *sc, int endpt, u_long cmd,
1129               caddr_t addr, int flag)
1130 {
1131         struct ugen_endpoint *sce;
1132         usbd_status err;
1133         usbd_interface_handle iface;
1134         struct usb_config_desc *cd;
1135         usb_config_descriptor_t *cdesc;
1136         struct usb_interface_desc *id;
1137         usb_interface_descriptor_t *idesc;
1138         struct usb_endpoint_desc *ed;
1139         usb_endpoint_descriptor_t *edesc;
1140         struct usb_alt_interface *ai;
1141         struct usb_string_desc *si;
1142         u_int8_t conf, alt;
1143
1144         DPRINTFN(5, ("ugenioctl: cmd=%08lx\n", cmd));
1145         if (sc->sc_dying)
1146                 return (EIO);
1147
1148         switch (cmd) {
1149         case USB_SET_SHORT_XFER:
1150                 /* This flag only affects read */
1151                 if (endpt == USB_CONTROL_ENDPOINT)
1152                         return (EINVAL);
1153                 sce = &sc->sc_endpoints[endpt][IN];
1154                 if (sce == NULL)
1155                         return (EINVAL);
1156
1157                 if (sce->pipeh == NULL) {
1158                         kprintf("ugenioctl: USB_SET_SHORT_XFER, no pipe\n");
1159                         return (EIO);
1160                 }
1161
1162                 if (*(int *)addr)
1163                         sce->state |= UGEN_SHORT_OK;
1164                 else
1165                         sce->state &= ~UGEN_SHORT_OK;
1166                 return (0);
1167         case USB_SET_TIMEOUT:
1168                 sce = &sc->sc_endpoints[endpt][IN];
1169                 if (sce == NULL)
1170                         return (EINVAL);
1171                 sce->timeout = *(int *)addr;
1172                 return (0);
1173         default:
1174                 break;
1175         }
1176
1177         if (endpt != USB_CONTROL_ENDPOINT)
1178                 return (EINVAL);
1179
1180         switch (cmd) {
1181 #ifdef USB_DEBUG
1182         case USB_SETDEBUG:
1183                 ugendebug = *(int *)addr;
1184                 break;
1185 #endif
1186         case USB_GET_CONFIG:
1187                 err = usbd_get_config(sc->sc_udev, &conf);
1188                 if (err)
1189                         return (EIO);
1190                 *(int *)addr = conf;
1191                 break;
1192         case USB_SET_CONFIG:
1193                 if (!(flag & FWRITE))
1194                         return (EPERM);
1195                 err = ugen_set_config(sc, *(int *)addr);
1196                 switch (err) {
1197                 case USBD_NORMAL_COMPLETION:
1198                         break;
1199                 case USBD_IN_USE:
1200                         return (EBUSY);
1201                 default:
1202                         return (EIO);
1203                 }
1204                 break;
1205         case USB_GET_ALTINTERFACE:
1206                 ai = (struct usb_alt_interface *)addr;
1207                 err = usbd_device2interface_handle(sc->sc_udev,
1208                           ai->uai_interface_index, &iface);
1209                 if (err)
1210                         return (EINVAL);
1211                 idesc = usbd_get_interface_descriptor(iface);
1212                 if (idesc == NULL)
1213                         return (EIO);
1214                 ai->uai_alt_no = idesc->bAlternateSetting;
1215                 break;
1216         case USB_SET_ALTINTERFACE:
1217                 if (!(flag & FWRITE))
1218                         return (EPERM);
1219                 ai = (struct usb_alt_interface *)addr;
1220                 err = usbd_device2interface_handle(sc->sc_udev,
1221                           ai->uai_interface_index, &iface);
1222                 if (err)
1223                         return (EINVAL);
1224                 err = ugen_set_interface(sc, ai->uai_interface_index, ai->uai_alt_no);
1225                 if (err)
1226                         return (EINVAL);
1227                 break;
1228         case USB_GET_NO_ALT:
1229                 ai = (struct usb_alt_interface *)addr;
1230                 cdesc = ugen_get_cdesc(sc, ai->uai_config_index, 0);
1231                 if (cdesc == NULL)
1232                         return (EINVAL);
1233                 idesc = usbd_find_idesc(cdesc, ai->uai_interface_index, 0);
1234                 if (idesc == NULL) {
1235                         kfree(cdesc, M_TEMP);
1236                         return (EINVAL);
1237                 }
1238                 ai->uai_alt_no = usbd_get_no_alts(cdesc, idesc->bInterfaceNumber);
1239                 kfree(cdesc, M_TEMP);
1240                 break;
1241         case USB_GET_DEVICE_DESC:
1242                 *(usb_device_descriptor_t *)addr =
1243                         *usbd_get_device_descriptor(sc->sc_udev);
1244                 break;
1245         case USB_GET_CONFIG_DESC:
1246                 cd = (struct usb_config_desc *)addr;
1247                 cdesc = ugen_get_cdesc(sc, cd->ucd_config_index, 0);
1248                 if (cdesc == NULL)
1249                         return (EINVAL);
1250                 cd->ucd_desc = *cdesc;
1251                 kfree(cdesc, M_TEMP);
1252                 break;
1253         case USB_GET_INTERFACE_DESC:
1254                 id = (struct usb_interface_desc *)addr;
1255                 cdesc = ugen_get_cdesc(sc, id->uid_config_index, 0);
1256                 if (cdesc == NULL)
1257                         return (EINVAL);
1258                 if (id->uid_config_index == USB_CURRENT_CONFIG_INDEX &&
1259                     id->uid_alt_index == USB_CURRENT_ALT_INDEX)
1260                         alt = ugen_get_alt_index(sc, id->uid_interface_index);
1261                 else
1262                         alt = id->uid_alt_index;
1263                 idesc = usbd_find_idesc(cdesc, id->uid_interface_index, alt);
1264                 if (idesc == NULL) {
1265                         kfree(cdesc, M_TEMP);
1266                         return (EINVAL);
1267                 }
1268                 id->uid_desc = *idesc;
1269                 kfree(cdesc, M_TEMP);
1270                 break;
1271         case USB_GET_ENDPOINT_DESC:
1272                 ed = (struct usb_endpoint_desc *)addr;
1273                 cdesc = ugen_get_cdesc(sc, ed->ued_config_index, 0);
1274                 if (cdesc == NULL)
1275                         return (EINVAL);
1276                 if (ed->ued_config_index == USB_CURRENT_CONFIG_INDEX &&
1277                     ed->ued_alt_index == USB_CURRENT_ALT_INDEX)
1278                         alt = ugen_get_alt_index(sc, ed->ued_interface_index);
1279                 else
1280                         alt = ed->ued_alt_index;
1281                 edesc = usbd_find_edesc(cdesc, ed->ued_interface_index,
1282                                         alt, ed->ued_endpoint_index);
1283                 if (edesc == NULL) {
1284                         kfree(cdesc, M_TEMP);
1285                         return (EINVAL);
1286                 }
1287                 ed->ued_desc = *edesc;
1288                 kfree(cdesc, M_TEMP);
1289                 break;
1290         case USB_GET_FULL_DESC:
1291         {
1292                 int len;
1293                 struct iovec iov;
1294                 struct uio uio;
1295                 struct usb_full_desc *fd = (struct usb_full_desc *)addr;
1296                 int error;
1297
1298                 cdesc = ugen_get_cdesc(sc, fd->ufd_config_index, &len);
1299                 if (len > fd->ufd_size)
1300                         len = fd->ufd_size;
1301                 iov.iov_base = (caddr_t)fd->ufd_data;
1302                 iov.iov_len = len;
1303                 uio.uio_iov = &iov;
1304                 uio.uio_iovcnt = 1;
1305                 uio.uio_resid = len;
1306                 uio.uio_offset = 0;
1307                 uio.uio_segflg = UIO_USERSPACE;
1308                 uio.uio_rw = UIO_READ;
1309                 uio.uio_td = curthread;
1310                 error = uiomove((void *)cdesc, len, &uio);
1311                 kfree(cdesc, M_TEMP);
1312                 return (error);
1313         }
1314         case USB_GET_STRING_DESC:
1315         {
1316                 int size;
1317
1318                 si = (struct usb_string_desc *)addr;
1319                 err = usbd_get_string_desc(sc->sc_udev, si->usd_string_index,
1320                           si->usd_language_id, &si->usd_desc, &size);
1321                 if (err)
1322                         return (EINVAL);
1323                 break;
1324         }
1325         case USB_DO_REQUEST:
1326         {
1327                 struct usb_ctl_request *ur = (void *)addr;
1328                 int len = UGETW(ur->ucr_request.wLength);
1329                 struct iovec iov;
1330                 struct uio uio;
1331                 void *ptr = 0;
1332                 usbd_status err;
1333                 int error = 0;
1334
1335                 if (!(flag & FWRITE))
1336                         return (EPERM);
1337                 /* Avoid requests that would damage the bus integrity. */
1338                 if ((ur->ucr_request.bmRequestType == UT_WRITE_DEVICE &&
1339                      ur->ucr_request.bRequest == UR_SET_ADDRESS) ||
1340                     (ur->ucr_request.bmRequestType == UT_WRITE_DEVICE &&
1341                      ur->ucr_request.bRequest == UR_SET_CONFIG) ||
1342                     (ur->ucr_request.bmRequestType == UT_WRITE_INTERFACE &&
1343                      ur->ucr_request.bRequest == UR_SET_INTERFACE))
1344                         return (EINVAL);
1345
1346                 if (len < 0 || len > 32767)
1347                         return (EINVAL);
1348                 if (len != 0) {
1349                         iov.iov_base = (caddr_t)ur->ucr_data;
1350                         iov.iov_len = len;
1351                         uio.uio_iov = &iov;
1352                         uio.uio_iovcnt = 1;
1353                         uio.uio_resid = len;
1354                         uio.uio_offset = 0;
1355                         uio.uio_segflg = UIO_USERSPACE;
1356                         uio.uio_rw =
1357                                 ur->ucr_request.bmRequestType & UT_READ ?
1358                                 UIO_READ : UIO_WRITE;
1359                         uio.uio_td = curthread;
1360                         ptr = kmalloc(len, M_TEMP, M_WAITOK);
1361                         if (uio.uio_rw == UIO_WRITE) {
1362                                 error = uiomove(ptr, len, &uio);
1363                                 if (error)
1364                                         goto ret;
1365                         }
1366                 }
1367                 sce = &sc->sc_endpoints[endpt][IN];
1368                 err = usbd_do_request_flags(sc->sc_udev, &ur->ucr_request,
1369                           ptr, ur->ucr_flags, &ur->ucr_actlen, sce->timeout);
1370                 if (err) {
1371                         error = EIO;
1372                         goto ret;
1373                 }
1374                 if (len != 0) {
1375                         if (uio.uio_rw == UIO_READ) {
1376                                 error = uiomove(ptr, len, &uio);
1377                                 if (error)
1378                                         goto ret;
1379                         }
1380                 }
1381         ret:
1382                 if (ptr)
1383                         kfree(ptr, M_TEMP);
1384                 return (error);
1385         }
1386         case USB_GET_DEVICEINFO:
1387                 usbd_fill_deviceinfo(sc->sc_udev,
1388                     (struct usb_device_info *)addr, 1);
1389                 break;
1390         default:
1391                 return (EINVAL);
1392         }
1393         return (0);
1394 }
1395
1396 int
1397 ugenioctl(struct dev_ioctl_args *ap)
1398 {
1399         cdev_t dev = ap->a_head.a_dev;
1400         int endpt = UGENENDPOINT(dev);
1401         struct ugen_softc *sc;
1402         int error;
1403
1404         sc = devclass_get_softc(ugen_devclass, UGENUNIT(dev));
1405
1406         sc->sc_refcnt++;
1407         error = ugen_do_ioctl(sc, endpt, ap->a_cmd, ap->a_data, ap->a_fflag);
1408         if (--sc->sc_refcnt < 0)
1409                 usb_detach_wakeup(sc->sc_dev);
1410         return (error);
1411 }
1412
1413 int
1414 ugenpoll(struct dev_poll_args *ap)
1415 {
1416         cdev_t dev = ap->a_head.a_dev;
1417         struct ugen_softc *sc;
1418         struct ugen_endpoint *sce;
1419         int revents = 0;
1420
1421         sc = devclass_get_softc(ugen_devclass, UGENUNIT(dev));
1422
1423         if (sc->sc_dying)
1424                 return (EIO);
1425
1426         /* XXX always IN */
1427         sce = &sc->sc_endpoints[UGENENDPOINT(dev)][IN];
1428         if (sce == NULL)
1429                 return (EINVAL);
1430
1431         if (!sce->edesc) {
1432                 kprintf("ugenpoll: no edesc\n");
1433                 return (EIO);
1434         }
1435         if (!sce->pipeh) {
1436                 kprintf("ugenpoll: no pipe\n");
1437                 return (EIO);
1438         }
1439
1440         crit_enter();
1441         switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
1442         case UE_INTERRUPT:
1443                 if (ap->a_events & (POLLIN | POLLRDNORM)) {
1444                         if (sce->q.c_cc > 0)
1445                                 revents |= ap->a_events & (POLLIN | POLLRDNORM);
1446                         else
1447                                 selrecord(curthread, &sce->rsel);
1448                 }
1449                 break;
1450         case UE_ISOCHRONOUS:
1451                 if (ap->a_events & (POLLIN | POLLRDNORM)) {
1452                         if (sce->cur != sce->fill)
1453                                 revents |= ap->a_events & (POLLIN | POLLRDNORM);
1454                         else
1455                                 selrecord(curthread, &sce->rsel);
1456                 }
1457                 break;
1458         case UE_BULK:
1459                 /*
1460                  * We have no easy way of determining if a read will
1461                  * yield any data or a write will happen.
1462                  * Pretend they will.
1463                  */
1464                 revents |= ap->a_events &
1465                            (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM);
1466                 break;
1467         default:
1468                 break;
1469         }
1470         crit_exit();
1471         ap->a_events = revents;
1472         return (0);
1473 }
1474
1475 DRIVER_MODULE(ugen, uhub, ugen_driver, ugen_devclass, usbd_driver_load, 0);
1476