On Fri, May 10, 2013 at 09:44:53AM +0200, Martin Pieuchot wrote: > So this is is one more step in my effort to merge the various code paths > to submit an USB transfer. > > 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. > > ok?
This is OK for me. > Index: sys/dev/usb/ugen.c > =================================================================== > RCS file: /cvs/src/sys/dev/usb/ugen.c,v > retrieving revision 1.71 > diff -u -p -r1.71 ugen.c > --- sys/dev/usb/ugen.c 15 Apr 2013 09:23:02 -0000 1.71 > +++ sys/dev/usb/ugen.c 26 Apr 2013 15:09:55 -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,14 +546,17 @@ 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, tn, > + flags, sce->timeout, NULL); > + err = usbd_transfer(xfer); > if (err) { > if (err == USBD_INTERRUPTED) > error = EINTR; > @@ -640,7 +643,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 +666,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,8 +680,9 @@ 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) { > if (err == USBD_INTERRUPTED) > error = EINTR; > @@ -698,8 +705,9 @@ 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) { > if (err == USBD_INTERRUPTED) > error = EINTR; > Index: sys/dev/usb/uhidev.c > =================================================================== > RCS file: /cvs/src/sys/dev/usb/uhidev.c,v > retrieving revision 1.43 > diff -u -p -r1.43 uhidev.c > --- sys/dev/usb/uhidev.c 15 Apr 2013 09:23:02 -0000 1.43 > +++ sys/dev/usb/uhidev.c 26 Apr 2013 15:03:01 -0000 > @@ -650,8 +650,9 @@ 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); > + return usbd_transfer(sc->sc_owxfer); > } > > int > Index: sys/dev/usb/ulpt.c > =================================================================== > RCS file: /cvs/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 26 Apr 2013 15:02:55 -0000 > @@ -636,8 +636,9 @@ 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) { > DPRINTF(("ulptwrite: error=%d\n", err)); > error = EIO; > @@ -704,8 +705,9 @@ 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) { > printf("%s: ucode upload error=%s!\n", > sc->sc_dev.dv_xname, usbd_errstr(error)); > Index: sys/dev/usb/umsm.c > =================================================================== > RCS file: /cvs/src/sys/dev/usb/umsm.c,v > retrieving revision 1.90 > diff -u -p -r1.90 umsm.c > --- sys/dev/usb/umsm.c 15 Apr 2013 09:23:02 -0000 1.90 > +++ sys/dev/usb/umsm.c 26 Apr 2013 15:02:43 -0000 > @@ -767,8 +767,9 @@ 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"); > + usbd_setup_xfer(xfer, cmdpipe, 0, bufp, n, > + USBD_NO_COPY | USBD_SYNCHRONOUS, 0, NULL); > + err = usbd_transfer(xfer); > if (err) > DPRINTF(("%s: send error:%s", __func__, > usbd_errstr(err))); > Index: sys/dev/usb/urio.c > =================================================================== > RCS file: /cvs/src/sys/dev/usb/urio.c,v > retrieving revision 1.41 > diff -u -p -r1.41 urio.c > --- sys/dev/usb/urio.c 15 Apr 2013 09:23:02 -0000 1.41 > +++ sys/dev/usb/urio.c 26 Apr 2013 15:02:02 -0000 > @@ -328,8 +328,9 @@ 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, tn, > + USBD_NO_COPY | USBD_SYNCHRONOUS, URIO_RW_TIMEOUT, NULL); > + err = usbd_transfer(xfer); > if (err) { > if (err == USBD_INTERRUPTED) > error = EINTR; > @@ -390,8 +391,9 @@ 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) > Index: sys/dev/usb/usbdi.c > =================================================================== > RCS file: /cvs/src/sys/dev/usb/usbdi.c,v > retrieving revision 1.55 > diff -u -p -r1.55 usbdi.c > --- sys/dev/usb/usbdi.c 26 Apr 2013 14:19:25 -0000 1.55 > +++ sys/dev/usb/usbdi.c 26 Apr 2013 15:14:07 -0000 > @@ -293,7 +293,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); > @@ -351,7 +351,8 @@ 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); > + tsleep(xfer, flags, "usbsyn", 0); > } > splx(s); > return (xfer->status); > Index: sys/dev/usb/usbdi.h > =================================================================== > RCS file: /cvs/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 26 Apr 2013 14:20:01 -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: /cvs/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 26 Apr 2013 14:20:01 -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: /cvs/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 26 Apr 2013 14:20:01 -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: sys/dev/usb/uscanner.c > =================================================================== > RCS file: /cvs/src/sys/dev/usb/uscanner.c,v > retrieving revision 1.48 > diff -u -p -r1.48 uscanner.c > --- sys/dev/usb/uscanner.c 15 Apr 2013 09:23:02 -0000 1.48 > +++ sys/dev/usb/uscanner.c 26 Apr 2013 15:01:47 -0000 > @@ -464,11 +464,12 @@ uscanner_do_read(struct uscanner_softc * > DPRINTFN(1, ("uscannerread: start transfer %d bytes\n",n)); > tn = n; > > - err = usbd_bulk_transfer( > + usbd_setup_xfer( > sc->sc_bulkin_xfer, sc->sc_bulkin_pipe, > - USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, > - sc->sc_bulkin_buffer, &tn, > - "uscnrb"); > + 0, sc->sc_bulkin_buffer, tn, > + USBD_SHORT_XFER_OK | USBD_SYNCHRONOUS | USBD_CATCH, 0, > + NULL); > + err = usbd_transfer(sc->sc_bulkin_xfer); > if (err) { > if (err == USBD_INTERRUPTED) > error = EINTR; > @@ -520,11 +521,11 @@ uscanner_do_write(struct uscanner_softc > if (error) > break; > DPRINTFN(1, ("uscanner_do_write: transfer %d bytes\n", n)); > - err = usbd_bulk_transfer( > + usbd_setup_xfer( > sc->sc_bulkout_xfer, sc->sc_bulkout_pipe, > - 0, USBD_NO_TIMEOUT, > - sc->sc_bulkout_buffer, &n, > - "uscnwb"); > + 0, sc->sc_bulkout_buffer, n, > + USBD_SYNCHRONOUS | USBD_CATCH, 0, NULL); > + err = usbd_transfer(sc->sc_bulkout_xfer); > if (err) { > if (err == USBD_INTERRUPTED) > error = EINTR; > Index: share/man/man9//Makefile > =================================================================== > RCS file: /cvs/src/share/man/man9/Makefile,v > retrieving revision 1.177 > diff -u -p -r1.177 Makefile > --- share/man/man9//Makefile 24 Apr 2013 17:29:02 -0000 1.177 > +++ share/man/man9//Makefile 30 Apr 2013 11:28:30 -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 \ > @@ -331,6 +333,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 30 Apr 2013 11:46:51 -0000 > @@ -0,0 +1,102 @@ > +.\" $OpenBSD$ > +.\" > +.\" Copyright (c) 2013 Martin Pieuchot <m...@openbsd.org> > +.\" > +.\" 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 initialized the structure pointed 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 to the endpoint for the transfer. > +.It Fa priv > +A pointer to a private cookie untouched by the USB stack for re-use 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 as follows: > +.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 USBD_SYNCHRONOUS flag to pass the PCATCH flag to > +.Xr tsleep 9 > +in order to check for signals before and after sleeping. > +.El > +.It Fa timout > +Timeout of the transfer in milliseconds. > +.It Fa callback > +A routine invoked upon completion of the transfer wether 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 perfom I/O with devices. > +.Pp > +.Sh CODE REFERENCES > +These functions are implemented in the file > +.Pa sys/dev/usb/usbdi.c . > +.Sh SEE ALSO > +.Xr usb 4 , > +.Xr ehci 4 , > +.Xr ohci 4 , > +.Xr uhci 4 , > +.Xr tsleep 9 > -- [ Marcus Glocker, mar...@nazgul.ch, mgloc...@openbsd.org ]