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