summaryrefslogtreecommitdiffstats
path: root/sys/dev/usb/README.TXT
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/usb/README.TXT')
-rw-r--r--sys/dev/usb/README.TXT411
1 files changed, 411 insertions, 0 deletions
diff --git a/sys/dev/usb/README.TXT b/sys/dev/usb/README.TXT
new file mode 100644
index 0000000..d24770c
--- /dev/null
+++ b/sys/dev/usb/README.TXT
@@ -0,0 +1,411 @@
+
+$FreeBSD$
+
+DESCRIPTION OF THE NEW USB API
+
+The new USB 2.0 API consists of 5 functions. All transfer types are
+managed using these functions. There is no longer need for separate
+functions to setup INTERRUPT- and ISOCHRONOUS- transfers.
+
++--------------------------------------------------------------+
+| |
+| "usb2_transfer_setup" - This function will allocate all |
+| necessary DMA memory and might |
+| sleep! |
+| |
+| "usb2_transfer_unsetup" - This function will stop the USB |
+| transfer, if it is currently |
+| active, release all DMA |
+| memory and might sleep! |
+| |
+| "usb2_transfer_start" - This function will start an USB |
+| transfer, if not already started.|
+| This function is always |
+| non-blocking. ** |
+| |
+| "usb2_transfer_stop" - This function will stop an USB |
+| transfer, if not already stopped.|
+| The callback function will be |
+| called before this function |
+| returns. This function is always |
+| non-blocking. ** |
+| |
+| "usb2_transfer_drain" - This function will stop an USB |
+| transfer, if not already stopped |
+| and wait for any additional |
+| DMA load operations to complete. |
+| Buffers that are loaded into DMA |
+| using "usb2_set_frame_data" can |
+| safely be freed after that |
+| this function has returned. This |
+| function can block the caller. |
+| |
+| ** These functions must be called with the private driver's |
+| lock locked. |
+| |
+| NOTE: These USB API functions are NULL safe, with regard |
+| to the USB transfer structure pointer. |
++--------------------------------------------------------------+
+
+Reference: /sys/dev/usb/usb_transfer.c
+
+/*
+ * A simple USB callback state-machine:
+ *
+ * +->-----------------------+
+ * | |
+ * +-<-+-------[tr_setup]--------+-<-+-<-[start/restart]
+ * | |
+ * | |
+ * | |
+ * +------>-[tr_transferred]---------+
+ * | |
+ * +--------->-[tr_error]------------+
+ */
+
+void
+usb2_default_callback(struct usb2_xfer *xfer)
+{
+ /*
+ * NOTE: it is not allowed to return
+ * before "USB_CHECK_STATUS()",
+ * even if the system is tearing down!
+ */
+ switch (USB_GET_STATE(xfer)) {
+ case USB_ST_SETUP:
+ /*
+ * Setup xfer->frlengths[], xfer->nframes
+ * and write data to xfer->frbuffers[], if any
+ */
+
+ /**/
+ usb2_start_hardware(xfer);
+ return;
+
+ case USB_ST_TRANSFERRED:
+ /*
+ * Read data from xfer->frbuffers[], if any.
+ * "xfer->frlengths[]" should now have been
+ * updated to the actual length.
+ */
+ return;
+
+ default: /* Error */
+ /* print error message and clear stall for example */
+ return;
+ }
+}
+
+=== Notes for USB control transfers ===
+
+An USB control transfer has three parts. First the SETUP packet, then
+DATA packet(s) and then a STATUS packet. The SETUP packet is always
+pointed to by "xfer->frbuffers[0]" and the length is stored in
+"xfer->frlengths[0]" also if there should not be sent any SETUP
+packet! If an USB control transfer has no DATA stage, then
+"xfer->nframes" should be set to 1. Else the default value is
+"xfer->nframes" equal to 2.
+
+Example1: SETUP + STATUS
+ xfer->nframes = 1;
+ xfer->frlenghts[0] = 8;
+ usb2_start_hardware(xfer);
+
+Example2: SETUP + DATA + STATUS
+ xfer->nframes = 2;
+ xfer->frlenghts[0] = 8;
+ xfer->frlenghts[1] = 1;
+ usb2_start_hardware(xfer);
+
+Example3: SETUP + DATA + STATUS - split
+1st callback:
+ xfer->nframes = 1;
+ xfer->frlenghts[0] = 8;
+ usb2_start_hardware(xfer);
+
+2nd callback:
+ /* IMPORTANT: frbuffer[0] must still point at the setup packet! */
+ xfer->nframes = 2;
+ xfer->frlenghts[0] = 0;
+ xfer->frlenghts[1] = 1;
+ usb2_start_hardware(xfer);
+
+Example4: SETUP + STATUS - split
+1st callback:
+ xfer->nframes = 1;
+ xfer->frlenghts[0] = 8;
+ xfer->flags.manual_status = 1;
+ usb2_start_hardware(xfer);
+
+2nd callback:
+ xfer->nframes = 1;
+ xfer->frlenghts[0] = 0;
+ xfer->flags.manual_status = 0;
+ usb2_start_hardware(xfer);
+
+
+=== General USB transfer notes ===
+
+ 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.
+
+ 2) After that the "usb2_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
+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 the thread returns from sleep.
+
+ 4) Polling.
+
+ use_polling
+ This flag can be used with any callback and will cause the
+ "usb2_transfer_start()" function to wait using "DELAY()",
+ without exiting any mutexes, until the transfer is finished or
+ has timed out. This flag can be changed during operation.
+
+ NOTE: If polling is used the "timeout" field should be non-zero!
+ NOTE: USB_ERR_CANCELLED is returned in case of timeout
+ instead of USB_ERR_TIMEOUT!
+
+
+
+USB device driver examples:
+
+/sys/dev/usb/net/if_axe.c
+/sys/dev/usb/net/if_aue.c
+
+QUICK REFERENCE
+===============
+
+
+/*------------------------------------------------------------------------*
+ * usb2_error_t
+ * usb2_transfer_setup(udev, ifaces, pxfer, setup_start,
+ * n_setup, priv_sc, priv_mtx)
+ *------------------------------------------------------------------------*/
+
+- "udev" is a pointer to "struct usb2_device".
+
+- "ifaces" array of interface index numbers to use. See "if_index".
+
+- "pxfer" is a pointer to an array of USB transfer pointers that are
+ initialized to NULL, and then pointed to allocated USB transfers.
+
+- "setup_start" is a pointer to an array of USB config structures.
+
+- "n_setup" is a number telling the USB system how many USB transfers
+ should be setup.
+
+- "priv_sc" is the private softc pointer, which will be used to
+ initialize "xfer->priv_sc".
+
+- "priv_mtx" is the private mutex protecting the transfer structure and
+ the softc. This pointer is used to initialize "xfer->priv_mtx".
+
+/*------------------------------------------------------------------------*
+ * void
+ * usb2_transfer_unsetup(pxfer, n_setup)
+ *------------------------------------------------------------------------*/
+
+- "pxfer" is a pointer to an array of USB transfer pointers, that may
+ be NULL, that should be freed by the USB system.
+
+- "n_setup" is a number telling the USB system how many USB transfers
+ should be unsetup
+
+NOTE: This function can sleep, waiting for active mutexes to become unlocked!
+NOTE: It is not allowed to call "usb2_transfer_unsetup" from the callback
+ of a USB transfer.
+
+/*------------------------------------------------------------------------*
+ * void
+ * usb2_transfer_start(xfer)
+ *------------------------------------------------------------------------*/
+
+- "xfer" is pointer to a USB transfer that should be started
+
+NOTE: this function must be called with "priv_mtx" locked
+
+/*------------------------------------------------------------------------*
+ * void
+ * usb2_transfer_stop(xfer)
+ *------------------------------------------------------------------------*/
+
+- "xfer" is a pointer to a USB transfer that should be stopped
+
+NOTE: this function must be called with "priv_mtx" locked
+
+NOTE: if the transfer was in progress, the callback will called with
+ "xfer->error=USB_ERR_CANCELLED", before this function returns
+
+/*------------------------------------------------------------------------*
+ * struct usb2_config {
+ * type, endpoint, direction, interval, timeout, frames, index
+ * flags, bufsize, callback
+ * };
+ *------------------------------------------------------------------------*/
+
+- The "type" field selects the USB pipe type. Valid values are:
+ UE_INTERRUPT, UE_CONTROL, UE_BULK, UE_ISOCHRONOUS. The special
+ value UE_BULK_INTR will select BULK and INTERRUPT pipes.
+ This field is mandatory.
+
+- The "endpoint" field selects the USB endpoint number. A value of
+ 0xFF, "-1" or "UE_ADDR_ANY" will select the first matching endpoint.
+ This field is mandatory.
+
+- The "direction" field selects the USB endpoint direction. A value of
+ "UE_DIR_ANY" will select the first matching endpoint. Else valid
+ values are: "UE_DIR_IN" and "UE_DIR_OUT". "UE_DIR_IN" and
+ "UE_DIR_OUT" can be binary ORed by "UE_DIR_SID" which means that the
+ direction will be swapped in case of USB_MODE_DEVICE. Note that
+ "UE_DIR_IN" refers to the data transfer direction of the "IN" tokens
+ and "UE_DIR_OUT" refers to the data transfer direction of the "OUT"
+ tokens. This field is mandatory.
+
+- The "interval" field selects the interrupt interval. The value of this
+ field is given in milliseconds and is independent of device speed. Depending
+ on the endpoint type, this field has different meaning:
+
+ UE_INTERRUPT)
+ "0" use the default interrupt interval based on endpoint descriptor.
+ "Else" use the given value for polling rate.
+
+ UE_ISOCHRONOUS)
+ "0" use default.
+ "Else" the value is ignored.
+
+ UE_BULK)
+ UE_CONTROL)
+ "0" no transfer pre-delay.
+ "Else" a delay as given by this field in milliseconds is
+ inserted before the hardware is started when
+ "usb2_start_hardware()" is called.
+ NOTE: The transfer timeout, if any, is started after that
+ the pre-delay has elapsed!
+
+- The "timeout" field, if non-zero, will set the transfer timeout in
+ 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 maximum number of frames. If zero is
+ specified it will yield the following results:
+
+ UE_BULK)
+ UE_INTERRUPT)
+ xfer->nframes = 1;
+
+ UE_CONTROL)
+ xfer->nframes = 2;
+
+ UE_ISOCHRONOUS)
+ Not allowed. Will cause an error.
+
+- The "ep_index" field allows you to give a number, in case more
+ endpoints match the description, that selects which matching
+ "ep_index" should be used.
+
+- The "if_index" field allows you to select which of the interface
+ numbers in the "ifaces" array parameter passed to "usb2_transfer_setup"
+ that should be used when setting up the given USB transfer.
+
+- The "flags" field has type "struct usb2_xfer_flags" and allows one
+ to set initial flags an USB transfer. Valid flags are:
+
+ force_short_xfer
+ This flag forces the last transmitted USB packet to be short.
+ A short packet has a length of less than "xfer->max_packet_size",
+ which derives from "wMaxPacketSize". This flag can be changed
+ during operation.
+
+ short_xfer_ok
+ This flag allows the received transfer length, "xfer->actlen"
+ to be less than "xfer->sumlen" upon completion of a transfer.
+ This flag can be changed during operation.
+
+ pipe_bof
+ This flag causes a failing USB transfer to remain first
+ in the PIPE queue except in the case of "xfer->error" equal
+ to "USB_ERR_CANCELLED". No other USB transfers in the affected
+ PIPE queue will be started until either:
+
+ 1) The failing USB transfer is stopped using "usb2_transfer_stop()".
+ 2) The failing USB transfer performs a successful transfer.
+
+ The purpose of this flag is to avoid races when multiple
+ transfers are queued for execution on an USB endpoint, and the
+ first executing transfer fails leading to the need for
+ clearing of stall for example. In this case this flag is used
+ to prevent the following USB transfers from being executed at
+ the same time the clear-stall command is executed on the USB
+ control endpoint. This flag can be changed during operation.
+
+ "BOF" is short for "Block On Failure"
+
+ NOTE: This flag should be set on all BULK and INTERRUPT
+ USB transfers which use an endpoint that can be shared
+ between userland and kernel.
+
+ proxy_buffer
+ 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. This flag can not be changed
+ during operation.
+
+ ext_buffer
+ Setting this flag will cause that no data buffer will be
+ allocated. Instead the USB client must supply a data buffer.
+ This flag can not be changed during operation.
+
+ manual_status
+ Setting this flag prevents an USB STATUS stage to be appended
+ to the end of the USB control transfer. If no control data is
+ transferred this flag must be cleared. Else an error will be
+ returned to the USB callback. This flag is mostly useful for
+ the USB device side. This flag can be changed during
+ operation.
+
+ no_pipe_ok
+ Setting this flag causes the USB_ERR_NO_PIPE error to be
+ ignored. This flag can not be changed during operation.
+
+ stall_pipe
+ Setting this flag will cause STALL pids to be sent to the
+ endpoint belonging to this transfer before the transfer is
+ started. The transfer is started at the moment the host issues
+ a clear-stall command on the STALL'ed endpoint. This flag can
+ be changed during operation. This flag does only have effect
+ in USB device side mode except for control endpoints. This
+ flag is cleared when the stall command has been executed. This
+ flag can only be changed outside the callback function by
+ using the functions "usb2_transfer_set_stall()" and
+ "usb2_transfer_clear_stall()" !
+
+- 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
+ setting up interrupt pipes. This field is mandatory.
+
+ NOTE: For control transfers "bufsize" includes
+ the length of the request structure.
+
+- The "callback" pointer sets the USB callback. This field is mandatory.
+
+MUTEX NOTE:
+===========
+
+When you create a mutex using "mtx_init()", don't forget to call
+"mtx_destroy()" at detach, else you can get "freed memory accessed"
+panics.
+
+--HPS
OpenPOWER on IntegriCloud