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