summaryrefslogtreecommitdiffstats
path: root/sys/dev/usb/ugen.c
diff options
context:
space:
mode:
authorjhay <jhay@FreeBSD.org>2003-02-28 19:28:29 +0000
committerjhay <jhay@FreeBSD.org>2003-02-28 19:28:29 +0000
commit9cfb22c2099b864d1c2dc45a37f750df81d5d0cd (patch)
tree56b7bb65e35cb711738a66b2bf64158dd7874a4c /sys/dev/usb/ugen.c
parentf7135842db85e9aa10d78271936053555f274767 (diff)
downloadFreeBSD-src-9cfb22c2099b864d1c2dc45a37f750df81d5d0cd.zip
FreeBSD-src-9cfb22c2099b864d1c2dc45a37f750df81d5d0cd.tar.gz
Implement outgoing interrupt pipes. It is part of the USB 1.1 spec.
The Lego Infrared Tower use it.
Diffstat (limited to 'sys/dev/usb/ugen.c')
-rw-r--r--sys/dev/usb/ugen.c31
1 files changed, 31 insertions, 0 deletions
diff --git a/sys/dev/usb/ugen.c b/sys/dev/usb/ugen.c
index fb2b46a..5f997dc 100644
--- a/sys/dev/usb/ugen.c
+++ b/sys/dev/usb/ugen.c
@@ -419,6 +419,13 @@ ugenopen(dev_t dev, int flag, int mode, usb_proc_ptr p)
edesc = sce->edesc;
switch (edesc->bmAttributes & UE_XFERTYPE) {
case UE_INTERRUPT:
+ if (dir == OUT) {
+ err = usbd_open_pipe(sce->iface,
+ edesc->bEndpointAddress, 0, &sce->pipeh);
+ if (err)
+ return (EIO);
+ break;
+ }
isize = UGETW(edesc->wMaxPacketSize);
if (isize == 0) /* shouldn't happen */
return (EINVAL);
@@ -776,6 +783,30 @@ ugen_do_write(struct ugen_softc *sc, int endpt, struct uio *uio, int flag)
}
usbd_free_xfer(xfer);
break;
+ case UE_INTERRUPT:
+ xfer = usbd_alloc_xfer(sc->sc_udev);
+ if (xfer == 0)
+ return (EIO);
+ while ((n = min(UGETW(sce->edesc->wMaxPacketSize),
+ uio->uio_resid)) != 0) {
+ error = uiomove(buf, n, uio);
+ if (error)
+ break;
+ DPRINTFN(1, ("ugenwrite: transfer %d bytes\n", n));
+ err = usbd_intr_transfer(xfer, sce->pipeh, 0,
+ sce->timeout, buf, &n,"ugenwi");
+ if (err) {
+ if (err == USBD_INTERRUPTED)
+ error = EINTR;
+ else if (err == USBD_TIMEOUT)
+ error = ETIMEDOUT;
+ else
+ error = EIO;
+ break;
+ }
+ }
+ usbd_free_xfer(xfer);
+ break;
default:
return (ENXIO);
}
OpenPOWER on IntegriCloud