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