On 17/05/13(Fri) 20:19, Martin Pieuchot wrote:
> On 14/05/13(Tue) 16:09, Marcus Glocker wrote:
> > On Fri, May 10, 2013 at 09:44:53AM +0200, Martin Pieuchot wrote:
> > > [...] 
> > > 
> > > This diff gets rid of the two badly named functions: usbd_bulk_transfer()
> > > & usbd_intr_transfer() and makes use of the usbd_setup_xfer(9) + 
> > > usbd_transfer(9) combination.  These functions were badly named because
> > > they are identical wrappers to submit a synchronous transfer.  There are
> > > however two small functional differences with this diff:
> > > 
> > >  - previously a custom name for the wait channel was given to tlseep(9)
> > >    while sleeping for I/O. Now it will be "usbsyn" for all USB
> > >    synchronous transfers.
> > > 
> > >  - previously the priority given to tlseep(9) was PZERO. Now it will be
> > >    PRIBIO like for all USB synchronous transfers. But this shouldn't make
> > >    a difference in practice, because the only priority between the two,
> > >    PVFS, is unused. 
> > > 
> > > This diff also includes a new manual for the above mentioned functions.
> > > I'd like to document as much functions of our USB stack as possible to
> > > make sure driver porter/writer understand how it works.
> 
> Updated diff with two minors tweaks to make sure that:
> 
>   - no information is leaked to userland when USBD_SHORT_XFER_OK is set
>     for ugen(4) reads 
> 
>   - do not bother checking for the actual transfered length for reads
>     in urio(4), USBD_SHORT_XFER_OK being not set, an error is returned
>     if actlen < len.
> 
> Plus includes some tweaks for the manpage by jmc@

Here's a new version of the diff that includes:

  - Remove the usbscanner(4) part since ajacoutot@ sent it to the Attic

  - Call usbd_clear_endpoint_stall() when an error occurred during the
    transfer to match the previous behavior.

  - Abort the pipe in case tsleep() returned an error and the transfer
    is still not done, from NetBSD via miod@

  - Remove the handling of USBD_INTERRUPTED from urio which looks like
    a bad copy/paste of ugen, because its doesn't tsleep() with PCATCH.

  - Update the status of the transfer to match the error code tsleep()
    returned.

Last version has been tested by various people, I don't expect any
regression, but don't hesitate to give it a shot and report back.

ok?


Index: sys/dev/usb/ugen.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/usb/ugen.c,v
retrieving revision 1.72
diff -u -p -r1.72 ugen.c
--- sys/dev/usb/ugen.c  17 May 2013 09:09:11 -0000      1.72
+++ sys/dev/usb/ugen.c  5 Sep 2013 10:23:37 -0000
@@ -478,7 +478,7 @@ ugen_do_read(struct ugen_softc *sc, int 
        struct usbd_xfer *xfer;
        usbd_status err;
        int s;
-       int error = 0;
+       int flags, error = 0;
        u_char buffer[UGEN_CHUNK];
 
        DPRINTFN(5, ("%s: ugenread: %d\n", sc->sc_dev.dv_xname, endpt));
@@ -546,15 +546,18 @@ ugen_do_read(struct ugen_softc *sc, int 
                xfer = usbd_alloc_xfer(sc->sc_udev);
                if (xfer == 0)
                        return (ENOMEM);
+               flags = USBD_SYNCHRONOUS;
+               if (sce->state & UGEN_SHORT_OK)
+                       flags |= USBD_SHORT_XFER_OK;
+               if (sce->timeout == 0)
+                       flags |= USBD_CATCH;
                while ((n = min(UGEN_BBSIZE, uio->uio_resid)) != 0) {
                        DPRINTFN(1, ("ugenread: start transfer %d bytes\n",n));
-                       tn = n;
-                       err = usbd_bulk_transfer(
-                                 xfer, sce->pipeh,
-                                 sce->state & UGEN_SHORT_OK ?
-                                     USBD_SHORT_XFER_OK : 0,
-                                 sce->timeout, buf, &tn, "ugenrb");
+                       usbd_setup_xfer(xfer, sce->pipeh, 0, buf, n,
+                           flags, sce->timeout, NULL);
+                       err = usbd_transfer(xfer);
                        if (err) {
+                               usbd_clear_endpoint_stall(sce->pipeh);
                                if (err == USBD_INTERRUPTED)
                                        error = EINTR;
                                else if (err == USBD_TIMEOUT)
@@ -563,6 +566,7 @@ ugen_do_read(struct ugen_softc *sc, int 
                                        error = EIO;
                                break;
                        }
+                       usbd_get_xfer_status(xfer, NULL, NULL, &tn, NULL);
                        DPRINTFN(1, ("ugenread: got %d bytes\n", tn));
                        error = uiomove(buf, tn, uio);
                        if (error || tn < n)
@@ -640,7 +644,7 @@ ugen_do_write(struct ugen_softc *sc, int
 {
        struct ugen_endpoint *sce = &sc->sc_endpoints[endpt][OUT];
        u_int32_t n;
-       int error = 0;
+       int flags, error = 0;
        char buf[UGEN_BBSIZE];
        struct usbd_xfer *xfer;
        usbd_status err;
@@ -663,6 +667,9 @@ ugen_do_write(struct ugen_softc *sc, int
                return (EIO);
        }
 #endif
+       flags = USBD_SYNCHRONOUS;
+       if (sce->timeout == 0)
+               flags |= USBD_CATCH;
 
        switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
        case UE_BULK:
@@ -674,9 +681,11 @@ ugen_do_write(struct ugen_softc *sc, int
                        if (error)
                                break;
                        DPRINTFN(1, ("ugenwrite: transfer %d bytes\n", n));
-                       err = usbd_bulk_transfer(xfer, sce->pipeh, 0,
-                                 sce->timeout, buf, &n,"ugenwb");
+                       usbd_setup_xfer(xfer, sce->pipeh, 0, buf, n,
+                           flags, sce->timeout, NULL);
+                       err = usbd_transfer(xfer);
                        if (err) {
+                               usbd_clear_endpoint_stall(sce->pipeh);
                                if (err == USBD_INTERRUPTED)
                                        error = EINTR;
                                else if (err == USBD_TIMEOUT)
@@ -698,9 +707,11 @@ ugen_do_write(struct ugen_softc *sc, int
                        if (error)
                                break;
                        DPRINTFN(1, ("ugenwrite: transfer %d bytes\n", n));
-                       err = usbd_intr_transfer(xfer, sce->pipeh, 0,
-                           sce->timeout, buf, &n, "ugenwi");
+                       usbd_setup_xfer(xfer, sce->pipeh, 0, buf, n,
+                           flags, sce->timeout, NULL);
+                       err = usbd_transfer(xfer);
                        if (err) {
+                               usbd_clear_endpoint_stall(sce->pipeh);
                                if (err == USBD_INTERRUPTED)
                                        error = EINTR;
                                else if (err == USBD_TIMEOUT)
Index: sys/dev/usb/uhidev.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/usb/uhidev.c,v
retrieving revision 1.44
diff -u -p -r1.44 uhidev.c
--- sys/dev/usb/uhidev.c        7 May 2013 08:44:38 -0000       1.44
+++ sys/dev/usb/uhidev.c        5 Sep 2013 10:23:37 -0000
@@ -627,6 +627,7 @@ uhidev_get_report(struct uhidev *scd, in
 usbd_status
 uhidev_write(struct uhidev_softc *sc, void *data, int len)
 {
+       usbd_status error;
 
        DPRINTF(("uhidev_write: data=%p, len=%d\n", data, len));
 
@@ -645,8 +646,13 @@ uhidev_write(struct uhidev_softc *sc, vo
                DPRINTF(("\n"));
        }
 #endif
-       return usbd_intr_transfer(sc->sc_owxfer, sc->sc_opipe, 0,
-           USBD_NO_TIMEOUT, data, &len, "uhidevwi");
+       usbd_setup_xfer(sc->sc_owxfer, sc->sc_opipe, 0, data, len,
+           USBD_SYNCHRONOUS | USBD_CATCH, 0, NULL);
+       error = usbd_transfer(sc->sc_owxfer);
+       if (error)
+               usbd_clear_endpoint_stall(sc->sc_opipe);
+
+       return (error);
 }
 
 int
Index: sys/dev/usb/ulpt.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/usb/ulpt.c,v
retrieving revision 1.43
diff -u -p -r1.43 ulpt.c
--- sys/dev/usb/ulpt.c  15 Apr 2013 09:23:02 -0000      1.43
+++ sys/dev/usb/ulpt.c  5 Sep 2013 10:23:37 -0000
@@ -636,9 +636,11 @@ ulpt_do_write(struct ulpt_softc *sc, str
                if (error)
                        break;
                DPRINTFN(1, ("ulptwrite: transfer %d bytes\n", n));
-               err = usbd_bulk_transfer(xfer, sc->sc_out_pipe, USBD_NO_COPY,
-                         USBD_NO_TIMEOUT, bufp, &n, "ulptwr");
+               usbd_setup_xfer(xfer, sc->sc_out_pipe, 0, bufp, n,
+                   USBD_NO_COPY | USBD_SYNCHRONOUS | USBD_CATCH, 0, NULL);
+               err = usbd_transfer(xfer);
                if (err) {
+                       usbd_clear_endpoint_stall(sc->sc_out_pipe);
                        DPRINTF(("ulptwrite: error=%d\n", err));
                        error = EIO;
                        break;
@@ -704,9 +706,11 @@ ulpt_ucode_loader_hp(struct ulpt_softc *
        while (remain > 0) {
                len = min(remain, ULPT_BSIZE);
                memcpy(bufp, &ucode[offset], len);
-               error = usbd_bulk_transfer(xfer, sc->sc_out_pipe, USBD_NO_COPY,
-                         USBD_NO_TIMEOUT, bufp, &len, "ulptwr");
+               usbd_setup_xfer(xfer, sc->sc_out_pipe, 0, bufp, len,
+                   USBD_NO_COPY | USBD_SYNCHRONOUS, 0, NULL);
+               error = usbd_transfer(xfer);
                if (error != USBD_NORMAL_COMPLETION) {
+                       usbd_clear_endpoint_stall(sc->sc_out_pipe);
                        printf("%s: ucode upload error=%s!\n",
                            sc->sc_dev.dv_xname, usbd_errstr(error));
                        break;
Index: sys/dev/usb/umsm.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/usb/umsm.c,v
retrieving revision 1.91
diff -u -p -r1.91 umsm.c
--- sys/dev/usb/umsm.c  2 Aug 2013 09:00:49 -0000       1.91
+++ sys/dev/usb/umsm.c  5 Sep 2013 10:23:37 -0000
@@ -768,11 +768,14 @@ umsm_umass_changemode(struct umsm_softc 
                else {
                        n = UMASS_BBB_CBW_SIZE;
                        memcpy(bufp, &cbw, UMASS_BBB_CBW_SIZE);
-                       err = usbd_bulk_transfer(xfer, cmdpipe, USBD_NO_COPY,
-                           USBD_NO_TIMEOUT, bufp, &n, "umsm");
-                       if (err)
+                       usbd_setup_xfer(xfer, cmdpipe, 0, bufp, n,
+                           USBD_NO_COPY | USBD_SYNCHRONOUS, 0, NULL);
+                       err = usbd_transfer(xfer);
+                       if (err) {
+                               usbd_clear_endpoint_stall(cmdpipe);
                                DPRINTF(("%s: send error:%s", __func__,
                                    usbd_errstr(err)));
+                       }
                }
                usbd_close_pipe(cmdpipe);
                usbd_free_buffer(xfer);
Index: sys/dev/usb/urio.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/usb/urio.c,v
retrieving revision 1.42
diff -u -p -r1.42 urio.c
--- sys/dev/usb/urio.c  17 May 2013 09:14:08 -0000      1.42
+++ sys/dev/usb/urio.c  5 Sep 2013 10:23:37 -0000
@@ -304,7 +304,7 @@ urioread(dev_t dev, struct uio *uio, int
        struct usbd_xfer *xfer;
        usbd_status err;
        void *bufp;
-       u_int32_t n, tn;
+       u_int32_t n;
        int error = 0;
 
        sc = urio_cd.cd_devs[URIOUNIT(dev)];
@@ -327,23 +327,22 @@ urioread(dev_t dev, struct uio *uio, int
 
        while ((n = min(URIO_BSIZE, uio->uio_resid)) != 0) {
                DPRINTFN(1, ("urioread: start transfer %d bytes\n", n));
-               tn = n;
-               err = usbd_bulk_transfer(xfer, sc->sc_in_pipe, USBD_NO_COPY,
-                         URIO_RW_TIMEOUT, bufp, &tn, "uriors");
+               usbd_setup_xfer(xfer, sc->sc_in_pipe, 0, bufp, n,
+                   USBD_NO_COPY | USBD_SYNCHRONOUS, URIO_RW_TIMEOUT, NULL);
+               err = usbd_transfer(xfer);
                if (err) {
-                       if (err == USBD_INTERRUPTED)
-                               error = EINTR;
-                       else if (err == USBD_TIMEOUT)
+                       usbd_clear_endpoint_stall(sc->sc_in_pipe);
+                       if (err == USBD_TIMEOUT)
                                error = ETIMEDOUT;
                        else
                                error = EIO;
                        break;
                }
 
-               DPRINTFN(1, ("urioread: got %d bytes\n", tn));
+               DPRINTFN(1, ("urioread: got %d bytes\n", n));
 
-               error = uiomove(bufp, tn, uio);
-               if (error || tn < n)
+               error = uiomove(bufp, n, uio);
+               if (error)
                        break;
        }
        usbd_free_xfer(xfer);
@@ -390,13 +389,13 @@ uriowrite(dev_t dev, struct uio *uio, in
 
                DPRINTFN(1, ("uriowrite: transfer %d bytes\n", n));
 
-               err = usbd_bulk_transfer(xfer, sc->sc_out_pipe, USBD_NO_COPY,
-                         URIO_RW_TIMEOUT, bufp, &n, "uriowr");
+               usbd_setup_xfer(xfer, sc->sc_out_pipe, 0, bufp, n,
+                   USBD_NO_COPY | USBD_SYNCHRONOUS, URIO_RW_TIMEOUT, NULL);
+               err = usbd_transfer(xfer);
                DPRINTFN(2, ("uriowrite: err=%d\n", err));
                if (err) {
-                       if (err == USBD_INTERRUPTED)
-                               error = EINTR;
-                       else if (err == USBD_TIMEOUT)
+                       usbd_clear_endpoint_stall(sc->sc_out_pipe);
+                       if (err == USBD_TIMEOUT)
                                error = ETIMEDOUT;
                        else
                                error = EIO;
Index: sys/dev/usb/usbdi.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/usb/usbdi.c,v
retrieving revision 1.57
diff -u -p -r1.57 usbdi.c
--- sys/dev/usb/usbdi.c 13 Aug 2013 09:26:04 -0000      1.57
+++ sys/dev/usb/usbdi.c 5 Sep 2013 10:23:37 -0000
@@ -294,7 +294,7 @@ usbd_transfer(struct usbd_xfer *xfer)
        struct usb_dma *dmap = &xfer->dmabuf;
        usbd_status err;
        u_int size;
-       int s;
+       int flags, s;
 
        if (usbd_is_dying(pipe->device))
                return (USBD_IOERROR);
@@ -352,7 +352,16 @@ usbd_transfer(struct usbd_xfer *xfer)
        while (!xfer->done) {
                if (pipe->device->bus->use_polling)
                        panic("usbd_transfer: not done");
-               tsleep(xfer, PRIBIO, "usbsyn", 0);
+               flags = PRIBIO | (xfer->flags & USBD_CATCH ? PCATCH : 0);
+
+               err = tsleep(xfer, flags, "usbsyn", 0);
+               if (err && !xfer->done) {
+                       usbd_abort_pipe(pipe);
+                       if (err == EINTR)
+                               xfer->status = USBD_INTERRUPTED;
+                       else
+                               xfer->status = USBD_TIMEOUT;
+               }
        }
        splx(s);
        return (xfer->status);
Index: sys/dev/usb/usbdi.h
===================================================================
RCS file: /home/ncvs/src/sys/dev/usb/usbdi.h,v
retrieving revision 1.53
diff -u -p -r1.53 usbdi.h
--- sys/dev/usb/usbdi.h 26 Apr 2013 14:19:25 -0000      1.53
+++ sys/dev/usb/usbdi.h 5 Sep 2013 10:23:37 -0000
@@ -76,6 +76,7 @@ typedef void (*usbd_callback)(struct usb
 #define USBD_SYNCHRONOUS       0x02    /* wait for completion */
 /* in usb.h #define USBD_SHORT_XFER_OK 0x04*/  /* allow short reads */
 #define USBD_FORCE_SHORT_XFER  0x08    /* force last short packet on write */
+#define USBD_CATCH             0x10    /* catch signals while sleeping */
 
 #define USBD_NO_TIMEOUT 0
 #define USBD_DEFAULT_TIMEOUT 5000 /* ms = 5 s */
Index: sys/dev/usb/usbdi_util.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/usb/usbdi_util.c,v
retrieving revision 1.31
diff -u -p -r1.31 usbdi_util.c
--- sys/dev/usb/usbdi_util.c    15 Apr 2013 09:23:02 -0000      1.31
+++ sys/dev/usb/usbdi_util.c    5 Sep 2013 10:23:37 -0000
@@ -396,90 +396,6 @@ usbd_get_config(struct usbd_device *dev,
        return (usbd_do_request(dev, &req, conf));
 }
 
-void usbd_bulk_transfer_cb(struct usbd_xfer *xfer, void *priv,
-    usbd_status status);
-void
-usbd_bulk_transfer_cb(struct usbd_xfer *xfer, void *priv,
-    usbd_status status)
-{
-       wakeup(xfer);
-}
-
-usbd_status
-usbd_bulk_transfer(struct usbd_xfer *xfer, struct usbd_pipe *pipe,
-    u_int16_t flags, u_int32_t timeout, void *buf, u_int32_t *size, char *lbl)
-{
-       usbd_status err;
-       int s, error, pri;
-
-       usbd_setup_xfer(xfer, pipe, 0, buf, *size, flags, timeout,
-           usbd_bulk_transfer_cb);
-       DPRINTFN(1, ("usbd_bulk_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);
-       }
-       pri = timeout == 0 ? (PZERO | PCATCH) : PZERO;
-       error = tsleep((caddr_t)xfer, pri, lbl, 0);
-       splx(s);
-       if (error) {
-               DPRINTF(("usbd_bulk_transfer: tsleep=%d\n", error));
-               usbd_abort_pipe(pipe);
-               return (USBD_INTERRUPTED);
-       }
-       usbd_get_xfer_status(xfer, NULL, NULL, size, &err);
-       DPRINTFN(1,("usbd_bulk_transfer: transferred %d\n", *size));
-       if (err) {
-               DPRINTF(("usbd_bulk_transfer: error=%d\n", err));
-               usbd_clear_endpoint_stall(pipe);
-       }
-       return (err);
-}
-
-void usbd_intr_transfer_cb(struct usbd_xfer *xfer, void *priv,
-    usbd_status status);
-void
-usbd_intr_transfer_cb(struct usbd_xfer *xfer, void *priv,
-    usbd_status status)
-{
-       wakeup(xfer);
-}
-
-usbd_status
-usbd_intr_transfer(struct usbd_xfer *xfer, struct usbd_pipe *pipe,
-    u_int16_t flags, u_int32_t timeout, void *buf, u_int32_t *size, char *lbl)
-{
-       usbd_status err;
-       int s, error, pri;
-
-       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);
-       }
-       pri = timeout == 0 ? (PZERO | PCATCH) : PZERO;
-       error = tsleep(xfer, pri, 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(struct device *dv)
 {
Index: sys/dev/usb/usbdi_util.h
===================================================================
RCS file: /home/ncvs/src/sys/dev/usb/usbdi_util.h,v
retrieving revision 1.21
diff -u -p -r1.21 usbdi_util.h
--- sys/dev/usb/usbdi_util.h    15 Apr 2013 09:23:02 -0000      1.21
+++ sys/dev/usb/usbdi_util.h    5 Sep 2013 10:23:37 -0000
@@ -69,13 +69,5 @@ usbd_status  usbd_set_config_no(struct us
 usbd_status    usbd_set_config_index(struct usbd_device *dev, int index,
                    int msg);
 
-usbd_status    usbd_bulk_transfer(struct usbd_xfer *xfer,
-                   struct usbd_pipe *pipe, u_int16_t flags, u_int32_t timeout,
-                   void *buf, u_int32_t *size, char *lbl);
-
-usbd_status    usbd_intr_transfer(struct usbd_xfer *xfer,
-                   struct usbd_pipe *pipe, u_int16_t flags, u_int32_t timeout,
-                   void *buf, u_int32_t *size, char *lbl);
-
 void usb_detach_wait(struct device *);
 void usb_detach_wakeup(struct device *);
Index: share/man/man9/Makefile
===================================================================
RCS file: /home/ncvs/src/share/man/man9/Makefile,v
retrieving revision 1.183
diff -u -p -r1.183 Makefile
--- share/man/man9/Makefile     8 Aug 2013 06:41:06 -0000       1.183
+++ share/man/man9/Makefile     5 Sep 2013 10:23:37 -0000
@@ -25,7 +25,9 @@ MAN=  altq.9 aml_evalnode.9 atomic.9 audi
        route.9 rwlock.9 sensor_attach.9 \
        shutdownhook_establish.9 tsleep.9 spl.9 startuphook_establish.9 \
        socreate.9 sosplice.9 style.9 syscall.9 systrace.9 sysctl_int.9 \
-       tc_init.9 time.9 timeout.9 tvtohz.9 uiomove.9 uvm.9 vfs.9 vfs_busy.9 \
+       tc_init.9 time.9 timeout.9 tvtohz.9 uiomove.9 uvm.9 \
+       usbd_transfer.9 \
+       vfs.9 vfs_busy.9 \
        vfs_cache.9 vaccess.9 vclean.9 vcount.9 vdevgone.9 vfinddev.9 vflush.9 \
        vflushbuf.9 vget.9 vgone.9 vhold.9 vinvalbuf.9 vnode.9 vnsubr.9 \
        VOP_GETATTR.9 VOP_LOOKUP.9 vput.9 vrecycle.9 vref.9 vrele.9 \
@@ -334,6 +336,7 @@ MLINKS+=timeout.9 timeout_add.9 timeout.
 MLINKS+=tsleep.9 wakeup.9 tsleep.9 msleep.9
 MLINKS+=tvtohz.9 tstohz.9
 MLINKS+=uiomove.9 uio.9
+MLINKS+=usbd_transfer.9 usbd_setup_xfer.9
 MLINKS+=uvm.9 uvm_init.9 uvm.9 uvm_init_limits.9 uvm.9 uvm_setpagesize.9 \
        uvm.9 uvm_swap_init.9 uvm.9 uvm_map.9 uvm.9 uvm_map_pageable.9 \
        uvm.9 uvm_map_pageable_all.9 uvm.9 uvm_map_checkprot.9 \
Index: share/man/man9/usbd_transfer.9
===================================================================
RCS file: share/man/man9/usbd_transfer.9
diff -N share/man/man9/usbd_transfer.9
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ share/man/man9/usbd_transfer.9      5 Sep 2013 10:23:37 -0000
@@ -0,0 +1,105 @@
+.\" $OpenBSD$
+.\"
+.\" Copyright (c) 2013 Martin Pieuchot
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.Dd $Mdocdate$
+.Dt USBD_TRANSFER 9
+.Os
+.Sh NAME
+.Nm usbd_setup_xfer , usbd_transfer
+.Nd submit USB data transfers
+.Sh SYNOPSIS
+.In dev/usb/usb.h
+.In dev/usb/usbdi.h
+.Ft void
+.Fn usbd_setup_xfer "struct usbd_xfer *xfer" "struct usbd_pipe *pipe" \
+ "void *priv" "void *buffer" "uint32_t length" "uint16_t flags" \
+ "uint32_t timeout" "usbd_callback callback"
+.Ft usbd_status
+.Fn usbd_transfer "struct usbd_xfer *xfer"
+.Sh DESCRIPTION
+These functions provide a controller independent mechanism to perform USB
+data transfers.
+.Pp
+The function
+.Fn usbd_setup_xfer
+is used to initialize the structure pointed to by
+.Fa xfer ,
+describing an individual transfer to submit.
+It takes the following arguments:
+.Bl -tag -width callback
+.It Fa xfer
+A pointer to an existing structure describing a transfer.
+.It Fa pipe
+A pointer to a pipe associated with the endpoint for the transfer.
+.It Fa priv
+A pointer to a private cookie untouched by the USB stack for reuse in the
+.Fa callback .
+.It Fa buffer
+A pointer to the data buffer.
+.It Fa length
+The total length of the data to read or write.
+.It Fa flags
+The characteristics of the transfer:
+.Bl -tag -width xxx -offset indent
+.It Dv USBD_NO_COPY
+Do not copy data between
+.Fa buffer
+and the DMA buffer.
+.It Dv USBD_SYNCHRONOUS
+Causes
+.Fn usbd_transfer
+to sleep until the I/O transfer is complete or the
+.Fa timeout
+expires.
+.It Dv USBD_SHORT_XFER_OK
+Do not report short reads, when the length of the data read is lower than
+.Fa length ,
+as errors.
+.It Dv USBD_FORCE_SHORT_XFER
+Submit a supplementary zero length packet at the end of the data if
+.Fa length
+is a multiple of the endpoint's wMaxPacketSize.
+.It Dv USBD_CATCH
+Used in conjunction with the
+.Dv USBD_SYNCHRONOUS
+flag to pass the
+.Dv PCATCH
+flag to
+.Xr tsleep 9
+in order to check for signals before and after sleeping.
+.El
+.It Fa timeout
+Timeout of the transfer in milliseconds.
+.It Fa callback
+A routine invoked upon completion of the transfer whether successful or not.
+.El
+.Pp
+The function
+.Fn usbd_transfer
+is used to submit the USB transfer described by
+.Fa xfer
+to the corresponding
+.Xr usb 4
+host controller to perform I/O with devices.
+.Sh CODE REFERENCES
+These functions are implemented in the file
+.Pa sys/dev/usb/usbdi.c .
+.Sh SEE ALSO
+.Xr ehci 4 ,
+.Xr ohci 4 ,
+.Xr uhci 4 ,
+.Xr usb 4 ,
+.Xr tsleep 9

Reply via email to