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