Hi,

I have a patch that adds outgoing interrupt pipes to the usb stack. I
needed it to make a Lego infrared tower work with FreeBSD. Outgoing
interrupt pipes are part of the USB 1.1 spec, but I think our usb
code comes from before that, so it only have incoming interrupt pipes.

Is there anybody that would like to review this or shall I just go
ahead and commit it? One thing to note is that the patch only fix
it for uhci controllers. I haven't been able to get my hands on an
ohci controller.

John
-- 
John Hay -- [EMAIL PROTECTED] / [EMAIL PROTECTED]


Index: share/man/man4/ugen.4
===================================================================
RCS file: /home/ncvs/src/share/man/man4/ugen.4,v
retrieving revision 1.2
diff -u -r1.2 ugen.4
--- share/man/man4/ugen.4       22 Nov 2001 11:56:54 -0000      1.2
+++ share/man/man4/ugen.4       14 Feb 2003 10:20:01 -0000
@@ -104,9 +104,12 @@
 should be used.
 All I/O operations on a bulk endpoint are unbuffered.
 .Pp
-The interrupt transfer mode can only be in.
-To perform input from an interrupt endpoint
+The interrupt transfer mode can be in or out depending on the
+endpoint.
+To perform I/O on an interrupt endpoint
 .Xr read 2
+and
+.Xr write 2
 should be used.
 A moderate amount of buffering is done
 by the driver.
Index: sys/dev/usb/ugen.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/usb/ugen.c,v
retrieving revision 1.66
diff -u -r1.66 ugen.c
--- sys/dev/usb/ugen.c  21 Jan 2003 08:55:44 -0000      1.66
+++ sys/dev/usb/ugen.c  12 Feb 2003 16:05:24 -0000
@@ -419,6 +419,13 @@
                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);
@@ -764,6 +771,30 @@
                        DPRINTFN(1, ("ugenwrite: transfer %d bytes\n", n));
                        err = usbd_bulk_transfer(xfer, sce->pipeh, 0, 
                                  sce->timeout, buf, &n,"ugenwb");
+                       if (err) {
+                               if (err == USBD_INTERRUPTED)
+                                       error = EINTR;
+                               else if (err == USBD_TIMEOUT)
+                                       error = ETIMEDOUT;
+                               else
+                                       error = EIO;
+                               break;
+                       }
+               }
+               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;
Index: sys/dev/usb/uhci.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/usb/uhci.c,v
retrieving revision 1.130
diff -u -r1.130 uhci.c
--- sys/dev/usb/uhci.c  21 Jan 2003 08:55:44 -0000      1.130
+++ sys/dev/usb/uhci.c  12 Feb 2003 16:27:48 -0000
@@ -149,6 +149,7 @@
                /* Interrupt pipe */
                struct {
                        int npoll;
+                       int isread;
                        uhci_soft_qh_t **qhs;
                } intr;
                /* Bulk pipe */
@@ -2032,6 +2033,7 @@
        uhci_soft_td_t *data, *dataend;
        uhci_soft_qh_t *sqh;
        usbd_status err;
+       int isread, endpt;
        int i, s;
 
        if (sc->sc_dying)
@@ -2045,8 +2047,15 @@
                panic("uhci_device_intr_transfer: a request\n");
 #endif
 
-       err = uhci_alloc_std_chain(upipe, sc, xfer->length, 1, xfer->flags,
-                                  &xfer->dmabuf, &data, &dataend);
+       endpt = upipe->pipe.endpoint->edesc->bEndpointAddress;
+       isread = UE_GET_DIR(endpt) == UE_DIR_IN;
+       sqh = upipe->u.bulk.sqh;
+
+       upipe->u.intr.isread = isread;
+
+       err = uhci_alloc_std_chain(upipe, sc, xfer->length, isread,
+                                  xfer->flags, &xfer->dmabuf, &data,
+                                  &dataend);
        if (err)
                return (err);
        dataend->td.td_status |= htole32(UHCI_TD_IOC);
@@ -2637,7 +2646,8 @@
                DPRINTFN(5,("uhci_device_intr_done: requeing\n"));
 
                /* This alloc cannot fail since we freed the chain above. */
-               uhci_alloc_std_chain(upipe, sc, xfer->length, 1, xfer->flags,
+               uhci_alloc_std_chain(upipe, sc, xfer->length,
+                                    upipe->u.intr.isread, xfer->flags,
                                     &xfer->dmabuf, &data, &dataend);
                dataend->td.td_status |= htole32(UHCI_TD_IOC);
 
Index: sys/dev/usb/usbdi_util.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/usb/usbdi_util.c,v
retrieving revision 1.26
diff -u -r1.26 usbdi_util.c
--- sys/dev/usb/usbdi_util.c    22 Aug 2002 21:24:00 -0000      1.26
+++ sys/dev/usb/usbdi_util.c    12 Feb 2003 16:05:24 -0000
@@ -445,6 +445,48 @@
        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((caddr_t)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)
 {
Index: sys/dev/usb/usbdi_util.h
===================================================================
RCS file: /home/ncvs/src/sys/dev/usb/usbdi_util.h,v
retrieving revision 1.14
diff -u -r1.14 usbdi_util.h
--- sys/dev/usb/usbdi_util.h    7 Apr 2002 17:13:00 -0000       1.14
+++ sys/dev/usb/usbdi_util.h    12 Feb 2003 16:05:24 -0000
@@ -80,6 +80,10 @@
                               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);
 

To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-current" in the body of the message

Reply via email to