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