PERFORCE change 127068 for review
Hans Petter Selasky
hselasky at FreeBSD.org
Mon Oct 1 11:01:00 PDT 2007
Change 127068 by hselasky at hselasky_laptop001 on 2007/10/01 18:00:52
Update README to reflect the latest USB API changes.
Affected files ...
.. //depot/projects/usb/src/sys/dev/usb/README#18 edit
==== //depot/projects/usb/src/sys/dev/usb/README#18 (text+ko) ====
@@ -1,14 +1,3 @@
-The OHCI and UHCI drivers do currently not compile due to ongoing
-work, which is expected to be complete by the end of week 39 2007.
-You can work around this by not including "device ohci" and "device
-uhci" in your kernel config file until furter. To use full/low speed
-devices, connect them through an external USB HUB.
DESCRIPTION OF THE NEW USB API
The new USB 2.0 API consists of 4 functions. All transfer types are managed
@@ -23,8 +12,8 @@
| "usbd_transfer_unsetup" - This function will stop the USB |
| transfer, if it is currently |
-| active and release all DMA |
-| memory. |
+| active, release all DMA |
+| memory and might sleep! |
| "usbd_transfer_start" - This function will start a USB |
| transfer, if not already started.|
@@ -46,13 +35,6 @@
-One must setup the USB transfer, struct usbd_xfer, from the
-callback handler, which is required for non-blocking operation, in the end.
-This behavior is also very practical when writing USB device drivers, because
-it is easy to make a loop, starting the next transfer from the previous.
-Simply reorder the labels! The callback's lock is locked by the caller. This
-solves synchronization problems related to stopping USB transfers.
* A simple USB callback state-machine:
@@ -70,48 +52,60 @@
usbd_default_callback(struct usbd_xfer *xfer)
- /* NOTE: it is not allowed to return
+ * NOTE: it is not allowed to return
* before "USBD_CHECK_STATUS()",
* even if the system is tearing down!
- /* setup xfer->length, xfer->frlengths, xfer->nframes
- * and write data to xfer->buffer if any
+ * Setup xfer->frlengths, xfer->nframes
+ * and write data to xfer->frbuffers, if any
- /* read data from xfer->buffer if any */
+ * Read data from xfer->frbuffers, if any.
+ * "xfer->frlengths" should now have been
+ * updated to the actual length.
- /* print error message and clear stall for example */
+ /* print error message and clear stall for example */
-NOTE for control endpoints: all of the control transfer now resides in the
-buffer pointed to by "xfer->buffer", including the request. This is better and
+NOTE: An USB control transfer has three parts. First the SETUP packet,
+then DATA packet(s) and then a STATUS packet. The SETUP packet is
+pointed to by "xfer->frbuffers" and the length is stored in
+"xfer->frlengths". Zero-length entries in the "xfer->frlengths" array
+will be ignored. Typically the DATA packet(s) are pointed to by
+"xfer->frbuffers" and the length is stored in "xfer->frlengths".
+The STATUS packet is automatically executed unless "xfer->flags.manual_status"
+is set. If "xfer->flags.manual_status" is set the STATUS packet will
+be executed if the length of last USB frame is zero.
- 1) Something that one should be aware of is that, all USB callbacks support
+ 1) Something that one should be aware of is that all USB callbacks support
recursation. That means one can start/stop whatever transfer from the callback
of another transfer one desires. Also the transfer that is currently called
-back. Recursion is handled like this, that when the callback that wants to
-recurse returns, it is called one more time.
+back. Recursion is handled like this that when the callback that wants to
+recurse returns it is called one more time.
- 2) After that the "tr_setup" label has been jumped in the callback, one can
-always depend on that "tr_error" or "tr_transferred" will get jumped
+ 2) After that the "usbd_start_hardware()" function has been called in
+the callback one can always depend on that "tr_error" or "tr_transferred"
+will get jumped afterwards. Always!
- 3) sleeping functions can only be called from the attach routine of the
+ 3) Sleeping functions can only be called from the attach routine of the
driver. Else one should not use sleeping functions unless one has to. It is
very difficult with sleep, because one has to think that the device might have
-detached when it returns from sleep.
+detached when the thread returns from sleep.
USB device driver examples:
@@ -230,26 +224,38 @@
milliseconds. If the "timeout" field is zero and the transfer type
is ISOCHRONOUS a timeout of 250ms will be used.
-- The "frames" field sets the number of isochronous frames, for
- "type" = UE_ISOCHRONOUS.
+- The "frames" field sets the maximum number of frames. If zero is
+ specified it will yield the following results:
+ xfer->nframes = 1;
+ xfer->nframes = 2;
+ Not allowed. Will cause an error.
- The "index" field allows one to give a number, in case more
endpoints match the description, that selects which matching
"index" should be used.
-- The "flags" field allows one to set flags for the transfer. Valid flags are:
+- The "flags" field has type "struct usbd_xfer_flags" and allows one
+ to set initial flags an USB transfer. Valid flags are:
This flag forces the last USB packet sent to be short. A short
packet has a length of less than "xfer->max_packet_size", which
derives from "wMaxPacketSize".
This flag allows the transfer length, "xfer->actlen" to be
- less than "xfer->length", upon completion of a transfer.
+ less than "xfer->sumlen" upon completion of a transfer.
This flag can be used with any callback and will cause the
- "usbd_transfer_start()" function to wait, using "DELAY()",
+ "usbd_transfer_start()" function to wait using "DELAY()",
without exiting any mutexes, until the transfer is finished or
has timed out.
@@ -257,15 +263,7 @@
NOTE: USBD_CANCELLED is returned in case of timeout
instead of USBD_TIMEOUT!
- This flag will cause the USB host controller driver to not
- allocate a second data buffer, "xfer->buffer". Instead of
- transferring data using "xfer->buffer", data must be
- transferred by a call to "usbd_copy_in(&(xfer->buf_data),
- offset, src, len)" or "usbd_copy_out(&(xfer->buf_data),
- offset, dst, len)". This saves an extra data copy.
This flag causes a failing USB transfer to remain first
in the PIPE queue except in the case of "xfer->error" equal
to "USBD_CANCELLED". No other USB transfers in the affected
@@ -288,9 +286,28 @@
USB transfers which use an endpoint that can be shared
between userland and kernel.
+ Setting this flag will cause that the total buffer size will
+ be rounded up to the nearest atomic hardware transfer
+ size. The maximum data length of any USB transfer is always
+ stored in the "xfer->max_data_length". For control transfers
+ the USB kernel will allocate additional space for the 8-bytes
+ of SETUP header. These 8-bytes are not counted by the
+ "xfer->max_data_length" variable.
+ Setting this flag will cause that no DMA data buffer will be
+ allocated. Instead the USB client can use its own DMA buffer.
+ Setting this flag causes that the STATUS stage of a control
+ transfer needs to be sent separately like a zero-length USB
+ frame. This flag has currently no effect on non-control
+ transfers. This flag is mostly useful for the USB device side.
- The "bufsize" field sets the total buffer size in bytes. If
this field is zero, "wMaxPacketSize" will be used, multiplied by the
- "frames" field if the transfer type is isochronous. This is useful for
+ "frames" field if the transfer type is ISOCHRONOUS. This is useful for
setting up interrupt pipes. This field is mandatory.
NOTE: For control transfers "bufsize" includes
@@ -301,9 +318,8 @@
-When you create a mutex, using "mtx_init()", don't forget to call
+When you create a mutex using "mtx_init()", don't forget to call
"mtx_destroy()" at detach, else you can get "freed memory accessed"
More information about the p4-projects