summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2004-07-21 00:01:09 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2004-07-21 00:01:09 +0000
commit1939583a95bbe7a8022a6bee1010821fde2ff1bb (patch)
tree7f8ebb392c8e96c623d578a3cd85077af6d5be37 /sys/dev
parenteb833e87668c2e29e560a558673f37ed802ef6d9 (diff)
from freebsd, ugen.c 1.68 usbdi_util.c 1.27 usbdi_util.h 1.15
log message: Implement outgoing interrupt pipes. It is part of the USB 1.1 spec. The Lego Infrared Tower use it. ok deraadt@
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/usb/ugen.c33
-rw-r--r--sys/dev/usb/usbdi_util.c44
-rw-r--r--sys/dev/usb/usbdi_util.h6
3 files changed, 80 insertions, 3 deletions
diff --git a/sys/dev/usb/ugen.c b/sys/dev/usb/ugen.c
index feee3004c41..b7f955fd601 100644
--- a/sys/dev/usb/ugen.c
+++ b/sys/dev/usb/ugen.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ugen.c,v 1.29 2004/07/08 22:18:44 deraadt Exp $ */
+/* $OpenBSD: ugen.c,v 1.30 2004/07/21 00:01:07 dlg Exp $ */
/* $NetBSD: ugen.c,v 1.63 2002/11/26 18:49:48 christos Exp $ */
/* $FreeBSD: src/sys/dev/usb/ugen.c,v 1.26 1999/11/17 22:33:41 n_hibma Exp $ */
@@ -359,6 +359,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);
@@ -715,6 +722,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);
}
diff --git a/sys/dev/usb/usbdi_util.c b/sys/dev/usb/usbdi_util.c
index 69fd35b6308..58fe86f4f9c 100644
--- a/sys/dev/usb/usbdi_util.c
+++ b/sys/dev/usb/usbdi_util.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: usbdi_util.c,v 1.16 2004/07/08 22:18:45 deraadt Exp $ */
+/* $OpenBSD: usbdi_util.c,v 1.17 2004/07/21 00:01:08 dlg Exp $ */
/* $NetBSD: usbdi_util.c,v 1.40 2002/07/11 21:14:36 augustss Exp $ */
/* $FreeBSD: src/sys/dev/usb/usbdi_util.c,v 1.14 1999/11/17 22:33:50 n_hibma Exp $ */
@@ -465,6 +465,48 @@ usbd_bulk_transfer(usbd_xfer_handle xfer, usbd_pipe_handle pipe,
return (err);
}
+Static void usbd_intr_transfer_cb(usbd_xfer_handle xfer,
+ usbd_private_handle priv, usbd_status status);
+Static void
+usbd_intr_transfer_cb(usbd_xfer_handle xfer, usbd_private_handle priv,
+ usbd_status status)
+{
+ wakeup(xfer);
+}
+
+usbd_status
+usbd_intr_transfer(usbd_xfer_handle xfer, usbd_pipe_handle pipe,
+ u_int16_t flags, u_int32_t timeout, void *buf,
+ u_int32_t *size, char *lbl)
+{
+ usbd_status err;
+ int s, error;
+
+ usbd_setup_xfer(xfer, pipe, 0, buf, *size,
+ flags, timeout, usbd_intr_transfer_cb);
+ DPRINTFN(1, ("usbd_intr_transfer: start transfer %d bytes\n", *size));
+ s = splusb(); /* don't want callback until tsleep() */
+ err = usbd_transfer(xfer);
+ if (err != USBD_IN_PROGRESS) {
+ splx(s);
+ return (err);
+ }
+ error = tsleep(xfer, PZERO | PCATCH, lbl, 0);
+ splx(s);
+ if (error) {
+ DPRINTF(("usbd_intr_transfer: tsleep=%d\n", error));
+ usbd_abort_pipe(pipe);
+ return (USBD_INTERRUPTED);
+ }
+ usbd_get_xfer_status(xfer, NULL, NULL, size, &err);
+ DPRINTFN(1,("usbd_intr_transfer: transferred %d\n", *size));
+ if (err) {
+ DPRINTF(("usbd_intr_transfer: error=%d\n", err));
+ usbd_clear_endpoint_stall(pipe);
+ }
+ return (err);
+}
+
void
usb_detach_wait(device_ptr_t dv)
{
diff --git a/sys/dev/usb/usbdi_util.h b/sys/dev/usb/usbdi_util.h
index 1d435df6ee5..71d40301b67 100644
--- a/sys/dev/usb/usbdi_util.h
+++ b/sys/dev/usb/usbdi_util.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: usbdi_util.h,v 1.12 2003/07/08 13:19:09 nate Exp $ */
+/* $OpenBSD: usbdi_util.h,v 1.13 2004/07/21 00:01:08 dlg Exp $ */
/* $NetBSD: usbdi_util.h,v 1.28 2002/07/11 21:14:36 augustss Exp $ */
/* $FreeBSD: src/sys/dev/usb/usbdi_util.h,v 1.9 1999/11/17 22:33:50 n_hibma Exp $ */
@@ -82,6 +82,10 @@ usbd_status usbd_bulk_transfer(usbd_xfer_handle xfer, usbd_pipe_handle pipe,
u_int16_t flags, u_int32_t timeout, void *buf,
u_int32_t *size, char *lbl);
+usbd_status usbd_intr_transfer(usbd_xfer_handle xfer, usbd_pipe_handle pipe,
+ u_int16_t flags, u_int32_t timeout, void *buf,
+ u_int32_t *size, char *lbl);
+
void usb_detach_wait(device_ptr_t);
void usb_detach_wakeup(device_ptr_t);