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