diff options
author | jhay <jhay@FreeBSD.org> | 2003-02-28 19:28:29 +0000 |
---|---|---|
committer | jhay <jhay@FreeBSD.org> | 2003-02-28 19:28:29 +0000 |
commit | 9cfb22c2099b864d1c2dc45a37f750df81d5d0cd (patch) | |
tree | 56b7bb65e35cb711738a66b2bf64158dd7874a4c /sys/dev/usb/ugen.c | |
parent | f7135842db85e9aa10d78271936053555f274767 (diff) | |
download | FreeBSD-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.c | 31 |
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); } |