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