1 /* $NetBSD: ugen.c,v 1.59 2002/07/11 21:14:28 augustss Exp $ */
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 $
10 #include <sys/cdefs.h>
11 __FBSDID("$FreeBSD$");
14 * Copyright (c) 1998 The NetBSD Foundation, Inc.
15 * All rights reserved.
17 * This code is derived from software contributed to The NetBSD Foundation
18 * by Lennart Augustsson (lennart@augustsson.net) at
19 * Carlstedt Research & Technology.
21 * Redistribution and use in source and binary forms, with or without
22 * modification, are permitted provided that the following conditions
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.
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.
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>
61 #include <sys/ioccom.h>
63 #include <sys/fcntl.h>
64 #include <sys/filio.h>
68 #if __FreeBSD_version >= 500014
69 #include <sys/selinfo.h>
71 #include <sys/select.h>
74 #include <sys/sysctl.h>
77 #include <dev/usb/usb.h>
78 #include <dev/usb/usbdi.h>
79 #include <dev/usb/usbdi_util.h>
82 #define DPRINTF(x) if (ugendebug) logprintf x
83 #define DPRINTFN(n,x) if (ugendebug>(n)) logprintf x
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");
93 #define UGEN_CHUNK 128 /* chunk size for read */
94 #define UGEN_IBSIZE 1020 /* buffer size */
95 #define UGEN_BBSIZE 1024
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 */
101 struct ugen_endpoint {
102 struct ugen_softc *sc;
103 #if defined(__FreeBSD__)
106 usb_endpoint_descriptor_t *edesc;
107 usbd_interface_handle iface;
109 #define UGEN_ASLP 0x02 /* waiting for data */
110 #define UGEN_SHORT_OK 0x04 /* short xfers are OK */
111 usbd_pipe_handle pipeh;
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) */
120 struct ugen_endpoint *sce;
121 usbd_xfer_handle xfer;
123 u_int16_t sizes[UGEN_NISORFRMS];
124 } isoreqs[UGEN_NISOREQS];
128 USBBASEDEVICE sc_dev; /* base device */
129 usbd_device_handle sc_udev;
130 #if defined(__FreeBSD__)
134 char sc_is_open[USB_MAX_ENDPOINTS];
135 struct ugen_endpoint sc_endpoints[USB_MAX_ENDPOINTS][2];
140 #define UGEN_DEV_REF(dev, sc) \
141 if ((sc)->sc_dying || dev_refthread(dev) == NULL) \
143 #define UGEN_DEV_RELE(dev, sc) \
145 #define UGEN_DEV_OPEN(dev, sc) \
146 /* handled by dev layer */
147 #define UGEN_DEV_CLOSE(dev, sc) \
148 /* handled by dev layer */
151 #define UGEN_DEV_REF(dev, sc) \
152 if ((sc)->sc_dying) \
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) \
160 #define UGEN_DEV_CLOSE(dev, sc) \
161 UGEN_DEV_RELE(dev, sc)
166 #if defined(__NetBSD__) || defined(__OpenBSD__)
168 #elif defined(__FreeBSD__)
177 Static struct cdevsw ugenctl_cdevsw = {
178 .d_version = D_VERSION,
179 .d_flags = D_NEEDGIANT,
181 .d_close = ugenclose,
182 .d_ioctl = ugenioctl,
183 .d_purge = ugenpurge,
185 #if __FreeBSD_version < 500014
190 Static struct cdevsw ugen_cdevsw = {
191 .d_version = D_VERSION,
192 .d_flags = D_NEEDGIANT,
194 .d_close = ugenclose,
196 .d_write = ugenwrite,
197 .d_ioctl = ugenioctl,
199 .d_purge = ugenpurge,
201 #if __FreeBSD_version < 500014
207 Static void ugenintr(usbd_xfer_handle xfer, usbd_private_handle addr,
209 Static void ugen_isoc_rintr(usbd_xfer_handle xfer, usbd_private_handle addr,
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);
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);
225 #define UGENUNIT(n) ((minor(n) >> 4) & 0xf)
226 #define UGENENDPOINT(n) (minor(n) & 0xf)
227 #define UGENMINOR(u, e) (((u) << 4) | (e))
229 USB_DECLARE_DRIVER(ugen);
233 USB_MATCH_START(ugen, uaa);
237 return (uaa->matchlvl);
240 return (UMATCH_GENERIC);
242 return (UMATCH_NONE);
247 USB_ATTACH_START(ugen, sc, uaa);
248 usbd_device_handle udev;
253 usbd_devinfo(uaa->device, 0, devinfo);
256 sc->sc_udev = udev = uaa->device;
258 memset(sc->sc_endpoints, 0, sizeof sc->sc_endpoints);
260 /* First set configuration index 0, the default one for ugen. */
261 err = usbd_set_config_index(udev, 0, 0);
263 printf("%s: setting configuration index 0 failed\n",
264 USBDEVNAME(sc->sc_dev));
266 USB_ATTACH_ERROR_RETURN;
268 conf = usbd_get_config_descriptor(udev)->bConfigurationValue;
270 /* Set up all the local state for this configuration. */
271 err = ugen_set_config(sc, conf);
273 printf("%s: setting configuration %d failed\n",
274 USBDEVNAME(sc->sc_dev), conf);
276 USB_ATTACH_ERROR_RETURN;
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);
287 USB_ATTACH_SUCCESS_RETURN;
290 #if defined(__FreeBSD__)
292 ugen_make_devnodes(struct ugen_softc *sc)
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.
305 * In the if clause above we check whether one
306 * of the structs is populated.
308 dev = make_dev(&ugen_cdevsw,
309 UGENMINOR(USBDEVUNIT(sc->sc_dev), endptno),
310 UID_ROOT, GID_OPERATOR, 0644,
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;
323 ugen_destroy_devnodes(struct ugen_softc *sc)
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.
337 * In the if clause above we check whether one
338 * of the structs is populated.
340 if (sc->sc_endpoints[endptno][IN].sc != NULL)
341 dev = sc->sc_endpoints[endptno][IN].dev;
343 dev = sc->sc_endpoints[endptno][OUT].dev;
351 ugen_set_config(struct ugen_softc *sc, int configno)
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;
362 DPRINTFN(1,("ugen_set_config: %s to configno %d, sc=%p\n",
363 USBDEVNAME(sc->sc_dev), configno, sc));
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.
368 for (endptno = 1; endptno < USB_MAX_ENDPOINTS; endptno++)
369 if (sc->sc_is_open[endptno]) {
371 ("ugen_set_config: %s - endpoint %d is open\n",
372 USBDEVNAME(sc->sc_dev), endptno));
373 return (USBD_IN_USE);
376 err = usbd_interface_count(dev, &niface);
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,
384 niface_cache = niface;
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);
390 panic("ugen_set_config: can't obtain interface handle");
391 err = usbd_endpoint_count(iface, &nendpt);
393 panic("ugen_set_config: endpoint count failed");
395 /* store endpoint descriptors for each interface */
396 nendpt_cache[ifaceno] = nendpt;
397 sce_cache = malloc(sizeof(struct ugen_endpoint *) * nendpt, M_TEMP,
399 sce_cache_arr[ifaceno] = sce_cache;
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];
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);
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);
422 #if defined(__FreeBSD__)
423 ugen_destroy_devnodes(sc);
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];
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);
443 /* no endpoints if the device is in the unconfigured state */
444 if (configno != USB_UNCONFIG_NO)
446 /* set the new configuration's ugen_endpoints */
447 err = usbd_interface_count(dev, &niface);
449 panic("ugen_set_config: interface count failed");
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);
456 panic("ugen_set_config: can't obtain interface handle");
457 err = usbd_endpoint_count(iface, &nendpt);
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"
467 endptno, endpt, UE_GET_ADDR(endpt),
468 UE_GET_DIR(endpt), sce));
476 return (USBD_NORMAL_COMPLETION);
480 ugenopen(struct cdev *dev, int flag, int mode, usb_proc_ptr p)
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;
489 usbd_xfer_handle xfer;
493 USB_GET_SC_OPEN(ugen, unit, sc);
495 DPRINTFN(5, ("ugenopen: flag=%d, mode=%d, unit=%d endpt=%d\n",
496 flag, mode, unit, endpt));
498 if (sc == NULL || sc->sc_dying)
501 if (sc->sc_is_open[endpt])
504 if (endpt == USB_CONTROL_ENDPOINT) {
505 sc->sc_is_open[USB_CONTROL_ENDPOINT] = 1;
506 UGEN_DEV_OPEN(dev, sc);
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];
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)))
524 sce = &sc->sc_endpoints[endpt][dir];
526 sce->timeout = USBD_NO_TIMEOUT;
527 DPRINTFN(5, ("ugenopen: sc=%p, endpt=%d, dir=%d, sce=%p\n",
528 sc, endpt, dir, sce));
530 switch (edesc->bmAttributes & UE_XFERTYPE) {
533 err = usbd_open_pipe(sce->iface,
534 edesc->bEndpointAddress, 0, &sce->pipeh);
539 isize = UGETW(edesc->wMaxPacketSize);
540 if (isize == 0) /* shouldn't happen */
542 sce->ibuf = malloc(isize, M_USBDEV, M_WAITOK);
543 DPRINTFN(5, ("ugenopen: intr endpt=%d,isize=%d\n",
545 if (clalloc(&sce->q, UGEN_IBSIZE, 0) == -1)
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);
553 free(sce->ibuf, M_USBDEV);
557 DPRINTFN(5, ("ugenopen: interrupt open done\n"));
560 err = usbd_open_pipe(sce->iface,
561 edesc->bEndpointAddress, 0, &sce->pipeh);
568 isize = UGETW(edesc->wMaxPacketSize);
569 if (isize == 0) /* shouldn't happen */
571 sce->ibuf = malloc(isize * UGEN_NISOFRAMES,
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",
577 err = usbd_open_pipe(sce->iface,
578 edesc->bEndpointAddress, 0, &sce->pipeh);
580 free(sce->ibuf, M_USBDEV);
583 for(i = 0; i < UGEN_NISOREQS; ++i) {
584 sce->isoreqs[i].sce = sce;
585 xfer = usbd_alloc_xfer(sc->sc_udev);
588 sce->isoreqs[i].xfer = xfer;
589 buf = usbd_alloc_buffer
590 (xfer, isize * UGEN_NISORFRMS);
595 sce->isoreqs[i].dmabuf = buf;
596 for(j = 0; j < UGEN_NISORFRMS; ++j)
597 sce->isoreqs[i].sizes[j] = isize;
599 (xfer, sce->pipeh, &sce->isoreqs[i],
600 sce->isoreqs[i].sizes,
601 UGEN_NISORFRMS, USBD_NO_COPY,
603 (void)usbd_transfer(xfer);
605 DPRINTFN(5, ("ugenopen: isoc open done\n"));
608 while (--i >= 0) /* implicit buffer free */
609 usbd_free_xfer(sce->isoreqs[i].xfer);
612 sce->timeout = USBD_DEFAULT_TIMEOUT;
616 sc->sc_is_open[endpt] = 1;
617 UGEN_DEV_OPEN(dev, sc);
622 ugenclose(struct cdev *dev, int flag, int mode, usb_proc_ptr p)
624 int endpt = UGENENDPOINT(dev);
625 struct ugen_softc *sc;
626 struct ugen_endpoint *sce;
630 USB_GET_SC(ugen, UGENUNIT(dev), sc);
632 DPRINTFN(5, ("ugenclose: flag=%d, mode=%d, unit=%d, endpt=%d\n",
633 flag, mode, UGENUNIT(dev), endpt));
636 if (!sc->sc_is_open[endpt]) {
637 printf("ugenclose: not open\n");
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);
649 for (dir = OUT; dir <= IN; dir++) {
650 if (!(flag & (dir == OUT ? FWRITE : FREAD)))
652 sce = &sc->sc_endpoints[endpt][dir];
653 if (sce->pipeh == NULL)
655 DPRINTFN(5, ("ugenclose: endpt=%d dir=%d sce=%p\n",
658 usbd_abort_pipe(sce->pipeh);
659 usbd_close_pipe(sce->pipeh);
662 switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
664 ndflush(&sce->q, sce->q.c_cc);
668 for (i = 0; i < UGEN_NISOREQS; ++i)
669 usbd_free_xfer(sce->isoreqs[i].xfer);
675 if (sce->ibuf != NULL) {
676 free(sce->ibuf, M_USBDEV);
681 sc->sc_is_open[endpt] = 0;
682 UGEN_DEV_CLOSE(dev, sc);
688 ugen_do_read(struct ugen_softc *sc, int endpt, struct uio *uio, int flag)
690 struct ugen_endpoint *sce = &sc->sc_endpoints[endpt][IN];
692 char buf[UGEN_BBSIZE];
693 usbd_xfer_handle xfer;
697 u_char buffer[UGEN_CHUNK];
699 DPRINTFN(5, ("%s: ugenread: %d\n", USBDEVNAME(sc->sc_dev), endpt));
704 if (endpt == USB_CONTROL_ENDPOINT)
708 if (sce->edesc == NULL) {
709 printf("ugenread: no edesc\n");
712 if (sce->pipeh == NULL) {
713 printf("ugenread: no pipe\n");
718 switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
720 /* Block until activity occurred. */
722 while (sce->q.c_cc == 0) {
723 if (flag & O_NONBLOCK) {
725 return (EWOULDBLOCK);
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));
734 sce->state &= ~UGEN_ASLP;
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))
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));
750 /* Copy the data to the user process. */
751 error = uiomove(buffer, n, uio);
757 xfer = usbd_alloc_xfer(sc->sc_udev);
760 while ((n = min(UGEN_BBSIZE, uio->uio_resid)) != 0) {
761 DPRINTFN(1, ("ugenread: start transfer %d bytes\n",n));
763 err = usbd_bulk_transfer(
765 sce->state & UGEN_SHORT_OK ?
766 USBD_SHORT_XFER_OK : 0,
767 sce->timeout, buf, &tn, "ugenrb");
769 if (err == USBD_INTERRUPTED)
771 else if (err == USBD_TIMEOUT)
777 DPRINTFN(1, ("ugenread: got %d bytes\n", tn));
778 error = uiomove(buf, tn, uio);
782 usbd_free_xfer(xfer);
786 while (sce->cur == sce->fill) {
787 if (flag & O_NONBLOCK) {
789 return (EWOULDBLOCK);
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));
798 sce->state &= ~UGEN_ASLP;
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);
807 n = min(sce->limit - sce->cur, uio->uio_resid);
809 DPRINTFN(5, ("ugenread: isoc got %d chars\n", n));
811 /* Copy the data to the user process. */
812 error = uiomove(sce->cur, n, uio);
816 if(sce->cur >= sce->limit)
817 sce->cur = sce->ibuf;
830 ugenread(struct cdev *dev, struct uio *uio, int flag)
832 int endpt = UGENENDPOINT(dev);
833 struct ugen_softc *sc;
836 USB_GET_SC(ugen, UGENUNIT(dev), sc);
838 UGEN_DEV_REF(dev, sc);
839 error = ugen_do_read(sc, endpt, uio, flag);
840 UGEN_DEV_RELE(dev, sc);
845 ugen_do_write(struct ugen_softc *sc, int endpt, struct uio *uio, int flag)
847 struct ugen_endpoint *sce = &sc->sc_endpoints[endpt][OUT];
850 char buf[UGEN_BBSIZE];
851 usbd_xfer_handle xfer;
854 DPRINTFN(5, ("%s: ugenwrite: %d\n", USBDEVNAME(sc->sc_dev), endpt));
859 if (endpt == USB_CONTROL_ENDPOINT)
863 if (sce->edesc == NULL) {
864 printf("ugenwrite: no edesc\n");
867 if (sce->pipeh == NULL) {
868 printf("ugenwrite: no pipe\n");
873 switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
875 xfer = usbd_alloc_xfer(sc->sc_udev);
878 while ((n = min(UGEN_BBSIZE, uio->uio_resid)) != 0) {
879 error = uiomove(buf, n, uio);
882 DPRINTFN(1, ("ugenwrite: transfer %d bytes\n", n));
883 err = usbd_bulk_transfer(xfer, sce->pipeh, 0,
884 sce->timeout, buf, &n,"ugenwb");
886 if (err == USBD_INTERRUPTED)
888 else if (err == USBD_TIMEOUT)
895 usbd_free_xfer(xfer);
898 xfer = usbd_alloc_xfer(sc->sc_udev);
901 while ((n = min(UGETW(sce->edesc->wMaxPacketSize),
902 uio->uio_resid)) != 0) {
903 error = uiomove(buf, n, uio);
906 DPRINTFN(1, ("ugenwrite: transfer %d bytes\n", n));
907 err = usbd_intr_transfer(xfer, sce->pipeh, 0,
908 sce->timeout, buf, &n, "ugenwi");
910 if (err == USBD_INTERRUPTED)
912 else if (err == USBD_TIMEOUT)
919 usbd_free_xfer(xfer);
928 ugenwrite(struct cdev *dev, struct uio *uio, int flag)
930 int endpt = UGENENDPOINT(dev);
931 struct ugen_softc *sc;
934 USB_GET_SC(ugen, UGENUNIT(dev), sc);
936 UGEN_DEV_REF(dev, sc);
937 error = ugen_do_write(sc, endpt, uio, flag);
938 UGEN_DEV_RELE(dev, sc);
942 #if defined(__NetBSD__) || defined(__OpenBSD__)
944 ugen_activate(device_ptr_t self, enum devact act)
946 struct ugen_softc *sc = (struct ugen_softc *)self;
952 case DVACT_DEACTIVATE:
962 ugenpurge(struct cdev *dev)
964 int endpt = UGENENDPOINT(dev);
965 struct ugen_endpoint *sce;
966 struct ugen_softc *sc;
968 if (endpt == USB_CONTROL_ENDPOINT)
970 USB_GET_SC(ugen, UGENUNIT(dev), sc);
971 sce = &sc->sc_endpoints[endpt][IN];
973 usbd_abort_pipe(sce->pipeh);
979 USB_DETACH_START(ugen, sc);
980 struct ugen_endpoint *sce;
982 #if defined(__NetBSD__) || defined(__OpenBSD__)
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));
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];
998 usbd_abort_pipe(sce->pipeh);
1002 #if defined(__NetBSD__) || defined(__OpenBSD__)
1004 if (sc->sc_refcnt > 0) {
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));
1014 /* Wait for opens to go away. */
1017 for (i = 0; i < USB_MAX_ENDPOINTS; i++) {
1018 if (sc->sc_is_open[i])
1022 tsleep(&sc->sc_dying, PZERO, "ugendr", hz);
1025 /* locate the major number */
1026 for (maj = 0; maj < nchrdev; maj++)
1027 if (cdevsw[maj].d_open == ugenopen)
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);
1042 ugenintr(usbd_xfer_handle xfer, usbd_private_handle addr, usbd_status status)
1044 struct ugen_endpoint *sce = addr;
1045 /*struct ugen_softc *sc = sce->sc;*/
1049 if (status == USBD_CANCELLED)
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);
1059 usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
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]));
1067 (void)b_to_q(ibuf, count, &sce->q);
1069 if (sce->state & UGEN_ASLP) {
1070 sce->state &= ~UGEN_ASLP;
1071 DPRINTFN(5, ("ugen_intr: waking %p\n", sce));
1074 selwakeuppri(&sce->rsel, PZERO);
1078 ugen_isoc_rintr(usbd_xfer_handle xfer, usbd_private_handle addr,
1081 struct isoreq *req = addr;
1082 struct ugen_endpoint *sce = req->sce;
1086 /* Return if we are aborting. */
1087 if (status == USBD_CANCELLED)
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),
1095 /* throw away oldest input if the buffer is full */
1096 if(sce->fill < sce->cur && sce->cur <= sce->fill + 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",
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;
1109 /* copy data to buffer */
1110 while (actlen > 0) {
1111 n = min(actlen, sce->limit - sce->fill);
1112 memcpy(sce->fill, buf, n);
1117 if(sce->fill == sce->limit)
1118 sce->fill = sce->ibuf;
1121 /* setup size for next transfer */
1122 req->sizes[i] = isize;
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);
1129 if (sce->state & UGEN_ASLP) {
1130 sce->state &= ~UGEN_ASLP;
1131 DPRINTFN(5, ("ugen_isoc_rintr: waking %p\n", sce));
1134 selwakeuppri(&sce->rsel, PZERO);
1138 ugen_set_interface(struct ugen_softc *sc, int ifaceidx, int altno)
1140 usbd_interface_handle iface;
1141 usb_endpoint_descriptor_t *ed;
1143 struct ugen_endpoint *sce, **sce_cache;
1144 u_int8_t niface, nendpt, nendpt_cache, endptno, endpt;
1147 DPRINTFN(15, ("ugen_set_interface %d %d\n", ifaceidx, altno));
1149 err = usbd_interface_count(sc->sc_udev, &niface);
1152 if (ifaceidx < 0 || ifaceidx >= niface)
1153 return (USBD_INVAL);
1155 err = usbd_device2interface_handle(sc->sc_udev, ifaceidx, &iface);
1158 err = usbd_endpoint_count(iface, &nendpt);
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,
1166 nendpt_cache = nendpt;
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];
1175 /* change setting */
1176 err = usbd_set_interface(iface, altno);
1178 free(sce_cache, M_TEMP);
1181 err = usbd_endpoint_count(iface, &nendpt);
1183 panic("ugen_set_interface: endpoint count failed");
1185 #if defined(__FreeBSD__)
1186 /* destroy the existing devices, we remake the new ones in a moment */
1187 ugen_destroy_devnodes(sc);
1190 /* now we can clear the old interface's ugen_endpoints */
1191 for (endptno = 0; endptno < nendpt_cache; endptno++) {
1192 sce = sce_cache[endptno];
1197 free(sce_cache, M_TEMP);
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];
1210 #if defined(__FreeBSD__)
1211 /* make the new devices */
1212 ugen_make_devnodes(sc);
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)
1222 usb_config_descriptor_t *cdesc, *tdesc, cdescr;
1226 if (index == USB_CURRENT_CONFIG_INDEX) {
1227 tdesc = usbd_get_config_descriptor(sc->sc_udev);
1228 len = UGETW(tdesc->wTotalLength);
1231 cdesc = malloc(len, M_TEMP, M_WAITOK);
1232 memcpy(cdesc, tdesc, len);
1233 DPRINTFN(5,("ugen_get_cdesc: current, len=%d\n", len));
1235 err = usbd_get_config_desc(sc->sc_udev, index, &cdescr);
1238 len = UGETW(cdescr.wTotalLength);
1239 DPRINTFN(5,("ugen_get_cdesc: index=%d, len=%d\n", index, len));
1242 cdesc = malloc(len, M_TEMP, M_WAITOK);
1243 err = usbd_get_config_desc_full(sc->sc_udev, index, cdesc, len);
1245 free(cdesc, M_TEMP);
1253 ugen_get_alt_index(struct ugen_softc *sc, int ifaceidx)
1255 usbd_interface_handle iface;
1258 err = usbd_device2interface_handle(sc->sc_udev, ifaceidx, &iface);
1261 return (usbd_get_interface_altindex(iface));
1265 ugen_do_ioctl(struct ugen_softc *sc, int endpt, u_long cmd,
1266 caddr_t addr, int flag, usb_proc_ptr p)
1268 struct ugen_endpoint *sce;
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;
1281 DPRINTFN(5, ("ugenioctl: cmd=%08lx\n", cmd));
1288 /* All handled in the upper FS layer. */
1290 case USB_SET_SHORT_XFER:
1291 if (endpt == USB_CONTROL_ENDPOINT)
1293 /* This flag only affects read */
1294 sce = &sc->sc_endpoints[endpt][IN];
1296 if (sce->pipeh == NULL) {
1297 printf("ugenioctl: USB_SET_SHORT_XFER, no pipe\n");
1302 sce->state |= UGEN_SHORT_OK;
1304 sce->state &= ~UGEN_SHORT_OK;
1306 case USB_SET_TIMEOUT:
1307 sce = &sc->sc_endpoints[endpt][IN];
1308 sce->timeout = *(int *)addr;
1314 if (endpt != USB_CONTROL_ENDPOINT)
1320 ugendebug = *(int *)addr;
1323 case USB_GET_CONFIG:
1324 err = usbd_get_config(sc->sc_udev, &conf);
1327 *(int *)addr = conf;
1329 case USB_SET_CONFIG:
1330 if (!(flag & FWRITE))
1332 err = ugen_set_config(sc, *(int *)addr);
1334 case USBD_NORMAL_COMPLETION:
1335 #if defined(__FreeBSD__)
1336 ugen_make_devnodes(sc);
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);
1351 idesc = usbd_get_interface_descriptor(iface);
1354 ai->uai_alt_no = idesc->bAlternateSetting;
1356 case USB_SET_ALTINTERFACE:
1357 if (!(flag & FWRITE))
1359 ai = (struct usb_alt_interface *)addr;
1360 err = usbd_device2interface_handle(sc->sc_udev,
1361 ai->uai_interface_index, &iface);
1364 err = ugen_set_interface(sc, ai->uai_interface_index,
1369 case USB_GET_NO_ALT:
1370 ai = (struct usb_alt_interface *)addr;
1371 cdesc = ugen_get_cdesc(sc, ai->uai_config_index, 0);
1374 idesc = usbd_find_idesc(cdesc, ai->uai_interface_index, 0);
1375 if (idesc == NULL) {
1376 free(cdesc, M_TEMP);
1379 ai->uai_alt_no = usbd_get_no_alts(cdesc,
1380 idesc->bInterfaceNumber);
1381 free(cdesc, M_TEMP);
1383 case USB_GET_DEVICE_DESC:
1384 *(usb_device_descriptor_t *)addr =
1385 *usbd_get_device_descriptor(sc->sc_udev);
1387 case USB_GET_CONFIG_DESC:
1388 cd = (struct usb_config_desc *)addr;
1389 cdesc = ugen_get_cdesc(sc, cd->ucd_config_index, 0);
1392 cd->ucd_desc = *cdesc;
1393 free(cdesc, M_TEMP);
1395 case USB_GET_INTERFACE_DESC:
1396 id = (struct usb_interface_desc *)addr;
1397 cdesc = ugen_get_cdesc(sc, id->uid_config_index, 0);
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);
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);
1410 id->uid_desc = *idesc;
1411 free(cdesc, M_TEMP);
1413 case USB_GET_ENDPOINT_DESC:
1414 ed = (struct usb_endpoint_desc *)addr;
1415 cdesc = ugen_get_cdesc(sc, ed->ued_config_index, 0);
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);
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);
1429 ed->ued_desc = *edesc;
1430 free(cdesc, M_TEMP);
1432 case USB_GET_FULL_DESC:
1437 struct usb_full_desc *fd = (struct usb_full_desc *)addr;
1440 cdesc = ugen_get_cdesc(sc, fd->ufd_config_index, &len);
1441 if (len > fd->ufd_size)
1443 iov.iov_base = (caddr_t)fd->ufd_data;
1447 uio.uio_resid = len;
1449 uio.uio_segflg = UIO_USERSPACE;
1450 uio.uio_rw = UIO_READ;
1452 error = uiomove((void *)cdesc, len, &uio);
1453 free(cdesc, M_TEMP);
1456 case USB_GET_STRING_DESC: {
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);
1465 case USB_DO_REQUEST:
1467 struct usb_ctl_request *ur = (void *)addr;
1468 int len = UGETW(ur->ucr_request.wLength);
1475 if (!(flag & FWRITE))
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))
1486 if (len < 0 || len > 32767)
1489 iov.iov_base = (caddr_t)ur->ucr_data;
1493 uio.uio_resid = len;
1495 uio.uio_segflg = UIO_USERSPACE;
1497 ur->ucr_request.bmRequestType & UT_READ ?
1498 UIO_READ : UIO_WRITE;
1500 ptr = malloc(len, M_TEMP, M_WAITOK);
1501 if (uio.uio_rw == UIO_WRITE) {
1502 error = uiomove(ptr, len, &uio);
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);
1515 if (uio.uio_rw == UIO_READ) {
1516 error = uiomove(ptr, len, &uio);
1526 case USB_GET_DEVICEINFO:
1527 usbd_fill_deviceinfo(sc->sc_udev,
1528 (struct usb_device_info *)addr, 1);
1537 ugenioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, usb_proc_ptr p)
1539 int endpt = UGENENDPOINT(dev);
1540 struct ugen_softc *sc;
1543 USB_GET_SC(ugen, UGENUNIT(dev), sc);
1545 UGEN_DEV_REF(dev, sc);
1546 error = ugen_do_ioctl(sc, endpt, cmd, addr, flag, p);
1547 UGEN_DEV_RELE(dev, sc);
1552 ugenpoll(struct cdev *dev, int events, usb_proc_ptr p)
1554 struct ugen_softc *sc;
1555 struct ugen_endpoint *sce;
1559 USB_GET_SC(ugen, UGENUNIT(dev), sc);
1565 sce = &sc->sc_endpoints[UGENENDPOINT(dev)][IN];
1568 printf("ugenpoll: no edesc\n");
1572 printf("ugenpoll: no pipe\n");
1577 switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
1579 if (events & (POLLIN | POLLRDNORM)) {
1580 if (sce->q.c_cc > 0)
1581 revents |= events & (POLLIN | POLLRDNORM);
1583 selrecord(p, &sce->rsel);
1586 case UE_ISOCHRONOUS:
1587 if (events & (POLLIN | POLLRDNORM)) {
1588 if (sce->cur != sce->fill)
1589 revents |= events & (POLLIN | POLLRDNORM);
1591 selrecord(p, &sce->rsel);
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.
1601 (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM);
1610 #if defined(__FreeBSD__)
1611 DRIVER_MODULE(ugen, uhub, ugen_driver, ugen_devclass, usbd_driver_load, 0);