Resguardo inicial

This commit is contained in:
lastdragon
2026-09-06 12:53:21 -06:00
parent 662efe3c2a
commit ad2088d178
94853 changed files with 43200404 additions and 0 deletions
@@ -0,0 +1,290 @@
.. _usb-urb:
USB Request Block (URB)
~~~~~~~~~~~~~~~~~~~~~~~
:Revised: 2000-Dec-05
:Again: 2002-Jul-06
:Again: 2005-Sep-19
:Again: 2017-Mar-29
.. note::
The USB subsystem now has a substantial section at :ref:`usb-hostside-api`
section, generated from the current source code.
This particular documentation file isn't complete and may not be
updated to the last version; don't rely on it except for a quick
overview.
Basic concept or 'What is an URB?'
==================================
The basic idea of the new driver is message passing, the message itself is
called USB Request Block, or URB for short.
- An URB consists of all relevant information to execute any USB transaction
and deliver the data and status back.
- Execution of an URB is inherently an asynchronous operation, i.e. the
:c:func:`usb_submit_urb` call returns immediately after it has successfully
queued the requested action.
- Transfers for one URB can be canceled with :c:func:`usb_unlink_urb`
at any time.
- Each URB has a completion handler, which is called after the action
has been successfully completed or canceled. The URB also contains a
context-pointer for passing information to the completion handler.
- Each endpoint for a device logically supports a queue of requests.
You can fill that queue, so that the USB hardware can still transfer
data to an endpoint while your driver handles completion of another.
This maximizes use of USB bandwidth, and supports seamless streaming
of data to (or from) devices when using periodic transfer modes.
The URB structure
=================
Some of the fields in struct urb are::
struct urb
{
// (IN) device and pipe specify the endpoint queue
struct usb_device *dev; // pointer to associated USB device
unsigned int pipe; // endpoint information
unsigned int transfer_flags; // URB_ISO_ASAP, URB_SHORT_NOT_OK, etc.
// (IN) all urbs need completion routines
void *context; // context for completion routine
usb_complete_t complete; // pointer to completion routine
// (OUT) status after each completion
int status; // returned status
// (IN) buffer used for data transfers
void *transfer_buffer; // associated data buffer
u32 transfer_buffer_length; // data buffer length
int number_of_packets; // size of iso_frame_desc
// (OUT) sometimes only part of CTRL/BULK/INTR transfer_buffer is used
u32 actual_length; // actual data buffer length
// (IN) setup stage for CTRL (pass a struct usb_ctrlrequest)
unsigned char *setup_packet; // setup packet (control only)
// Only for PERIODIC transfers (ISO, INTERRUPT)
// (IN/OUT) start_frame is set unless URB_ISO_ASAP isn't set
int start_frame; // start frame
int interval; // polling interval
// ISO only: packets are only "best effort"; each can have errors
int error_count; // number of errors
struct usb_iso_packet_descriptor iso_frame_desc[0];
};
Your driver must create the "pipe" value using values from the appropriate
endpoint descriptor in an interface that it's claimed.
How to get an URB?
==================
URBs are allocated by calling :c:func:`usb_alloc_urb`::
struct urb *usb_alloc_urb(int isoframes, int mem_flags)
Return value is a pointer to the allocated URB, 0 if allocation failed.
The parameter isoframes specifies the number of isochronous transfer frames
you want to schedule. For CTRL/BULK/INT, use 0. The mem_flags parameter
holds standard memory allocation flags, letting you control (among other
things) whether the underlying code may block or not.
To free an URB, use :c:func:`usb_free_urb`::
void usb_free_urb(struct urb *urb)
You may free an urb that you've submitted, but which hasn't yet been
returned to you in a completion callback. It will automatically be
deallocated when it is no longer in use.
What has to be filled in?
=========================
Depending on the type of transaction, there are some inline functions
defined in ``linux/usb.h`` to simplify the initialization, such as
:c:func:`usb_fill_control_urb`, :c:func:`usb_fill_bulk_urb` and
:c:func:`usb_fill_int_urb`. In general, they need the usb device pointer,
the pipe (usual format from usb.h), the transfer buffer, the desired transfer
length, the completion handler, and its context. Take a look at the some
existing drivers to see how they're used.
Flags:
- For ISO there are two startup behaviors: Specified start_frame or ASAP.
- For ASAP set ``URB_ISO_ASAP`` in transfer_flags.
If short packets should NOT be tolerated, set ``URB_SHORT_NOT_OK`` in
transfer_flags.
How to submit an URB?
=====================
Just call :c:func:`usb_submit_urb`::
int usb_submit_urb(struct urb *urb, int mem_flags)
The ``mem_flags`` parameter, such as ``GFP_ATOMIC``, controls memory
allocation, such as whether the lower levels may block when memory is tight.
It immediately returns, either with status 0 (request queued) or some
error code, usually caused by the following:
- Out of memory (``-ENOMEM``)
- Unplugged device (``-ENODEV``)
- Stalled endpoint (``-EPIPE``)
- Too many queued ISO transfers (``-EAGAIN``)
- Too many requested ISO frames (``-EFBIG``)
- Invalid INT interval (``-EINVAL``)
- More than one packet for INT (``-EINVAL``)
After submission, ``urb->status`` is ``-EINPROGRESS``; however, you should
never look at that value except in your completion callback.
For isochronous endpoints, your completion handlers should (re)submit
URBs to the same endpoint with the ``URB_ISO_ASAP`` flag, using
multi-buffering, to get seamless ISO streaming.
How to cancel an already running URB?
=====================================
There are two ways to cancel an URB you've submitted but which hasn't
been returned to your driver yet. For an asynchronous cancel, call
:c:func:`usb_unlink_urb`::
int usb_unlink_urb(struct urb *urb)
It removes the urb from the internal list and frees all allocated
HW descriptors. The status is changed to reflect unlinking. Note
that the URB will not normally have finished when :c:func:`usb_unlink_urb`
returns; you must still wait for the completion handler to be called.
To cancel an URB synchronously, call :c:func:`usb_kill_urb`::
void usb_kill_urb(struct urb *urb)
It does everything :c:func:`usb_unlink_urb` does, and in addition it waits
until after the URB has been returned and the completion handler
has finished. It also marks the URB as temporarily unusable, so
that if the completion handler or anyone else tries to resubmit it
they will get a ``-EPERM`` error. Thus you can be sure that when
:c:func:`usb_kill_urb` returns, the URB is totally idle.
There is a lifetime issue to consider. An URB may complete at any
time, and the completion handler may free the URB. If this happens
while :c:func:`usb_unlink_urb` or :c:func:`usb_kill_urb` is running, it will
cause a memory-access violation. The driver is responsible for avoiding this,
which often means some sort of lock will be needed to prevent the URB
from being deallocated while it is still in use.
On the other hand, since usb_unlink_urb may end up calling the
completion handler, the handler must not take any lock that is held
when usb_unlink_urb is invoked. The general solution to this problem
is to increment the URB's reference count while holding the lock, then
drop the lock and call usb_unlink_urb or usb_kill_urb, and then
decrement the URB's reference count. You increment the reference
count by calling :c:func`usb_get_urb`::
struct urb *usb_get_urb(struct urb *urb)
(ignore the return value; it is the same as the argument) and
decrement the reference count by calling :c:func:`usb_free_urb`. Of course,
none of this is necessary if there's no danger of the URB being freed
by the completion handler.
What about the completion handler?
==================================
The handler is of the following type::
typedef void (*usb_complete_t)(struct urb *)
I.e., it gets the URB that caused the completion call. In the completion
handler, you should have a look at ``urb->status`` to detect any USB errors.
Since the context parameter is included in the URB, you can pass
information to the completion handler.
Note that even when an error (or unlink) is reported, data may have been
transferred. That's because USB transfers are packetized; it might take
sixteen packets to transfer your 1KByte buffer, and ten of them might
have transferred successfully before the completion was called.
.. warning::
NEVER SLEEP IN A COMPLETION HANDLER.
These are often called in atomic context.
In the current kernel, completion handlers run with local interrupts
disabled, but in the future this will be changed, so don't assume that
local IRQs are always disabled inside completion handlers.
How to do isochronous (ISO) transfers?
======================================
Besides the fields present on a bulk transfer, for ISO, you also
have to set ``urb->interval`` to say how often to make transfers; it's
often one per frame (which is once every microframe for highspeed devices).
The actual interval used will be a power of two that's no bigger than what
you specify. You can use the :c:func:`usb_fill_int_urb` macro to fill
most ISO transfer fields.
For ISO transfers you also have to fill a :c:type:`usb_iso_packet_descriptor`
structure, allocated at the end of the URB by :c:func:`usb_alloc_urb`, for
each packet you want to schedule.
The :c:func:`usb_submit_urb` call modifies ``urb->interval`` to the implemented
interval value that is less than or equal to the requested interval value. If
``URB_ISO_ASAP`` scheduling is used, ``urb->start_frame`` is also updated.
For each entry you have to specify the data offset for this frame (base is
transfer_buffer), and the length you want to write/expect to read.
After completion, actual_length contains the actual transferred length and
status contains the resulting status for the ISO transfer for this frame.
It is allowed to specify a varying length from frame to frame (e.g. for
audio synchronisation/adaptive transfer rates). You can also use the length
0 to omit one or more frames (striping).
For scheduling you can choose your own start frame or ``URB_ISO_ASAP``. As
explained earlier, if you always keep at least one URB queued and your
completion keeps (re)submitting a later URB, you'll get smooth ISO streaming
(if usb bandwidth utilization allows).
If you specify your own start frame, make sure it's several frames in advance
of the current frame. You might want this model if you're synchronizing
ISO data with some other event stream.
How to start interrupt (INT) transfers?
=======================================
Interrupt transfers, like isochronous transfers, are periodic, and happen
in intervals that are powers of two (1, 2, 4 etc) units. Units are frames
for full and low speed devices, and microframes for high speed ones.
You can use the :c:func:`usb_fill_int_urb` macro to fill INT transfer fields.
The :c:func:`usb_submit_urb` call modifies ``urb->interval`` to the implemented
interval value that is less than or equal to the requested interval value.
In Linux 2.6, unlike earlier versions, interrupt URBs are not automagically
restarted when they complete. They end when the completion handler is
called, just like other URBs. If you want an interrupt URB to be restarted,
your completion handler must resubmit it.
s
@@ -0,0 +1,72 @@
USB Anchors
~~~~~~~~~~~
What is anchor?
===============
A USB driver needs to support some callbacks requiring
a driver to cease all IO to an interface. To do so, a
driver has to keep track of the URBs it has submitted
to know they've all completed or to call usb_kill_urb
for them. The anchor is a data structure takes care of
keeping track of URBs and provides methods to deal with
multiple URBs.
Allocation and Initialisation
=============================
There's no API to allocate an anchor. It is simply declared
as struct usb_anchor. :c:func:`init_usb_anchor` must be called to
initialise the data structure.
Deallocation
============
Once it has no more URBs associated with it, the anchor can be
freed with normal memory management operations.
Association and disassociation of URBs with anchors
===================================================
An association of URBs to an anchor is made by an explicit
call to :c:func:`usb_anchor_urb`. The association is maintained until
an URB is finished by (successful) completion. Thus disassociation
is automatic. A function is provided to forcibly finish (kill)
all URBs associated with an anchor.
Furthermore, disassociation can be made with :c:func:`usb_unanchor_urb`
Operations on multitudes of URBs
================================
:c:func:`usb_kill_anchored_urbs`
--------------------------------
This function kills all URBs associated with an anchor. The URBs
are called in the reverse temporal order they were submitted.
This way no data can be reordered.
:c:func:`usb_scuttle_anchored_urbs`
-----------------------------------
All URBs of an anchor are unanchored en masse.
:c:func:`usb_wait_anchor_empty_timeout`
---------------------------------------
This function waits for all URBs associated with an anchor to finish
or a timeout, whichever comes first. Its return value will tell you
whether the timeout was reached.
:c:func:`usb_anchor_empty`
--------------------------
Returns true if no URBs are associated with an anchor. Locking
is the caller's responsibility.
:c:func:`usb_get_from_anchor`
-----------------------------
Returns the oldest anchored URB of an anchor. The URB is unanchored
and returned with a reference. As you may mix URBs to several
destinations in one anchor you have no guarantee the chronologically
first submitted URB is returned.
@@ -0,0 +1,83 @@
USB bulk streams
~~~~~~~~~~~~~~~~
Background
==========
Bulk endpoint streams were added in the USB 3.0 specification. Streams allow a
device driver to overload a bulk endpoint so that multiple transfers can be
queued at once.
Streams are defined in sections 4.4.6.4 and 8.12.1.4 of the Universal Serial Bus
3.0 specification at https://www.usb.org/developers/docs/ The USB Attached SCSI
Protocol, which uses streams to queue multiple SCSI commands, can be found on
the T10 website (https://t10.org/).
Device-side implications
========================
Once a buffer has been queued to a stream ring, the device is notified (through
an out-of-band mechanism on another endpoint) that data is ready for that stream
ID. The device then tells the host which "stream" it wants to start. The host
can also initiate a transfer on a stream without the device asking, but the
device can refuse that transfer. Devices can switch between streams at any
time.
Driver implications
===================
::
int usb_alloc_streams(struct usb_interface *interface,
struct usb_host_endpoint **eps, unsigned int num_eps,
unsigned int num_streams, gfp_t mem_flags);
Device drivers will call this API to request that the host controller driver
allocate memory so the driver can use up to num_streams stream IDs. They must
pass an array of usb_host_endpoints that need to be setup with similar stream
IDs. This is to ensure that a UASP driver will be able to use the same stream
ID for the bulk IN and OUT endpoints used in a Bi-directional command sequence.
The return value is an error condition (if one of the endpoints doesn't support
streams, or the xHCI driver ran out of memory), or the number of streams the
host controller allocated for this endpoint. The xHCI host controller hardware
declares how many stream IDs it can support, and each bulk endpoint on a
SuperSpeed device will say how many stream IDs it can handle. Therefore,
drivers should be able to deal with being allocated less stream IDs than they
requested.
Do NOT call this function if you have URBs enqueued for any of the endpoints
passed in as arguments. Do not call this function to request less than two
streams.
Drivers will only be allowed to call this API once for the same endpoint
without calling usb_free_streams(). This is a simplification for the xHCI host
controller driver, and may change in the future.
Picking new Stream IDs to use
=============================
Stream ID 0 is reserved, and should not be used to communicate with devices. If
usb_alloc_streams() returns with a value of N, you may use streams 1 though N.
To queue an URB for a specific stream, set the urb->stream_id value. If the
endpoint does not support streams, an error will be returned.
Note that new API to choose the next stream ID will have to be added if the xHCI
driver supports secondary stream IDs.
Clean up
========
If a driver wishes to stop using streams to communicate with the device, it
should call::
void usb_free_streams(struct usb_interface *interface,
struct usb_host_endpoint **eps, unsigned int num_eps,
gfp_t mem_flags);
All stream IDs will be deallocated when the driver releases the interface, to
ensure that drivers that don't support streams will be able to use the endpoint.
@@ -0,0 +1,159 @@
USB core callbacks
~~~~~~~~~~~~~~~~~~
What callbacks will usbcore do?
===============================
Usbcore will call into a driver through callbacks defined in the driver
structure and through the completion handler of URBs a driver submits.
Only the former are in the scope of this document. These two kinds of
callbacks are completely independent of each other. Information on the
completion callback can be found in :ref:`usb-urb`.
The callbacks defined in the driver structure are:
1. Hotplugging callbacks:
- @probe:
Called to see if the driver is willing to manage a particular
interface on a device.
- @disconnect:
Called when the interface is no longer accessible, usually
because its device has been (or is being) disconnected or the
driver module is being unloaded.
2. Odd backdoor through usbfs:
- @ioctl:
Used for drivers that want to talk to userspace through
the "usbfs" filesystem. This lets devices provide ways to
expose information to user space regardless of where they
do (or don't) show up otherwise in the filesystem.
3. Power management (PM) callbacks:
- @suspend:
Called when the device is going to be suspended.
- @resume:
Called when the device is being resumed.
- @reset_resume:
Called when the suspended device has been reset instead
of being resumed.
4. Device level operations:
- @pre_reset:
Called when the device is about to be reset.
- @post_reset:
Called after the device has been reset
The ioctl interface (2) should be used only if you have a very good
reason. Sysfs is preferred these days. The PM callbacks are covered
separately in :ref:`usb-power-management`.
Calling conventions
===================
All callbacks are mutually exclusive. There's no need for locking
against other USB callbacks. All callbacks are called from a task
context. You may sleep. However, it is important that all sleeps have a
small fixed upper limit in time. In particular you must not call out to
user space and await results.
Hotplugging callbacks
=====================
These callbacks are intended to associate and disassociate a driver with
an interface. A driver's bond to an interface is exclusive.
The probe() callback
--------------------
::
int (*probe) (struct usb_interface *intf,
const struct usb_device_id *id);
Accept or decline an interface. If you accept the device return 0,
otherwise -ENODEV or -ENXIO. Other error codes should be used only if a
genuine error occurred during initialisation which prevented a driver
from accepting a device that would else have been accepted.
You are strongly encouraged to use usbcore's facility,
usb_set_intfdata(), to associate a data structure with an interface, so
that you know which internal state and identity you associate with a
particular interface. The device will not be suspended and you may do IO
to the interface you are called for and endpoint 0 of the device. Device
initialisation that doesn't take too long is a good idea here.
The disconnect() callback
-------------------------
::
void (*disconnect) (struct usb_interface *intf);
This callback is a signal to break any connection with an interface.
You are not allowed any IO to a device after returning from this
callback. You also may not do any other operation that may interfere
with another driver bound to the interface, eg. a power management
operation. Outstanding operations on the device must be completed or
aborted before this callback may return.
If you are called due to a physical disconnection, all your URBs will be
killed by usbcore. Note that in this case disconnect will be called some
time after the physical disconnection. Thus your driver must be prepared
to deal with failing IO even prior to the callback.
Device level callbacks
======================
pre_reset
---------
::
int (*pre_reset)(struct usb_interface *intf);
A driver or user space is triggering a reset on the device which
contains the interface passed as an argument. Cease IO, wait for all
outstanding URBs to complete, and save any device state you need to
restore. No more URBs may be submitted until the post_reset method
is called.
If you need to allocate memory here, use GFP_NOIO or GFP_ATOMIC, if you
are in atomic context.
post_reset
----------
::
int (*post_reset)(struct usb_interface *intf);
The reset has completed. Restore any saved device state and begin
using the device again.
If you need to allocate memory here, use GFP_NOIO or GFP_ATOMIC, if you
are in atomic context.
Call sequences
==============
No callbacks other than probe will be invoked for an interface
that isn't bound to your driver.
Probe will never be called for an interface bound to a driver.
Hence following a successful probe, disconnect will be called
before there is another probe for the same interface.
Once your driver is bound to an interface, disconnect can be
called at any time except in between pre_reset and post_reset.
pre_reset is always followed by post_reset, even if the reset
failed or the device has been unplugged.
suspend is always followed by one of: resume, reset_resume, or
disconnect.
@@ -0,0 +1,110 @@
USB DMA
~~~~~~~
In Linux 2.5 kernels (and later), USB device drivers have additional control
over how DMA may be used to perform I/O operations. The APIs are detailed
in the kernel usb programming guide (kerneldoc, from the source code).
API overview
============
The big picture is that USB drivers can continue to ignore most DMA issues,
though they still must provide DMA-ready buffers (see
Documentation/core-api/dma-api-howto.rst). That's how they've worked through
the 2.4 (and earlier) kernels, or they can now be DMA-aware.
DMA-aware usb drivers:
- New calls enable DMA-aware drivers, letting them allocate dma buffers and
manage dma mappings for existing dma-ready buffers (see below).
- URBs have an additional "transfer_dma" field, as well as a transfer_flags
bit saying if it's valid. (Control requests also have "setup_dma", but
drivers must not use it.)
- "usbcore" will map this DMA address, if a DMA-aware driver didn't do
it first and set ``URB_NO_TRANSFER_DMA_MAP``. HCDs
don't manage dma mappings for URBs.
- There's a new "generic DMA API", parts of which are usable by USB device
drivers. Never use dma_set_mask() on any USB interface or device; that
would potentially break all devices sharing that bus.
Eliminating copies
==================
It's good to avoid making CPUs copy data needlessly. The costs can add up,
and effects like cache-trashing can impose subtle penalties.
- If you're doing lots of small data transfers from the same buffer all
the time, that can really burn up resources on systems which use an
IOMMU to manage the DMA mappings. It can cost MUCH more to set up and
tear down the IOMMU mappings with each request than perform the I/O!
For those specific cases, USB has primitives to allocate less expensive
memory. They work like kmalloc and kfree versions that give you the right
kind of addresses to store in urb->transfer_buffer and urb->transfer_dma.
You'd also set ``URB_NO_TRANSFER_DMA_MAP`` in urb->transfer_flags::
void *usb_alloc_coherent (struct usb_device *dev, size_t size,
int mem_flags, dma_addr_t *dma);
void usb_free_coherent (struct usb_device *dev, size_t size,
void *addr, dma_addr_t dma);
Most drivers should **NOT** be using these primitives; they don't need
to use this type of memory ("dma-coherent"), and memory returned from
:c:func:`kmalloc` will work just fine.
The memory buffer returned is "dma-coherent"; sometimes you might need to
force a consistent memory access ordering by using memory barriers. It's
not using a streaming DMA mapping, so it's good for small transfers on
systems where the I/O would otherwise thrash an IOMMU mapping. (See
Documentation/core-api/dma-api-howto.rst for definitions of "coherent" and
"streaming" DMA mappings.)
Asking for 1/Nth of a page (as well as asking for N pages) is reasonably
space-efficient.
On most systems the memory returned will be uncached, because the
semantics of dma-coherent memory require either bypassing CPU caches
or using cache hardware with bus-snooping support. While x86 hardware
has such bus-snooping, many other systems use software to flush cache
lines to prevent DMA conflicts.
- Devices on some EHCI controllers could handle DMA to/from high memory.
Unfortunately, the current Linux DMA infrastructure doesn't have a sane
way to expose these capabilities ... and in any case, HIGHMEM is mostly a
design wart specific to x86_32. So your best bet is to ensure you never
pass a highmem buffer into a USB driver. That's easy; it's the default
behavior. Just don't override it; e.g. with ``NETIF_F_HIGHDMA``.
This may force your callers to do some bounce buffering, copying from
high memory to "normal" DMA memory. If you can come up with a good way
to fix this issue (for x86_32 machines with over 1 GByte of memory),
feel free to submit patches.
Working with existing buffers
=============================
Existing buffers aren't usable for DMA without first being mapped into the
DMA address space of the device. However, most buffers passed to your
driver can safely be used with such DMA mapping. (See the first section
of Documentation/core-api/dma-api-howto.rst, titled "What memory is DMA-able?")
- When you have the scatterlists which have been mapped for the USB controller,
you could use the new ``usb_sg_*()`` calls, which would turn scatterlist
into URBs::
int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev,
unsigned pipe, unsigned period, struct scatterlist *sg,
int nents, size_t length, gfp_t mem_flags);
void usb_sg_wait(struct usb_sg_request *io);
void usb_sg_cancel(struct usb_sg_request *io);
When the USB controller doesn't support DMA, the ``usb_sg_init()`` would try
to submit URBs in PIO way as long as the page in scatterlists is not in the
Highmem, which could be very rare in modern architectures.
@@ -0,0 +1,711 @@
===============================================================
Synopsys DesignWare Core SuperSpeed USB 3.0 Controller
===============================================================
:Author: Felipe Balbi <felipe.balbi@linux.intel.com>
:Date: April 2017
Introduction
============
The *Synopsys DesignWare Core SuperSpeed USB 3.0 Controller*
(hereinafter referred to as *DWC3*) is a USB SuperSpeed compliant
controller which can be configured in one of 4 ways:
1. Peripheral-only configuration
2. Host-only configuration
3. Dual-Role configuration
4. Hub configuration
Linux currently supports several versions of this controller. In all
likelihood, the version in your SoC is already supported. At the time
of this writing, known tested versions range from 2.02a to 3.10a. As a
rule of thumb, anything above 2.02a should work reliably well.
Currently, we have many known users for this driver. In alphabetical
order:
1. Cavium
2. Intel Corporation
3. Qualcomm
4. Rockchip
5. ST
6. Samsung
7. Texas Instruments
8. Xilinx
Summary of Features
======================
For details about features supported by your version of DWC3, consult
your IP team and/or *Synopsys DesignWare Core SuperSpeed USB 3.0
Controller Databook*. Following is a list of features supported by the
driver at the time of this writing:
1. Up to 16 bidirectional endpoints (including the control
pipe - ep0)
2. Flexible endpoint configuration
3. Simultaneous IN and OUT transfer support
4. Scatter-list support
5. Up to 256 TRBs [#trb]_ per endpoint
6. Support for all transfer types (*Control*, *Bulk*,
*Interrupt*, and *Isochronous*)
7. SuperSpeed Bulk Streams
8. Link Power Management
9. Trace Events for debugging
10. DebugFS [#debugfs]_ interface
These features have all been exercised with many of the **in-tree**
gadget drivers. We have verified both *ConfigFS* [#configfs]_ and
legacy gadget drivers.
Driver Design
==============
The DWC3 driver sits on the *drivers/usb/dwc3/* directory. All files
related to this driver are in this one directory. This makes it easy
for new-comers to read the code and understand how it behaves.
Because of DWC3's configuration flexibility, the driver is a little
complex in some places but it should be rather straightforward to
understand.
The biggest part of the driver refers to the Gadget API.
Known Limitations
===================
Like any other HW, DWC3 has its own set of limitations. To avoid
constant questions about such problems, we decided to document them
here and have a single location to where we could point users.
OUT Transfer Size Requirements
---------------------------------
According to Synopsys Databook, all OUT transfer TRBs [#trb]_ must
have their *size* field set to a value which is integer divisible by
the endpoint's *wMaxPacketSize*. This means that *e.g.* in order to
receive a Mass Storage *CBW* [#cbw]_, req->length must either be set
to a value that's divisible by *wMaxPacketSize* (1024 on SuperSpeed,
512 on HighSpeed, etc), or DWC3 driver must add a Chained TRB pointing
to a throw-away buffer for the remaining length. Without this, OUT
transfers will **NOT** start.
Note that as of this writing, this won't be a problem because DWC3 is
fully capable of appending a chained TRB for the remaining length and
completely hide this detail from the gadget driver. It's still worth
mentioning because this seems to be the largest source of queries
about DWC3 and *non-working transfers*.
TRB Ring Size Limitation
-------------------------
We, currently, have a hard limit of 256 TRBs [#trb]_ per endpoint,
with the last TRB being a Link TRB [#link_trb]_ pointing back to the
first. This limit is arbitrary but it has the benefit of adding up to
exactly 4096 bytes, or 1 Page.
DWC3 driver will try its best to cope with more than 255 requests and,
for the most part, it should work normally. However this is not
something that has been exercised very frequently. If you experience
any problems, see section **Reporting Bugs** below.
Reporting Bugs
================
Whenever you encounter a problem with DWC3, first and foremost you
should make sure that:
1. You're running latest tag from `Linus' tree`_
2. You can reproduce the error without any out-of-tree changes
to DWC3
3. You have checked that it's not a fault on the host machine
After all these are verified, then here's how to capture enough
information so we can be of any help to you.
Required Information
---------------------
DWC3 relies exclusively on Trace Events for debugging. Everything is
exposed there, with some extra bits being exposed to DebugFS
[#debugfs]_.
In order to capture DWC3's Trace Events you should run the following
commands **before** plugging the USB cable to a host machine:
.. code-block:: sh
# mkdir -p /d
# mkdir -p /t
# mount -t debugfs none /d
# mount -t tracefs none /t
# echo 81920 > /t/buffer_size_kb
# echo 1 > /t/events/dwc3/enable
After this is done, you can connect your USB cable and reproduce the
problem. As soon as the fault is reproduced, make a copy of files
``trace`` and ``regdump``, like so:
.. code-block:: sh
# cp /t/trace /root/trace.txt
# cat /d/*dwc3*/regdump > /root/regdump.txt
Make sure to compress ``trace.txt`` and ``regdump.txt`` in a tarball
and email it to `me`_ with `linux-usb`_ in Cc. If you want to be extra
sure that I'll help you, write your subject line in the following
format:
**[BUG REPORT] usb: dwc3: Bug while doing XYZ**
On the email body, make sure to detail what you doing, which gadget
driver you were using, how to reproduce the problem, what SoC you're
using, which OS (and its version) was running on the Host machine.
With all this information, we should be able to understand what's
going on and be helpful to you.
Debugging
===========
First and foremost a disclaimer::
DISCLAIMER: The information available on DebugFS and/or TraceFS can
change at any time at any Major Linux Kernel Release. If writing
scripts, do **NOT** assume information to be available in the
current format.
With that out of the way, let's carry on.
If you're willing to debug your own problem, you deserve a round of
applause :-)
Anyway, there isn't much to say here other than Trace Events will be
really helpful in figuring out issues with DWC3. Also, access to
Synopsys Databook will be **really** valuable in this case.
A USB Sniffer can be helpful at times but it's not entirely required,
there's a lot that can be understood without looking at the wire.
Feel free to email `me`_ and Cc `linux-usb`_ if you need any help.
``DebugFS``
-------------
``DebugFS`` is very good for gathering snapshots of what's going on
with DWC3 and/or any endpoint.
On DWC3's ``DebugFS`` directory, you will find the following files and
directories:
``ep[0..15]{in,out}/``
``link_state``
``regdump``
``testmode``
``link_state``
``````````````
When read, ``link_state`` will print out one of ``U0``, ``U1``,
``U2``, ``U3``, ``SS.Disabled``, ``RX.Detect``, ``SS.Inactive``,
``Polling``, ``Recovery``, ``Hot Reset``, ``Compliance``,
``Loopback``, ``Reset``, ``Resume`` or ``UNKNOWN link state``.
This file can also be written to in order to force link to one of the
states above.
``regdump``
`````````````
File name is self-explanatory. When read, ``regdump`` will print out a
register dump of DWC3. Note that this file can be grepped to find the
information you want.
``testmode``
``````````````
When read, ``testmode`` will print out a name of one of the specified
USB 2.0 Testmodes (``test_j``, ``test_k``, ``test_se0_nak``,
``test_packet``, ``test_force_enable``) or the string ``no test`` in
case no tests are currently being executed.
In order to start any of these test modes, the same strings can be
written to the file and DWC3 will enter the requested test mode.
``ep[0..15]{in,out}``
``````````````````````
For each endpoint we expose one directory following the naming
convention ``ep$num$dir`` *(ep0in, ep0out, ep1in, ...)*. Inside each
of these directories you will find the following files:
``descriptor_fetch_queue``
``event_queue``
``rx_fifo_queue``
``rx_info_queue``
``rx_request_queue``
``transfer_type``
``trb_ring``
``tx_fifo_queue``
``tx_request_queue``
With access to Synopsys Databook, you can decode the information on
them.
``transfer_type``
~~~~~~~~~~~~~~~~~~
When read, ``transfer_type`` will print out one of ``control``,
``bulk``, ``interrupt`` or ``isochronous`` depending on what the
endpoint descriptor says. If the endpoint hasn't been enabled yet, it
will print ``--``.
``trb_ring``
~~~~~~~~~~~~~
When read, ``trb_ring`` will print out details about all TRBs on the
ring. It will also tell you where our enqueue and dequeue pointers are
located in the ring:
.. code-block:: sh
buffer_addr,size,type,ioc,isp_imi,csp,chn,lst,hwo
000000002c754000,481,normal,1,0,1,0,0,0
000000002c75c000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c754000,481,normal,1,0,1,0,0,0
000000002c75c000,481,normal,1,0,1,0,0,0
000000002c784000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c784000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c754000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c784000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c784000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c754000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c75c000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c754000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c754000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c754000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c75c000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c784000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c754000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c75c000,512,normal,1,0,1,0,0,1 D
0000000000000000,0,UNKNOWN,0,0,0,0,0,0 E
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
00000000381ab000,0,link,0,0,0,0,0,1
Trace Events
-------------
DWC3 also provides several trace events which help us gathering
information about the behavior of the driver during runtime.
In order to use these events, you must enable ``CONFIG_FTRACE`` in
your kernel config.
For details about how enable DWC3 events, see section **Reporting
Bugs**.
The following subsections will give details about each Event Class and
each Event defined by DWC3.
MMIO
```````
It is sometimes useful to look at every MMIO access when looking for
bugs. Because of that, DWC3 offers two Trace Events (one for
dwc3_readl() and one for dwc3_writel()). ``TP_printk`` follows::
TP_printk("addr %p value %08x", __entry->base + __entry->offset,
__entry->value)
Interrupt Events
````````````````
Every IRQ event can be logged and decoded into a human readable
string. Because every event will be different, we don't give an
example other than the ``TP_printk`` format used::
TP_printk("event (%08x): %s", __entry->event,
dwc3_decode_event(__entry->event, __entry->ep0state))
Control Request
`````````````````
Every USB Control Request can be logged to the trace buffer. The
output format is::
TP_printk("%s", dwc3_decode_ctrl(__entry->bRequestType,
__entry->bRequest, __entry->wValue,
__entry->wIndex, __entry->wLength)
)
Note that Standard Control Requests will be decoded into
human-readable strings with their respective arguments. Class and
Vendor requests will be printed out a sequence of 8 bytes in hex
format.
Lifetime of a ``struct usb_request``
```````````````````````````````````````
The entire lifetime of a ``struct usb_request`` can be tracked on the
trace buffer. We have one event for each of allocation, free,
queueing, dequeueing, and giveback. Output format is::
TP_printk("%s: req %p length %u/%u %s%s%s ==> %d",
__get_str(name), __entry->req, __entry->actual, __entry->length,
__entry->zero ? "Z" : "z",
__entry->short_not_ok ? "S" : "s",
__entry->no_interrupt ? "i" : "I",
__entry->status
)
Generic Commands
````````````````````
We can log and decode every Generic Command with its completion
code. Format is::
TP_printk("cmd '%s' [%x] param %08x --> status: %s",
dwc3_gadget_generic_cmd_string(__entry->cmd),
__entry->cmd, __entry->param,
dwc3_gadget_generic_cmd_status_string(__entry->status)
)
Endpoint Commands
````````````````````
Endpoints commands can also be logged together with completion
code. Format is::
TP_printk("%s: cmd '%s' [%d] params %08x %08x %08x --> status: %s",
__get_str(name), dwc3_gadget_ep_cmd_string(__entry->cmd),
__entry->cmd, __entry->param0,
__entry->param1, __entry->param2,
dwc3_ep_cmd_status_string(__entry->cmd_status)
)
Lifetime of a ``TRB``
``````````````````````
A ``TRB`` Lifetime is simple. We are either preparing a ``TRB`` or
completing it. With these two events, we can see how a ``TRB`` changes
over time. Format is::
TP_printk("%s: %d/%d trb %p buf %08x%08x size %s%d ctrl %08x (%c%c%c%c:%c%c:%s)",
__get_str(name), __entry->queued, __entry->allocated,
__entry->trb, __entry->bph, __entry->bpl,
({char *s;
int pcm = ((__entry->size >> 24) & 3) + 1;
switch (__entry->type) {
case USB_ENDPOINT_XFER_INT:
case USB_ENDPOINT_XFER_ISOC:
switch (pcm) {
case 1:
s = "1x ";
break;
case 2:
s = "2x ";
break;
case 3:
s = "3x ";
break;
}
default:
s = "";
} s; }),
DWC3_TRB_SIZE_LENGTH(__entry->size), __entry->ctrl,
__entry->ctrl & DWC3_TRB_CTRL_HWO ? 'H' : 'h',
__entry->ctrl & DWC3_TRB_CTRL_LST ? 'L' : 'l',
__entry->ctrl & DWC3_TRB_CTRL_CHN ? 'C' : 'c',
__entry->ctrl & DWC3_TRB_CTRL_CSP ? 'S' : 's',
__entry->ctrl & DWC3_TRB_CTRL_ISP_IMI ? 'S' : 's',
__entry->ctrl & DWC3_TRB_CTRL_IOC ? 'C' : 'c',
dwc3_trb_type_string(DWC3_TRBCTL_TYPE(__entry->ctrl))
)
Lifetime of an Endpoint
```````````````````````
And endpoint's lifetime is summarized with enable and disable
operations, both of which can be traced. Format is::
TP_printk("%s: mps %d/%d streams %d burst %d ring %d/%d flags %c:%c%c%c%c%c:%c:%c",
__get_str(name), __entry->maxpacket,
__entry->maxpacket_limit, __entry->max_streams,
__entry->maxburst, __entry->trb_enqueue,
__entry->trb_dequeue,
__entry->flags & DWC3_EP_ENABLED ? 'E' : 'e',
__entry->flags & DWC3_EP_STALL ? 'S' : 's',
__entry->flags & DWC3_EP_WEDGE ? 'W' : 'w',
__entry->flags & DWC3_EP_TRANSFER_STARTED ? 'B' : 'b',
__entry->flags & DWC3_EP_PENDING_REQUEST ? 'P' : 'p',
__entry->flags & DWC3_EP_END_TRANSFER_PENDING ? 'E' : 'e',
__entry->direction ? '<' : '>'
)
Structures, Methods and Definitions
====================================
.. kernel-doc:: drivers/usb/dwc3/core.h
:doc: main data structures
:internal:
.. kernel-doc:: drivers/usb/dwc3/gadget.h
:doc: gadget-only helpers
:internal:
.. kernel-doc:: drivers/usb/dwc3/gadget.c
:doc: gadget-side implementation
:internal:
.. kernel-doc:: drivers/usb/dwc3/core.c
:doc: core driver (probe, PM, etc)
:internal:
.. [#trb] Transfer Request Block
.. [#link_trb] Transfer Request Block pointing to another Transfer
Request Block.
.. [#debugfs] The Debug File System
.. [#configfs] The Config File System
.. [#cbw] Command Block Wrapper
.. _Linus' tree: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/
.. _me: felipe.balbi@linux.intel.com
.. _linux-usb: linux-usb@vger.kernel.org
@@ -0,0 +1,210 @@
.. _usb-error-codes:
USB Error codes
~~~~~~~~~~~~~~~
:Revised: 2004-Oct-21
This is the documentation of (hopefully) all possible error codes (and
their interpretation) that can be returned from usbcore.
Some of them are returned by the Host Controller Drivers (HCDs), which
device drivers only see through usbcore. As a rule, all the HCDs should
behave the same except for transfer speed dependent behaviors and the
way certain faults are reported.
Error codes returned by :c:func:`usb_submit_urb`
================================================
Non-USB-specific:
=============== ===============================================
0 URB submission went fine
``-ENOMEM`` no memory for allocation of internal structures
=============== ===============================================
USB-specific:
======================= =======================================================
``-EBUSY`` The URB is already active.
``-ENODEV`` specified USB-device or bus doesn't exist
``-ENOENT`` specified interface or endpoint does not exist or
is not enabled
``-ENXIO`` host controller driver does not support queuing of
this type of urb. (treat as a host controller bug.)
``-EINVAL`` a) Invalid transfer type specified (or not supported)
b) Invalid or unsupported periodic transfer interval
c) ISO: attempted to change transfer interval
d) ISO: ``number_of_packets`` is < 0
e) various other cases
``-EXDEV`` ISO: ``URB_ISO_ASAP`` wasn't specified and all the
frames the URB would be scheduled in have already
expired.
``-EFBIG`` Host controller driver can't schedule that many ISO
frames.
``-EPIPE`` The pipe type specified in the URB doesn't match the
endpoint's actual type.
``-EMSGSIZE`` (a) endpoint maxpacket size is zero; it is not usable
in the current interface altsetting.
(b) ISO packet is larger than the endpoint maxpacket.
(c) requested data transfer length is invalid: negative
or too large for the host controller.
``-EBADR`` The wLength value in a control URB's setup packet does
not match the URB's transfer_buffer_length.
``-ENOSPC`` This request would overcommit the usb bandwidth reserved
for periodic transfers (interrupt, isochronous).
``-ESHUTDOWN`` The device or host controller has been disabled due to
some problem that could not be worked around.
``-EPERM`` Submission failed because ``urb->reject`` was set.
``-EHOSTUNREACH`` URB was rejected because the device is suspended.
``-ENOEXEC`` A control URB doesn't contain a Setup packet.
======================= =======================================================
Error codes returned by ``in urb->status`` or in ``iso_frame_desc[n].status`` (for ISO)
=======================================================================================
USB device drivers may only test urb status values in completion handlers.
This is because otherwise there would be a race between HCDs updating
these values on one CPU, and device drivers testing them on another CPU.
A transfer's actual_length may be positive even when an error has been
reported. That's because transfers often involve several packets, so that
one or more packets could finish before an error stops further endpoint I/O.
For isochronous URBs, the urb status value is non-zero only if the URB is
unlinked, the device is removed, the host controller is disabled, or the total
transferred length is less than the requested length and the
``URB_SHORT_NOT_OK`` flag is set. Completion handlers for isochronous URBs
should only see ``urb->status`` set to zero, ``-ENOENT``, ``-ECONNRESET``,
``-ESHUTDOWN``, or ``-EREMOTEIO``. Individual frame descriptor status fields
may report more status codes.
=============================== ===============================================
0 Transfer completed successfully
``-ENOENT`` URB was synchronously unlinked by
:c:func:`usb_unlink_urb`
``-EINPROGRESS`` URB still pending, no results yet
(That is, if drivers see this it's a bug.)
``-EPROTO`` [#f1]_, [#f2]_ a) bitstuff error
b) no response packet received within the
prescribed bus turn-around time
c) unknown USB error
``-EILSEQ`` [#f1]_, [#f2]_ a) CRC mismatch
b) no response packet received within the
prescribed bus turn-around time
c) unknown USB error
Note that often the controller hardware does
not distinguish among cases a), b), and c), so
a driver cannot tell whether there was a
protocol error, a failure to respond (often
caused by device disconnect), or some other
fault.
``-ETIME`` [#f2]_ No response packet received within the
prescribed bus turn-around time. This error
may instead be reported as
``-EPROTO`` or ``-EILSEQ``.
``-ETIMEDOUT`` Synchronous USB message functions use this code
to indicate timeout expired before the transfer
completed, and no other error was reported
by HC.
``-EPIPE`` [#f2]_ Endpoint stalled. For non-control endpoints,
reset this status with
:c:func:`usb_clear_halt`.
``-ECOMM`` During an IN transfer, the host controller
received data from an endpoint faster than it
could be written to system memory
``-ENOSR`` During an OUT transfer, the host controller
could not retrieve data from system memory fast
enough to keep up with the USB data rate
``-EOVERFLOW`` [#f1]_ The amount of data returned by the endpoint was
greater than either the max packet size of the
endpoint or the remaining buffer size.
"Babble".
``-EREMOTEIO`` The data read from the endpoint did not fill
the specified buffer, and ``URB_SHORT_NOT_OK``
was set in ``urb->transfer_flags``.
``-ENODEV`` Device was removed. Often preceded by a burst
of other errors, since the hub driver doesn't
detect device removal events immediately.
``-EXDEV`` ISO transfer only partially completed
(only set in ``iso_frame_desc[n].status``,
not ``urb->status``)
``-EINVAL`` ISO madness, if this happens: Log off and
go home
``-ECONNRESET`` URB was asynchronously unlinked by
:c:func:`usb_unlink_urb`
``-ESHUTDOWN`` The device or host controller has been
disabled due to some problem that could not
be worked around, such as a physical
disconnect.
=============================== ===============================================
.. [#f1]
Error codes like ``-EPROTO``, ``-EILSEQ`` and ``-EOVERFLOW`` normally
indicate hardware problems such as bad devices (including firmware)
or cables.
.. [#f2]
This is also one of several codes that different kinds of host
controller use to indicate a transfer has failed because of device
disconnect. In the interval before the hub driver starts disconnect
processing, devices may receive such fault reports for every request.
Error codes returned by usbcore-functions
=========================================
.. note:: expect also other submit and transfer status codes
:c:func:`usb_register`:
======================= ===================================
``-EINVAL`` error during registering new driver
======================= ===================================
``usb_get_*/usb_set_*()``,
:c:func:`usb_control_msg`,
:c:func:`usb_bulk_msg()`:
======================= ==============================================
``-ETIMEDOUT`` Timeout expired before the transfer completed.
======================= ==============================================
@@ -0,0 +1,510 @@
========================
USB Gadget API for Linux
========================
:Author: David Brownell
:Date: 20 August 2004
Introduction
============
This document presents a Linux-USB "Gadget" kernel mode API, for use
within peripherals and other USB devices that embed Linux. It provides
an overview of the API structure, and shows how that fits into a system
development project. This is the first such API released on Linux to
address a number of important problems, including:
- Supports USB 2.0, for high speed devices which can stream data at
several dozen megabytes per second.
- Handles devices with dozens of endpoints just as well as ones with
just two fixed-function ones. Gadget drivers can be written so
they're easy to port to new hardware.
- Flexible enough to expose more complex USB device capabilities such
as multiple configurations, multiple interfaces, composite devices,
and alternate interface settings.
- USB "On-The-Go" (OTG) support, in conjunction with updates to the
Linux-USB host side.
- Sharing data structures and API models with the Linux-USB host side
API. This helps the OTG support, and looks forward to more-symmetric
frameworks (where the same I/O model is used by both host and device
side drivers).
- Minimalist, so it's easier to support new device controller hardware.
I/O processing doesn't imply large demands for memory or CPU
resources.
Most Linux developers will not be able to use this API, since they have
USB ``host`` hardware in a PC, workstation, or server. Linux users with
embedded systems are more likely to have USB peripheral hardware. To
distinguish drivers running inside such hardware from the more familiar
Linux "USB device drivers", which are host side proxies for the real USB
devices, a different term is used: the drivers inside the peripherals
are "USB gadget drivers". In USB protocol interactions, the device
driver is the master (or "client driver") and the gadget driver is the
slave (or "function driver").
The gadget API resembles the host side Linux-USB API in that both use
queues of request objects to package I/O buffers, and those requests may
be submitted or canceled. They share common definitions for the standard
USB *Chapter 9* messages, structures, and constants. Also, both APIs
bind and unbind drivers to devices. The APIs differ in detail, since the
host side's current URB framework exposes a number of implementation
details and assumptions that are inappropriate for a gadget API. While
the model for control transfers and configuration management is
necessarily different (one side is a hardware-neutral master, the other
is a hardware-aware slave), the endpoint I/0 API used here should also
be usable for an overhead-reduced host side API.
Structure of Gadget Drivers
===========================
A system running inside a USB peripheral normally has at least three
layers inside the kernel to handle USB protocol processing, and may have
additional layers in user space code. The ``gadget`` API is used by the
middle layer to interact with the lowest level (which directly handles
hardware).
In Linux, from the bottom up, these layers are:
*USB Controller Driver*
This is the lowest software level. It is the only layer that talks
to hardware, through registers, fifos, dma, irqs, and the like. The
``<linux/usb/gadget.h>`` API abstracts the peripheral controller
endpoint hardware. That hardware is exposed through endpoint
objects, which accept streams of IN/OUT buffers, and through
callbacks that interact with gadget drivers. Since normal USB
devices only have one upstream port, they only have one of these
drivers. The controller driver can support any number of different
gadget drivers, but only one of them can be used at a time.
Examples of such controller hardware include the PCI-based NetChip
2280 USB 2.0 high speed controller, the SA-11x0 or PXA-25x UDC
(found within many PDAs), and a variety of other products.
*Gadget Driver*
The lower boundary of this driver implements hardware-neutral USB
functions, using calls to the controller driver. Because such
hardware varies widely in capabilities and restrictions, and is used
in embedded environments where space is at a premium, the gadget
driver is often configured at compile time to work with endpoints
supported by one particular controller. Gadget drivers may be
portable to several different controllers, using conditional
compilation. (Recent kernels substantially simplify the work
involved in supporting new hardware, by *autoconfiguring* endpoints
automatically for many bulk-oriented drivers.) Gadget driver
responsibilities include:
- handling setup requests (ep0 protocol responses) possibly
including class-specific functionality
- returning configuration and string descriptors
- (re)setting configurations and interface altsettings, including
enabling and configuring endpoints
- handling life cycle events, such as managing bindings to
hardware, USB suspend/resume, remote wakeup, and disconnection
from the USB host.
- managing IN and OUT transfers on all currently enabled endpoints
Such drivers may be modules of proprietary code, although that
approach is discouraged in the Linux community.
*Upper Level*
Most gadget drivers have an upper boundary that connects to some
Linux driver or framework in Linux. Through that boundary flows the
data which the gadget driver produces and/or consumes through
protocol transfers over USB. Examples include:
- user mode code, using generic (gadgetfs) or application specific
files in ``/dev``
- networking subsystem (for network gadgets, like the CDC Ethernet
Model gadget driver)
- data capture drivers, perhaps video4Linux or a scanner driver; or
test and measurement hardware.
- input subsystem (for HID gadgets)
- sound subsystem (for audio gadgets)
- file system (for PTP gadgets)
- block i/o subsystem (for usb-storage gadgets)
- ... and more
*Additional Layers*
Other layers may exist. These could include kernel layers, such as
network protocol stacks, as well as user mode applications building
on standard POSIX system call APIs such as ``open()``, ``close()``,
``read()`` and ``write()``. On newer systems, POSIX Async I/O calls may
be an option. Such user mode code will not necessarily be subject to
the GNU General Public License (GPL).
OTG-capable systems will also need to include a standard Linux-USB host
side stack, with ``usbcore``, one or more *Host Controller Drivers*
(HCDs), *USB Device Drivers* to support the OTG "Targeted Peripheral
List", and so forth. There will also be an *OTG Controller Driver*,
which is visible to gadget and device driver developers only indirectly.
That helps the host and device side USB controllers implement the two
new OTG protocols (HNP and SRP). Roles switch (host to peripheral, or
vice versa) using HNP during USB suspend processing, and SRP can be
viewed as a more battery-friendly kind of device wakeup protocol.
Over time, reusable utilities are evolving to help make some gadget
driver tasks simpler. For example, building configuration descriptors
from vectors of descriptors for the configurations interfaces and
endpoints is now automated, and many drivers now use autoconfiguration
to choose hardware endpoints and initialize their descriptors. A
potential example of particular interest is code implementing standard
USB-IF protocols for HID, networking, storage, or audio classes. Some
developers are interested in KDB or KGDB hooks, to let target hardware
be remotely debugged. Most such USB protocol code doesn't need to be
hardware-specific, any more than network protocols like X11, HTTP, or
NFS are. Such gadget-side interface drivers should eventually be
combined, to implement composite devices.
Kernel Mode Gadget API
======================
Gadget drivers declare themselves through a struct
:c:type:`usb_gadget_driver`, which is responsible for most parts of enumeration
for a struct usb_gadget. The response to a set_configuration usually
involves enabling one or more of the struct usb_ep objects exposed by
the gadget, and submitting one or more struct usb_request buffers to
transfer data. Understand those four data types, and their operations,
and you will understand how this API works.
.. Note::
Other than the "Chapter 9" data types, most of the significant data
types and functions are described here.
However, some relevant information is likely omitted from what you
are reading. One example of such information is endpoint
autoconfiguration. You'll have to read the header file, and use
example source code (such as that for "Gadget Zero"), to fully
understand the API.
The part of the API implementing some basic driver capabilities is
specific to the version of the Linux kernel that's in use. The 2.6
and upper kernel versions include a *driver model* framework that has
no analogue on earlier kernels; so those parts of the gadget API are
not fully portable. (They are implemented on 2.4 kernels, but in a
different way.) The driver model state is another part of this API that is
ignored by the kerneldoc tools.
The core API does not expose every possible hardware feature, only the
most widely available ones. There are significant hardware features,
such as device-to-device DMA (without temporary storage in a memory
buffer) that would be added using hardware-specific APIs.
This API allows drivers to use conditional compilation to handle
endpoint capabilities of different hardware, but doesn't require that.
Hardware tends to have arbitrary restrictions, relating to transfer
types, addressing, packet sizes, buffering, and availability. As a rule,
such differences only matter for "endpoint zero" logic that handles
device configuration and management. The API supports limited run-time
detection of capabilities, through naming conventions for endpoints.
Many drivers will be able to at least partially autoconfigure
themselves. In particular, driver init sections will often have endpoint
autoconfiguration logic that scans the hardware's list of endpoints to
find ones matching the driver requirements (relying on those
conventions), to eliminate some of the most common reasons for
conditional compilation.
Like the Linux-USB host side API, this API exposes the "chunky" nature
of USB messages: I/O requests are in terms of one or more "packets", and
packet boundaries are visible to drivers. Compared to RS-232 serial
protocols, USB resembles synchronous protocols like HDLC (N bytes per
frame, multipoint addressing, host as the primary station and devices as
secondary stations) more than asynchronous ones (tty style: 8 data bits
per frame, no parity, one stop bit). So for example the controller
drivers won't buffer two single byte writes into a single two-byte USB
IN packet, although gadget drivers may do so when they implement
protocols where packet boundaries (and "short packets") are not
significant.
Driver Life Cycle
-----------------
Gadget drivers make endpoint I/O requests to hardware without needing to
know many details of the hardware, but driver setup/configuration code
needs to handle some differences. Use the API like this:
1. Register a driver for the particular device side usb controller
hardware, such as the net2280 on PCI (USB 2.0), sa11x0 or pxa25x as
found in Linux PDAs, and so on. At this point the device is logically
in the USB ch9 initial state (``attached``), drawing no power and not
usable (since it does not yet support enumeration). Any host should
not see the device, since it's not activated the data line pullup
used by the host to detect a device, even if VBUS power is available.
2. Register a gadget driver that implements some higher level device
function. That will then bind() to a :c:type:`usb_gadget`, which activates
the data line pullup sometime after detecting VBUS.
3. The hardware driver can now start enumerating. The steps it handles
are to accept USB ``power`` and ``set_address`` requests. Other steps are
handled by the gadget driver. If the gadget driver module is unloaded
before the host starts to enumerate, steps before step 7 are skipped.
4. The gadget driver's ``setup()`` call returns usb descriptors, based both
on what the bus interface hardware provides and on the functionality
being implemented. That can involve alternate settings or
configurations, unless the hardware prevents such operation. For OTG
devices, each configuration descriptor includes an OTG descriptor.
5. The gadget driver handles the last step of enumeration, when the USB
host issues a ``set_configuration`` call. It enables all endpoints used
in that configuration, with all interfaces in their default settings.
That involves using a list of the hardware's endpoints, enabling each
endpoint according to its descriptor. It may also involve using
``usb_gadget_vbus_draw`` to let more power be drawn from VBUS, as
allowed by that configuration. For OTG devices, setting a
configuration may also involve reporting HNP capabilities through a
user interface.
6. Do real work and perform data transfers, possibly involving changes
to interface settings or switching to new configurations, until the
device is disconnect()ed from the host. Queue any number of transfer
requests to each endpoint. It may be suspended and resumed several
times before being disconnected. On disconnect, the drivers go back
to step 3 (above).
7. When the gadget driver module is being unloaded, the driver unbind()
callback is issued. That lets the controller driver be unloaded.
Drivers will normally be arranged so that just loading the gadget driver
module (or statically linking it into a Linux kernel) allows the
peripheral device to be enumerated, but some drivers will defer
enumeration until some higher level component (like a user mode daemon)
enables it. Note that at this lowest level there are no policies about
how ep0 configuration logic is implemented, except that it should obey
USB specifications. Such issues are in the domain of gadget drivers,
including knowing about implementation constraints imposed by some USB
controllers or understanding that composite devices might happen to be
built by integrating reusable components.
Note that the lifecycle above can be slightly different for OTG devices.
Other than providing an additional OTG descriptor in each configuration,
only the HNP-related differences are particularly visible to driver
code. They involve reporting requirements during the ``SET_CONFIGURATION``
request, and the option to invoke HNP during some suspend callbacks.
Also, SRP changes the semantics of ``usb_gadget_wakeup`` slightly.
USB 2.0 Chapter 9 Types and Constants
-------------------------------------
Gadget drivers rely on common USB structures and constants defined in
the :ref:`linux/usb/ch9.h <usb_chapter9>` header file, which is standard in
Linux 2.6+ kernels. These are the same types and constants used by host side
drivers (and usbcore).
Core Objects and Methods
------------------------
These are declared in ``<linux/usb/gadget.h>``, and are used by gadget
drivers to interact with USB peripheral controller drivers.
.. kernel-doc:: include/linux/usb/gadget.h
:internal:
Optional Utilities
------------------
The core API is sufficient for writing a USB Gadget Driver, but some
optional utilities are provided to simplify common tasks. These
utilities include endpoint autoconfiguration.
.. kernel-doc:: drivers/usb/gadget/usbstring.c
:export:
.. kernel-doc:: drivers/usb/gadget/config.c
:export:
Composite Device Framework
--------------------------
The core API is sufficient for writing drivers for composite USB devices
(with more than one function in a given configuration), and also
multi-configuration devices (also more than one function, but not
necessarily sharing a given configuration). There is however an optional
framework which makes it easier to reuse and combine functions.
Devices using this framework provide a struct usb_composite_driver,
which in turn provides one or more struct usb_configuration
instances. Each such configuration includes at least one struct
:c:type:`usb_function`, which packages a user visible role such as "network
link" or "mass storage device". Management functions may also exist,
such as "Device Firmware Upgrade".
.. kernel-doc:: include/linux/usb/composite.h
:internal:
.. kernel-doc:: drivers/usb/gadget/composite.c
:export:
Composite Device Functions
--------------------------
At this writing, a few of the current gadget drivers have been converted
to this framework. Near-term plans include converting all of them,
except for ``gadgetfs``.
Peripheral Controller Drivers
=============================
The first hardware supporting this API was the NetChip 2280 controller,
which supports USB 2.0 high speed and is based on PCI. This is the
``net2280`` driver module. The driver supports Linux kernel versions 2.4
and 2.6; contact NetChip Technologies for development boards and product
information.
Other hardware working in the ``gadget`` framework includes: Intel's PXA
25x and IXP42x series processors (``pxa2xx_udc``), Toshiba TC86c001
"Goku-S" (``goku_udc``), Renesas SH7705/7727 (``sh_udc``), MediaQ 11xx
(``mq11xx_udc``), Hynix HMS30C7202 (``h7202_udc``), National 9303/4
(``n9604_udc``), Texas Instruments OMAP (``omap_udc``), Sharp LH7A40x
(``lh7a40x_udc``), and more. Most of those are full speed controllers.
At this writing, there are people at work on drivers in this framework
for several other USB device controllers, with plans to make many of
them be widely available.
A partial USB simulator, the ``dummy_hcd`` driver, is available. It can
act like a net2280, a pxa25x, or an sa11x0 in terms of available
endpoints and device speeds; and it simulates control, bulk, and to some
extent interrupt transfers. That lets you develop some parts of a gadget
driver on a normal PC, without any special hardware, and perhaps with
the assistance of tools such as GDB running with User Mode Linux. At
least one person has expressed interest in adapting that approach,
hooking it up to a simulator for a microcontroller. Such simulators can
help debug subsystems where the runtime hardware is unfriendly to
software development, or is not yet available.
Support for other controllers is expected to be developed and
contributed over time, as this driver framework evolves.
Gadget Drivers
==============
In addition to *Gadget Zero* (used primarily for testing and development
with drivers for usb controller hardware), other gadget drivers exist.
There's an ``ethernet`` gadget driver, which implements one of the most
useful *Communications Device Class* (CDC) models. One of the standards
for cable modem interoperability even specifies the use of this ethernet
model as one of two mandatory options. Gadgets using this code look to a
USB host as if they're an Ethernet adapter. It provides access to a
network where the gadget's CPU is one host, which could easily be
bridging, routing, or firewalling access to other networks. Since some
hardware can't fully implement the CDC Ethernet requirements, this
driver also implements a "good parts only" subset of CDC Ethernet. (That
subset doesn't advertise itself as CDC Ethernet, to avoid creating
problems.)
Support for Microsoft's ``RNDIS`` protocol has been contributed by
Pengutronix and Auerswald GmbH. This is like CDC Ethernet, but it runs
on more slightly USB hardware (but less than the CDC subset). However,
its main claim to fame is being able to connect directly to recent
versions of Windows, using drivers that Microsoft bundles and supports,
making it much simpler to network with Windows.
There is also support for user mode gadget drivers, using ``gadgetfs``.
This provides a *User Mode API* that presents each endpoint as a single
file descriptor. I/O is done using normal ``read()`` and ``read()`` calls.
Familiar tools like GDB and pthreads can be used to develop and debug
user mode drivers, so that once a robust controller driver is available
many applications for it won't require new kernel mode software. Linux
2.6 *Async I/O (AIO)* support is available, so that user mode software
can stream data with only slightly more overhead than a kernel driver.
There's a USB Mass Storage class driver, which provides a different
solution for interoperability with systems such as MS-Windows and MacOS.
That *Mass Storage* driver uses a file or block device as backing store
for a drive, like the ``loop`` driver. The USB host uses the BBB, CB, or
CBI versions of the mass storage class specification, using transparent
SCSI commands to access the data from the backing store.
There's a "serial line" driver, useful for TTY style operation over USB.
The latest version of that driver supports CDC ACM style operation, like
a USB modem, and so on most hardware it can interoperate easily with
MS-Windows. One interesting use of that driver is in boot firmware (like
a BIOS), which can sometimes use that model with very small systems
without real serial lines.
Support for other kinds of gadget is expected to be developed and
contributed over time, as this driver framework evolves.
USB On-The-GO (OTG)
===================
USB OTG support on Linux 2.6 was initially developed by Texas
Instruments for `OMAP <http://www.omap.com>`__ 16xx and 17xx series
processors. Other OTG systems should work in similar ways, but the
hardware level details could be very different.
Systems need specialized hardware support to implement OTG, notably
including a special *Mini-AB* jack and associated transceiver to support
*Dual-Role* operation: they can act either as a host, using the standard
Linux-USB host side driver stack, or as a peripheral, using this
``gadget`` framework. To do that, the system software relies on small
additions to those programming interfaces, and on a new internal
component (here called an "OTG Controller") affecting which driver stack
connects to the OTG port. In each role, the system can reuse the
existing pool of hardware-neutral drivers, layered on top of the
controller driver interfaces (:c:type:`usb_bus` or :c:type:`usb_gadget`).
Such drivers need at most minor changes, and most of the calls added to
support OTG can also benefit non-OTG products.
- Gadget drivers test the ``is_otg`` flag, and use it to determine
whether or not to include an OTG descriptor in each of their
configurations.
- Gadget drivers may need changes to support the two new OTG protocols,
exposed in new gadget attributes such as ``b_hnp_enable`` flag. HNP
support should be reported through a user interface (two LEDs could
suffice), and is triggered in some cases when the host suspends the
peripheral. SRP support can be user-initiated just like remote
wakeup, probably by pressing the same button.
- On the host side, USB device drivers need to be taught to trigger HNP
at appropriate moments, using ``usb_suspend_device()``. That also
conserves battery power, which is useful even for non-OTG
configurations.
- Also on the host side, a driver must support the OTG "Targeted
Peripheral List". That's just a whitelist, used to reject peripherals
not supported with a given Linux OTG host. *This whitelist is
product-specific; each product must modify* ``otg_whitelist.h`` *to
match its interoperability specification.*
Non-OTG Linux hosts, like PCs and workstations, normally have some
solution for adding drivers, so that peripherals that aren't
recognized can eventually be supported. That approach is unreasonable
for consumer products that may never have their firmware upgraded,
and where it's usually unrealistic to expect traditional
PC/workstation/server kinds of support model to work. For example,
it's often impractical to change device firmware once the product has
been distributed, so driver bugs can't normally be fixed if they're
found after shipment.
Additional changes are needed below those hardware-neutral :c:type:`usb_bus`
and :c:type:`usb_gadget` driver interfaces; those aren't discussed here in any
detail. Those affect the hardware-specific code for each USB Host or
Peripheral controller, and how the HCD initializes (since OTG can be
active only on a single port). They also involve what may be called an
*OTG Controller Driver*, managing the OTG transceiver and the OTG state
machine logic as well as much of the root hub behavior for the OTG port.
The OTG controller driver needs to activate and deactivate USB
controllers depending on the relevant device role. Some related changes
were needed inside usbcore, so that it can identify OTG-capable devices
and respond appropriately to HNP or SRP protocols.
@@ -0,0 +1,154 @@
USB hotplugging
~~~~~~~~~~~~~~~
Linux Hotplugging
=================
In hotpluggable buses like USB (and Cardbus PCI), end-users plug devices
into the bus with power on. In most cases, users expect the devices to become
immediately usable. That means the system must do many things, including:
- Find a driver that can handle the device. That may involve
loading a kernel module; newer drivers can use module-init-tools
to publish their device (and class) support to user utilities.
- Bind a driver to that device. Bus frameworks do that using a
device driver's probe() routine.
- Tell other subsystems to configure the new device. Print
queues may need to be enabled, networks brought up, disk
partitions mounted, and so on. In some cases these will
be driver-specific actions.
This involves a mix of kernel mode and user mode actions. Making devices
be immediately usable means that any user mode actions can't wait for an
administrator to do them: the kernel must trigger them, either passively
(triggering some monitoring daemon to invoke a helper program) or
actively (calling such a user mode helper program directly).
Those triggered actions must support a system's administrative policies;
such programs are called "policy agents" here. Typically they involve
shell scripts that dispatch to more familiar administration tools.
Because some of those actions rely on information about drivers (metadata)
that is currently available only when the drivers are dynamically linked,
you get the best hotplugging when you configure a highly modular system.
Kernel Hotplug Helper (``/sbin/hotplug``)
=========================================
There is a kernel parameter: ``/proc/sys/kernel/hotplug``, which normally
holds the pathname ``/sbin/hotplug``. That parameter names a program
which the kernel may invoke at various times.
The /sbin/hotplug program can be invoked by any subsystem as part of its
reaction to a configuration change, from a thread in that subsystem.
Only one parameter is required: the name of a subsystem being notified of
some kernel event. That name is used as the first key for further event
dispatch; any other argument and environment parameters are specified by
the subsystem making that invocation.
Hotplug software and other resources is available at:
http://linux-hotplug.sourceforge.net
Mailing list information is also available at that site.
USB Policy Agent
================
The USB subsystem currently invokes ``/sbin/hotplug`` when USB devices
are added or removed from system. The invocation is done by the kernel
hub workqueue [hub_wq], or else as part of root hub initialization
(done by init, modprobe, kapmd, etc). Its single command line parameter
is the string "usb", and it passes these environment variables:
========== ============================================
ACTION ``add``, ``remove``
PRODUCT USB vendor, product, and version codes (hex)
TYPE device class codes (decimal)
INTERFACE interface 0 class codes (decimal)
========== ============================================
If "usbdevfs" is configured, DEVICE and DEVFS are also passed. DEVICE is
the pathname of the device, and is useful for devices with multiple and/or
alternate interfaces that complicate driver selection. By design, USB
hotplugging is independent of ``usbdevfs``: you can do most essential parts
of USB device setup without using that filesystem, and without running a
user mode daemon to detect changes in system configuration.
Currently available policy agent implementations can load drivers for
modules, and can invoke driver-specific setup scripts. The newest ones
leverage USB module-init-tools support. Later agents might unload drivers.
USB Modutils Support
====================
Current versions of module-init-tools will create a ``modules.usbmap`` file
which contains the entries from each driver's ``MODULE_DEVICE_TABLE``. Such
files can be used by various user mode policy agents to make sure all the
right driver modules get loaded, either at boot time or later.
See ``linux/usb.h`` for full information about such table entries; or look
at existing drivers. Each table entry describes one or more criteria to
be used when matching a driver to a device or class of devices. The
specific criteria are identified by bits set in "match_flags", paired
with field values. You can construct the criteria directly, or with
macros such as these, and use driver_info to store more information::
USB_DEVICE (vendorId, productId)
... matching devices with specified vendor and product ids
USB_DEVICE_VER (vendorId, productId, lo, hi)
... like USB_DEVICE with lo <= productversion <= hi
USB_INTERFACE_INFO (class, subclass, protocol)
... matching specified interface class info
USB_DEVICE_INFO (class, subclass, protocol)
... matching specified device class info
A short example, for a driver that supports several specific USB devices
and their quirks, might have a MODULE_DEVICE_TABLE like this::
static const struct usb_device_id mydriver_id_table[] = {
{ USB_DEVICE (0x9999, 0xaaaa), driver_info: QUIRK_X },
{ USB_DEVICE (0xbbbb, 0x8888), driver_info: QUIRK_Y|QUIRK_Z },
...
{ } /* end with an all-zeroes entry */
};
MODULE_DEVICE_TABLE(usb, mydriver_id_table);
Most USB device drivers should pass these tables to the USB subsystem as
well as to the module management subsystem. Not all, though: some driver
frameworks connect using interfaces layered over USB, and so they won't
need such a struct usb_driver.
Drivers that connect directly to the USB subsystem should be declared
something like this::
static struct usb_driver mydriver = {
.name = "mydriver",
.id_table = mydriver_id_table,
.probe = my_probe,
.disconnect = my_disconnect,
/*
if using the usb chardev framework:
.minor = MY_USB_MINOR_START,
.fops = my_file_ops,
if exposing any operations through usbdevfs:
.ioctl = my_ioctl,
*/
};
When the USB subsystem knows about a driver's device ID table, it's used when
choosing drivers to probe(). The thread doing new device processing checks
drivers' device ID entries from the ``MODULE_DEVICE_TABLE`` against interface
and device descriptors for the device. It will only call ``probe()`` if there
is a match, and the third argument to ``probe()`` will be the entry that
matched.
If you don't provide an ``id_table`` for your driver, then your driver may get
probed for each new device; the third parameter to ``probe()`` will be
``NULL``.
@@ -0,0 +1,24 @@
=============
Linux USB API
=============
.. toctree::
:maxdepth: 1
usb
gadget
anchors
bulk-streams
callbacks
dma
URB
power-management
hotplug
persist
error-codes
writing_usb_driver
dwc3
writing_musb_glue_layer
typec
typec_bus
usb3-debug-port
@@ -0,0 +1,171 @@
.. _usb-persist:
USB device persistence during system suspend
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:Author: Alan Stern <stern@rowland.harvard.edu>
:Date: September 2, 2006 (Updated February 25, 2008)
What is the problem?
====================
According to the USB specification, when a USB bus is suspended the
bus must continue to supply suspend current (around 1-5 mA). This
is so that devices can maintain their internal state and hubs can
detect connect-change events (devices being plugged in or unplugged).
The technical term is "power session".
If a USB device's power session is interrupted then the system is
required to behave as though the device has been unplugged. It's a
conservative approach; in the absence of suspend current the computer
has no way to know what has actually happened. Perhaps the same
device is still attached or perhaps it was removed and a different
device plugged into the port. The system must assume the worst.
By default, Linux behaves according to the spec. If a USB host
controller loses power during a system suspend, then when the system
wakes up all the devices attached to that controller are treated as
though they had disconnected. This is always safe and it is the
"officially correct" thing to do.
For many sorts of devices this behavior doesn't matter in the least.
If the kernel wants to believe that your USB keyboard was unplugged
while the system was asleep and a new keyboard was plugged in when the
system woke up, who cares? It'll still work the same when you type on
it.
Unfortunately problems _can_ arise, particularly with mass-storage
devices. The effect is exactly the same as if the device really had
been unplugged while the system was suspended. If you had a mounted
filesystem on the device, you're out of luck -- everything in that
filesystem is now inaccessible. This is especially annoying if your
root filesystem was located on the device, since your system will
instantly crash.
Loss of power isn't the only mechanism to worry about. Anything that
interrupts a power session will have the same effect. For example,
even though suspend current may have been maintained while the system
was asleep, on many systems during the initial stages of wakeup the
firmware (i.e., the BIOS) resets the motherboard's USB host
controllers. Result: all the power sessions are destroyed and again
it's as though you had unplugged all the USB devices. Yes, it's
entirely the BIOS's fault, but that doesn't do _you_ any good unless
you can convince the BIOS supplier to fix the problem (lots of luck!).
On many systems the USB host controllers will get reset after a
suspend-to-RAM. On almost all systems, no suspend current is
available during hibernation (also known as swsusp or suspend-to-disk).
You can check the kernel log after resuming to see if either of these
has happened; look for lines saying "root hub lost power or was reset".
In practice, people are forced to unmount any filesystems on a USB
device before suspending. If the root filesystem is on a USB device,
the system can't be suspended at all. (All right, it _can_ be
suspended -- but it will crash as soon as it wakes up, which isn't
much better.)
What is the solution?
=====================
The kernel includes a feature called USB-persist. It tries to work
around these issues by allowing the core USB device data structures to
persist across a power-session disruption.
It works like this. If the kernel sees that a USB host controller is
not in the expected state during resume (i.e., if the controller was
reset or otherwise had lost power) then it applies a persistence check
to each of the USB devices below that controller for which the
"persist" attribute is set. It doesn't try to resume the device; that
can't work once the power session is gone. Instead it issues a USB
port reset and then re-enumerates the device. (This is exactly the
same thing that happens whenever a USB device is reset.) If the
re-enumeration shows that the device now attached to that port has the
same descriptors as before, including the Vendor and Product IDs, then
the kernel continues to use the same device structure. In effect, the
kernel treats the device as though it had merely been reset instead of
unplugged.
The same thing happens if the host controller is in the expected state
but a USB device was unplugged and then replugged, or if a USB device
fails to carry out a normal resume.
If no device is now attached to the port, or if the descriptors are
different from what the kernel remembers, then the treatment is what
you would expect. The kernel destroys the old device structure and
behaves as though the old device had been unplugged and a new device
plugged in.
The end result is that the USB device remains available and usable.
Filesystem mounts and memory mappings are unaffected, and the world is
now a good and happy place.
Note that the "USB-persist" feature will be applied only to those
devices for which it is enabled. You can enable the feature by doing
(as root)::
echo 1 >/sys/bus/usb/devices/.../power/persist
where the "..." should be filled in the with the device's ID. Disable
the feature by writing 0 instead of 1. For hubs the feature is
automatically and permanently enabled and the power/persist file
doesn't even exist, so you only have to worry about setting it for
devices where it really matters.
Is this the best solution?
==========================
Perhaps not. Arguably, keeping track of mounted filesystems and
memory mappings across device disconnects should be handled by a
centralized Logical Volume Manager. Such a solution would allow you
to plug in a USB flash device, create a persistent volume associated
with it, unplug the flash device, plug it back in later, and still
have the same persistent volume associated with the device. As such
it would be more far-reaching than USB-persist.
On the other hand, writing a persistent volume manager would be a big
job and using it would require significant input from the user. This
solution is much quicker and easier -- and it exists now, a giant
point in its favor!
Furthermore, the USB-persist feature applies to _all_ USB devices, not
just mass-storage devices. It might turn out to be equally useful for
other device types, such as network interfaces.
WARNING: USB-persist can be dangerous!!
=======================================
When recovering an interrupted power session the kernel does its best
to make sure the USB device hasn't been changed; that is, the same
device is still plugged into the port as before. But the checks
aren't guaranteed to be 100% accurate.
If you replace one USB device with another of the same type (same
manufacturer, same IDs, and so on) there's an excellent chance the
kernel won't detect the change. The serial number string and other
descriptors are compared with the kernel's stored values, but this
might not help since manufacturers frequently omit serial numbers
entirely in their devices.
Furthermore it's quite possible to leave a USB device exactly the same
while changing its media. If you replace the flash memory card in a
USB card reader while the system is asleep, the kernel will have no
way to know you did it. The kernel will assume that nothing has
happened and will continue to use the partition tables, inodes, and
memory mappings for the old card.
If the kernel gets fooled in this way, it's almost certain to cause
data corruption and to crash your system. You'll have no one to blame
but yourself.
For those devices with avoid_reset_quirk attribute being set, persist
maybe fail because they may morph after reset.
YOU HAVE BEEN WARNED! USE AT YOUR OWN RISK!
That having been said, most of the time there shouldn't be any trouble
at all. The USB-persist feature can be extremely useful. Make the
most of it.
@@ -0,0 +1,798 @@
.. _usb-power-management:
Power Management for USB
~~~~~~~~~~~~~~~~~~~~~~~~
:Author: Alan Stern <stern@rowland.harvard.edu>
:Date: Last-updated: February 2014
..
Contents:
---------
* What is Power Management?
* What is Remote Wakeup?
* When is a USB device idle?
* Forms of dynamic PM
* The user interface for dynamic PM
* Changing the default idle-delay time
* Warnings
* The driver interface for Power Management
* The driver interface for autosuspend and autoresume
* Other parts of the driver interface
* Mutual exclusion
* Interaction between dynamic PM and system PM
* xHCI hardware link PM
* USB Port Power Control
* User Interface for Port Power Control
* Suggested Userspace Port Power Policy
What is Power Management?
-------------------------
Power Management (PM) is the practice of saving energy by suspending
parts of a computer system when they aren't being used. While a
component is ``suspended`` it is in a nonfunctional low-power state; it
might even be turned off completely. A suspended component can be
``resumed`` (returned to a functional full-power state) when the kernel
needs to use it. (There also are forms of PM in which components are
placed in a less functional but still usable state instead of being
suspended; an example would be reducing the CPU's clock rate. This
document will not discuss those other forms.)
When the parts being suspended include the CPU and most of the rest of
the system, we speak of it as a "system suspend". When a particular
device is turned off while the system as a whole remains running, we
call it a "dynamic suspend" (also known as a "runtime suspend" or
"selective suspend"). This document concentrates mostly on how
dynamic PM is implemented in the USB subsystem, although system PM is
covered to some extent (see ``Documentation/power/*.rst`` for more
information about system PM).
System PM support is present only if the kernel was built with
``CONFIG_SUSPEND`` or ``CONFIG_HIBERNATION`` enabled. Dynamic PM support
for USB is present whenever
the kernel was built with ``CONFIG_PM`` enabled.
[Historically, dynamic PM support for USB was present only if the
kernel had been built with ``CONFIG_USB_SUSPEND`` enabled (which depended on
``CONFIG_PM_RUNTIME``). Starting with the 3.10 kernel release, dynamic PM
support for USB was present whenever the kernel was built with
``CONFIG_PM_RUNTIME`` enabled. The ``CONFIG_USB_SUSPEND`` option had been
eliminated.]
What is Remote Wakeup?
----------------------
When a device has been suspended, it generally doesn't resume until
the computer tells it to. Likewise, if the entire computer has been
suspended, it generally doesn't resume until the user tells it to, say
by pressing a power button or opening the cover.
However some devices have the capability of resuming by themselves, or
asking the kernel to resume them, or even telling the entire computer
to resume. This capability goes by several names such as "Wake On
LAN"; we will refer to it generically as "remote wakeup". When a
device is enabled for remote wakeup and it is suspended, it may resume
itself (or send a request to be resumed) in response to some external
event. Examples include a suspended keyboard resuming when a key is
pressed, or a suspended USB hub resuming when a device is plugged in.
When is a USB device idle?
--------------------------
A device is idle whenever the kernel thinks it's not busy doing
anything important and thus is a candidate for being suspended. The
exact definition depends on the device's driver; drivers are allowed
to declare that a device isn't idle even when there's no actual
communication taking place. (For example, a hub isn't considered idle
unless all the devices plugged into that hub are already suspended.)
In addition, a device isn't considered idle so long as a program keeps
its usbfs file open, whether or not any I/O is going on.
If a USB device has no driver, its usbfs file isn't open, and it isn't
being accessed through sysfs, then it definitely is idle.
Forms of dynamic PM
-------------------
Dynamic suspends occur when the kernel decides to suspend an idle
device. This is called ``autosuspend`` for short. In general, a device
won't be autosuspended unless it has been idle for some minimum period
of time, the so-called idle-delay time.
Of course, nothing the kernel does on its own initiative should
prevent the computer or its devices from working properly. If a
device has been autosuspended and a program tries to use it, the
kernel will automatically resume the device (autoresume). For the
same reason, an autosuspended device will usually have remote wakeup
enabled, if the device supports remote wakeup.
It is worth mentioning that many USB drivers don't support
autosuspend. In fact, at the time of this writing (Linux 2.6.23) the
only drivers which do support it are the hub driver, kaweth, asix,
usblp, usblcd, and usb-skeleton (which doesn't count). If a
non-supporting driver is bound to a device, the device won't be
autosuspended. In effect, the kernel pretends the device is never
idle.
We can categorize power management events in two broad classes:
external and internal. External events are those triggered by some
agent outside the USB stack: system suspend/resume (triggered by
userspace), manual dynamic resume (also triggered by userspace), and
remote wakeup (triggered by the device). Internal events are those
triggered within the USB stack: autosuspend and autoresume. Note that
all dynamic suspend events are internal; external agents are not
allowed to issue dynamic suspends.
The user interface for dynamic PM
---------------------------------
The user interface for controlling dynamic PM is located in the ``power/``
subdirectory of each USB device's sysfs directory, that is, in
``/sys/bus/usb/devices/.../power/`` where "..." is the device's ID. The
relevant attribute files are: wakeup, control, and
``autosuspend_delay_ms``. (There may also be a file named ``level``; this
file was deprecated as of the 2.6.35 kernel and replaced by the
``control`` file. In 2.6.38 the ``autosuspend`` file will be deprecated
and replaced by the ``autosuspend_delay_ms`` file. The only difference
is that the newer file expresses the delay in milliseconds whereas the
older file uses seconds. Confusingly, both files are present in 2.6.37
but only ``autosuspend`` works.)
``power/wakeup``
This file is empty if the device does not support
remote wakeup. Otherwise the file contains either the
word ``enabled`` or the word ``disabled``, and you can
write those words to the file. The setting determines
whether or not remote wakeup will be enabled when the
device is next suspended. (If the setting is changed
while the device is suspended, the change won't take
effect until the following suspend.)
``power/control``
This file contains one of two words: ``on`` or ``auto``.
You can write those words to the file to change the
device's setting.
- ``on`` means that the device should be resumed and
autosuspend is not allowed. (Of course, system
suspends are still allowed.)
- ``auto`` is the normal state in which the kernel is
allowed to autosuspend and autoresume the device.
(In kernels up to 2.6.32, you could also specify
``suspend``, meaning that the device should remain
suspended and autoresume was not allowed. This
setting is no longer supported.)
``power/autosuspend_delay_ms``
This file contains an integer value, which is the
number of milliseconds the device should remain idle
before the kernel will autosuspend it (the idle-delay
time). The default is 2000. 0 means to autosuspend
as soon as the device becomes idle, and negative
values mean never to autosuspend. You can write a
number to the file to change the autosuspend
idle-delay time.
Writing ``-1`` to ``power/autosuspend_delay_ms`` and writing ``on`` to
``power/control`` do essentially the same thing -- they both prevent the
device from being autosuspended. Yes, this is a redundancy in the
API.
(In 2.6.21 writing ``0`` to ``power/autosuspend`` would prevent the device
from being autosuspended; the behavior was changed in 2.6.22. The
``power/autosuspend`` attribute did not exist prior to 2.6.21, and the
``power/level`` attribute did not exist prior to 2.6.22. ``power/control``
was added in 2.6.34, and ``power/autosuspend_delay_ms`` was added in
2.6.37 but did not become functional until 2.6.38.)
Changing the default idle-delay time
------------------------------------
The default autosuspend idle-delay time (in seconds) is controlled by
a module parameter in usbcore. You can specify the value when usbcore
is loaded. For example, to set it to 5 seconds instead of 2 you would
do::
modprobe usbcore autosuspend=5
Equivalently, you could add to a configuration file in /etc/modprobe.d
a line saying::
options usbcore autosuspend=5
Some distributions load the usbcore module very early during the boot
process, by means of a program or script running from an initramfs
image. To alter the parameter value you would have to rebuild that
image.
If usbcore is compiled into the kernel rather than built as a loadable
module, you can add::
usbcore.autosuspend=5
to the kernel's boot command line.
Finally, the parameter value can be changed while the system is
running. If you do::
echo 5 >/sys/module/usbcore/parameters/autosuspend
then each new USB device will have its autosuspend idle-delay
initialized to 5. (The idle-delay values for already existing devices
will not be affected.)
Setting the initial default idle-delay to -1 will prevent any
autosuspend of any USB device. This has the benefit of allowing you
then to enable autosuspend for selected devices.
Warnings
--------
The USB specification states that all USB devices must support power
management. Nevertheless, the sad fact is that many devices do not
support it very well. You can suspend them all right, but when you
try to resume them they disconnect themselves from the USB bus or
they stop working entirely. This seems to be especially prevalent
among printers and scanners, but plenty of other types of device have
the same deficiency.
For this reason, by default the kernel disables autosuspend (the
``power/control`` attribute is initialized to ``on``) for all devices other
than hubs. Hubs, at least, appear to be reasonably well-behaved in
this regard.
(In 2.6.21 and 2.6.22 this wasn't the case. Autosuspend was enabled
by default for almost all USB devices. A number of people experienced
problems as a result.)
This means that non-hub devices won't be autosuspended unless the user
or a program explicitly enables it. As of this writing there aren't
any widespread programs which will do this; we hope that in the near
future device managers such as HAL will take on this added
responsibility. In the meantime you can always carry out the
necessary operations by hand or add them to a udev script. You can
also change the idle-delay time; 2 seconds is not the best choice for
every device.
If a driver knows that its device has proper suspend/resume support,
it can enable autosuspend all by itself. For example, the video
driver for a laptop's webcam might do this (in recent kernels they
do), since these devices are rarely used and so should normally be
autosuspended.
Sometimes it turns out that even when a device does work okay with
autosuspend there are still problems. For example, the usbhid driver,
which manages keyboards and mice, has autosuspend support. Tests with
a number of keyboards show that typing on a suspended keyboard, while
causing the keyboard to do a remote wakeup all right, will nonetheless
frequently result in lost keystrokes. Tests with mice show that some
of them will issue a remote-wakeup request in response to button
presses but not to motion, and some in response to neither.
The kernel will not prevent you from enabling autosuspend on devices
that can't handle it. It is even possible in theory to damage a
device by suspending it at the wrong time. (Highly unlikely, but
possible.) Take care.
The driver interface for Power Management
-----------------------------------------
The requirements for a USB driver to support external power management
are pretty modest; the driver need only define::
.suspend
.resume
.reset_resume
methods in its :c:type:`usb_driver` structure, and the ``reset_resume`` method
is optional. The methods' jobs are quite simple:
- The ``suspend`` method is called to warn the driver that the
device is going to be suspended. If the driver returns a
negative error code, the suspend will be aborted. Normally
the driver will return 0, in which case it must cancel all
outstanding URBs (:c:func:`usb_kill_urb`) and not submit any more.
- The ``resume`` method is called to tell the driver that the
device has been resumed and the driver can return to normal
operation. URBs may once more be submitted.
- The ``reset_resume`` method is called to tell the driver that
the device has been resumed and it also has been reset.
The driver should redo any necessary device initialization,
since the device has probably lost most or all of its state
(although the interfaces will be in the same altsettings as
before the suspend).
If the device is disconnected or powered down while it is suspended,
the ``disconnect`` method will be called instead of the ``resume`` or
``reset_resume`` method. This is also quite likely to happen when
waking up from hibernation, as many systems do not maintain suspend
current to the USB host controllers during hibernation. (It's
possible to work around the hibernation-forces-disconnect problem by
using the USB Persist facility.)
The ``reset_resume`` method is used by the USB Persist facility (see
:ref:`usb-persist`) and it can also be used under certain
circumstances when ``CONFIG_USB_PERSIST`` is not enabled. Currently, if a
device is reset during a resume and the driver does not have a
``reset_resume`` method, the driver won't receive any notification about
the resume. Later kernels will call the driver's ``disconnect`` method;
2.6.23 doesn't do this.
USB drivers are bound to interfaces, so their ``suspend`` and ``resume``
methods get called when the interfaces are suspended or resumed. In
principle one might want to suspend some interfaces on a device (i.e.,
force the drivers for those interface to stop all activity) without
suspending the other interfaces. The USB core doesn't allow this; all
interfaces are suspended when the device itself is suspended and all
interfaces are resumed when the device is resumed. It isn't possible
to suspend or resume some but not all of a device's interfaces. The
closest you can come is to unbind the interfaces' drivers.
The driver interface for autosuspend and autoresume
---------------------------------------------------
To support autosuspend and autoresume, a driver should implement all
three of the methods listed above. In addition, a driver indicates
that it supports autosuspend by setting the ``.supports_autosuspend`` flag
in its usb_driver structure. It is then responsible for informing the
USB core whenever one of its interfaces becomes busy or idle. The
driver does so by calling these six functions::
int usb_autopm_get_interface(struct usb_interface *intf);
void usb_autopm_put_interface(struct usb_interface *intf);
int usb_autopm_get_interface_async(struct usb_interface *intf);
void usb_autopm_put_interface_async(struct usb_interface *intf);
void usb_autopm_get_interface_no_resume(struct usb_interface *intf);
void usb_autopm_put_interface_no_suspend(struct usb_interface *intf);
The functions work by maintaining a usage counter in the
usb_interface's embedded device structure. When the counter is > 0
then the interface is deemed to be busy, and the kernel will not
autosuspend the interface's device. When the usage counter is = 0
then the interface is considered to be idle, and the kernel may
autosuspend the device.
Drivers must be careful to balance their overall changes to the usage
counter. Unbalanced "get"s will remain in effect when a driver is
unbound from its interface, preventing the device from going into
runtime suspend should the interface be bound to a driver again. On
the other hand, drivers are allowed to achieve this balance by calling
the ``usb_autopm_*`` functions even after their ``disconnect`` routine
has returned -- say from within a work-queue routine -- provided they
retain an active reference to the interface (via ``usb_get_intf`` and
``usb_put_intf``).
Drivers using the async routines are responsible for their own
synchronization and mutual exclusion.
:c:func:`usb_autopm_get_interface` increments the usage counter and
does an autoresume if the device is suspended. If the
autoresume fails, the counter is decremented back.
:c:func:`usb_autopm_put_interface` decrements the usage counter and
attempts an autosuspend if the new value is = 0.
:c:func:`usb_autopm_get_interface_async` and
:c:func:`usb_autopm_put_interface_async` do almost the same things as
their non-async counterparts. The big difference is that they
use a workqueue to do the resume or suspend part of their
jobs. As a result they can be called in an atomic context,
such as an URB's completion handler, but when they return the
device will generally not yet be in the desired state.
:c:func:`usb_autopm_get_interface_no_resume` and
:c:func:`usb_autopm_put_interface_no_suspend` merely increment or
decrement the usage counter; they do not attempt to carry out
an autoresume or an autosuspend. Hence they can be called in
an atomic context.
The simplest usage pattern is that a driver calls
:c:func:`usb_autopm_get_interface` in its open routine and
:c:func:`usb_autopm_put_interface` in its close or release routine. But other
patterns are possible.
The autosuspend attempts mentioned above will often fail for one
reason or another. For example, the ``power/control`` attribute might be
set to ``on``, or another interface in the same device might not be
idle. This is perfectly normal. If the reason for failure was that
the device hasn't been idle for long enough, a timer is scheduled to
carry out the operation automatically when the autosuspend idle-delay
has expired.
Autoresume attempts also can fail, although failure would mean that
the device is no longer present or operating properly. Unlike
autosuspend, there's no idle-delay for an autoresume.
Other parts of the driver interface
-----------------------------------
Drivers can enable autosuspend for their devices by calling::
usb_enable_autosuspend(struct usb_device *udev);
in their :c:func:`probe` routine, if they know that the device is capable of
suspending and resuming correctly. This is exactly equivalent to
writing ``auto`` to the device's ``power/control`` attribute. Likewise,
drivers can disable autosuspend by calling::
usb_disable_autosuspend(struct usb_device *udev);
This is exactly the same as writing ``on`` to the ``power/control`` attribute.
Sometimes a driver needs to make sure that remote wakeup is enabled
during autosuspend. For example, there's not much point
autosuspending a keyboard if the user can't cause the keyboard to do a
remote wakeup by typing on it. If the driver sets
``intf->needs_remote_wakeup`` to 1, the kernel won't autosuspend the
device if remote wakeup isn't available. (If the device is already
autosuspended, though, setting this flag won't cause the kernel to
autoresume it. Normally a driver would set this flag in its ``probe``
method, at which time the device is guaranteed not to be
autosuspended.)
If a driver does its I/O asynchronously in interrupt context, it
should call :c:func:`usb_autopm_get_interface_async` before starting output and
:c:func:`usb_autopm_put_interface_async` when the output queue drains. When
it receives an input event, it should call::
usb_mark_last_busy(struct usb_device *udev);
in the event handler. This tells the PM core that the device was just
busy and therefore the next autosuspend idle-delay expiration should
be pushed back. Many of the usb_autopm_* routines also make this call,
so drivers need to worry only when interrupt-driven input arrives.
Asynchronous operation is always subject to races. For example, a
driver may call the :c:func:`usb_autopm_get_interface_async` routine at a time
when the core has just finished deciding the device has been idle for
long enough but not yet gotten around to calling the driver's ``suspend``
method. The ``suspend`` method must be responsible for synchronizing with
the I/O request routine and the URB completion handler; it should
cause autosuspends to fail with -EBUSY if the driver needs to use the
device.
External suspend calls should never be allowed to fail in this way,
only autosuspend calls. The driver can tell them apart by applying
the :c:func:`PMSG_IS_AUTO` macro to the message argument to the ``suspend``
method; it will return True for internal PM events (autosuspend) and
False for external PM events.
Mutual exclusion
----------------
For external events -- but not necessarily for autosuspend or
autoresume -- the device semaphore (udev->dev.sem) will be held when a
``suspend`` or ``resume`` method is called. This implies that external
suspend/resume events are mutually exclusive with calls to ``probe``,
``disconnect``, ``pre_reset``, and ``post_reset``; the USB core guarantees that
this is true of autosuspend/autoresume events as well.
If a driver wants to block all suspend/resume calls during some
critical section, the best way is to lock the device and call
:c:func:`usb_autopm_get_interface` (and do the reverse at the end of the
critical section). Holding the device semaphore will block all
external PM calls, and the :c:func:`usb_autopm_get_interface` will prevent any
internal PM calls, even if it fails. (Exercise: Why?)
Interaction between dynamic PM and system PM
--------------------------------------------
Dynamic power management and system power management can interact in
a couple of ways.
Firstly, a device may already be autosuspended when a system suspend
occurs. Since system suspends are supposed to be as transparent as
possible, the device should remain suspended following the system
resume. But this theory may not work out well in practice; over time
the kernel's behavior in this regard has changed. As of 2.6.37 the
policy is to resume all devices during a system resume and let them
handle their own runtime suspends afterward.
Secondly, a dynamic power-management event may occur as a system
suspend is underway. The window for this is short, since system
suspends don't take long (a few seconds usually), but it can happen.
For example, a suspended device may send a remote-wakeup signal while
the system is suspending. The remote wakeup may succeed, which would
cause the system suspend to abort. If the remote wakeup doesn't
succeed, it may still remain active and thus cause the system to
resume as soon as the system suspend is complete. Or the remote
wakeup may fail and get lost. Which outcome occurs depends on timing
and on the hardware and firmware design.
xHCI hardware link PM
---------------------
xHCI host controller provides hardware link power management to usb2.0
(xHCI 1.0 feature) and usb3.0 devices which support link PM. By
enabling hardware LPM, the host can automatically put the device into
lower power state(L1 for usb2.0 devices, or U1/U2 for usb3.0 devices),
which state device can enter and resume very quickly.
The user interface for controlling hardware LPM is located in the
``power/`` subdirectory of each USB device's sysfs directory, that is, in
``/sys/bus/usb/devices/.../power/`` where "..." is the device's ID. The
relevant attribute files are ``usb2_hardware_lpm`` and ``usb3_hardware_lpm``.
``power/usb2_hardware_lpm``
When a USB2 device which support LPM is plugged to a
xHCI host root hub which support software LPM, the
host will run a software LPM test for it; if the device
enters L1 state and resume successfully and the host
supports USB2 hardware LPM, this file will show up and
driver will enable hardware LPM for the device. You
can write y/Y/1 or n/N/0 to the file to enable/disable
USB2 hardware LPM manually. This is for test purpose mainly.
``power/usb3_hardware_lpm_u1``
``power/usb3_hardware_lpm_u2``
When a USB 3.0 lpm-capable device is plugged in to a
xHCI host which supports link PM, it will check if U1
and U2 exit latencies have been set in the BOS
descriptor; if the check is passed and the host
supports USB3 hardware LPM, USB3 hardware LPM will be
enabled for the device and these files will be created.
The files hold a string value (enable or disable)
indicating whether or not USB3 hardware LPM U1 or U2
is enabled for the device.
USB Port Power Control
----------------------
In addition to suspending endpoint devices and enabling hardware
controlled link power management, the USB subsystem also has the
capability to disable power to ports under some conditions. Power is
controlled through ``Set/ClearPortFeature(PORT_POWER)`` requests to a hub.
In the case of a root or platform-internal hub the host controller
driver translates ``PORT_POWER`` requests into platform firmware (ACPI)
method calls to set the port power state. For more background see the
Linux Plumbers Conference 2012 slides [#f1]_ and video [#f2]_:
Upon receiving a ``ClearPortFeature(PORT_POWER)`` request a USB port is
logically off, and may trigger the actual loss of VBUS to the port [#f3]_.
VBUS may be maintained in the case where a hub gangs multiple ports into
a shared power well causing power to remain until all ports in the gang
are turned off. VBUS may also be maintained by hub ports configured for
a charging application. In any event a logically off port will lose
connection with its device, not respond to hotplug events, and not
respond to remote wakeup events.
.. warning::
turning off a port may result in the inability to hot add a device.
Please see "User Interface for Port Power Control" for details.
As far as the effect on the device itself it is similar to what a device
goes through during system suspend, i.e. the power session is lost. Any
USB device or driver that misbehaves with system suspend will be
similarly affected by a port power cycle event. For this reason the
implementation shares the same device recovery path (and honors the same
quirks) as the system resume path for the hub.
.. [#f1]
http://dl.dropbox.com/u/96820575/sarah-sharp-lpt-port-power-off2-mini.pdf
.. [#f2]
http://linuxplumbers.ubicast.tv/videos/usb-port-power-off-kerneluserspace-api/
.. [#f3]
USB 3.1 Section 10.12
wakeup note: if a device is configured to send wakeup events the port
power control implementation will block poweroff attempts on that
port.
User Interface for Port Power Control
-------------------------------------
The port power control mechanism uses the PM runtime system. Poweroff is
requested by clearing the ``power/pm_qos_no_power_off`` flag of the port device
(defaults to 1). If the port is disconnected it will immediately receive a
``ClearPortFeature(PORT_POWER)`` request. Otherwise, it will honor the pm
runtime rules and require the attached child device and all descendants to be
suspended. This mechanism is dependent on the hub advertising port power
switching in its hub descriptor (wHubCharacteristics logical power switching
mode field).
Note, some interface devices/drivers do not support autosuspend. Userspace may
need to unbind the interface drivers before the :c:type:`usb_device` will
suspend. An unbound interface device is suspended by default. When unbinding,
be careful to unbind interface drivers, not the driver of the parent usb
device. Also, leave hub interface drivers bound. If the driver for the usb
device (not interface) is unbound the kernel is no longer able to resume the
device. If a hub interface driver is unbound, control of its child ports is
lost and all attached child-devices will disconnect. A good rule of thumb is
that if the 'driver/module' link for a device points to
``/sys/module/usbcore`` then unbinding it will interfere with port power
control.
Example of the relevant files for port power control. Note, in this example
these files are relative to a usb hub device (prefix)::
prefix=/sys/devices/pci0000:00/0000:00:14.0/usb3/3-1
attached child device +
hub port device + |
hub interface device + | |
v v v
$prefix/3-1:1.0/3-1-port1/device
$prefix/3-1:1.0/3-1-port1/power/pm_qos_no_power_off
$prefix/3-1:1.0/3-1-port1/device/power/control
$prefix/3-1:1.0/3-1-port1/device/3-1.1:<intf0>/driver/unbind
$prefix/3-1:1.0/3-1-port1/device/3-1.1:<intf1>/driver/unbind
...
$prefix/3-1:1.0/3-1-port1/device/3-1.1:<intfN>/driver/unbind
In addition to these files some ports may have a 'peer' link to a port on
another hub. The expectation is that all superspeed ports have a
hi-speed peer::
$prefix/3-1:1.0/3-1-port1/peer -> ../../../../usb2/2-1/2-1:1.0/2-1-port1
../../../../usb2/2-1/2-1:1.0/2-1-port1/peer -> ../../../../usb3/3-1/3-1:1.0/3-1-port1
Distinct from 'companion ports', or 'ehci/xhci shared switchover ports'
peer ports are simply the hi-speed and superspeed interface pins that
are combined into a single usb3 connector. Peer ports share the same
ancestor XHCI device.
While a superspeed port is powered off a device may downgrade its
connection and attempt to connect to the hi-speed pins. The
implementation takes steps to prevent this:
1. Port suspend is sequenced to guarantee that hi-speed ports are powered-off
before their superspeed peer is permitted to power-off. The implication is
that the setting ``pm_qos_no_power_off`` to zero on a superspeed port may
not cause the port to power-off until its highspeed peer has gone to its
runtime suspend state. Userspace must take care to order the suspensions
if it wants to guarantee that a superspeed port will power-off.
2. Port resume is sequenced to force a superspeed port to power-on prior to its
highspeed peer.
3. Port resume always triggers an attached child device to resume. After a
power session is lost the device may have been removed, or need reset.
Resuming the child device when the parent port regains power resolves those
states and clamps the maximum port power cycle frequency at the rate the
child device can suspend (autosuspend-delay) and resume (reset-resume
latency).
Sysfs files relevant for port power control:
``<hubdev-portX>/power/pm_qos_no_power_off``:
This writable flag controls the state of an idle port.
Once all children and descendants have suspended the
port may suspend/poweroff provided that
pm_qos_no_power_off is '0'. If pm_qos_no_power_off is
'1' the port will remain active/powered regardless of
the stats of descendants. Defaults to 1.
``<hubdev-portX>/power/runtime_status``:
This file reflects whether the port is 'active' (power is on)
or 'suspended' (logically off). There is no indication to
userspace whether VBUS is still supplied.
``<hubdev-portX>/connect_type``:
An advisory read-only flag to userspace indicating the
location and connection type of the port. It returns
one of four values 'hotplug', 'hardwired', 'not used',
and 'unknown'. All values, besides unknown, are set by
platform firmware.
``hotplug`` indicates an externally connectable/visible
port on the platform. Typically userspace would choose
to keep such a port powered to handle new device
connection events.
``hardwired`` refers to a port that is not visible but
connectable. Examples are internal ports for USB
bluetooth that can be disconnected via an external
switch or a port with a hardwired USB camera. It is
expected to be safe to allow these ports to suspend
provided pm_qos_no_power_off is coordinated with any
switch that gates connections. Userspace must arrange
for the device to be connected prior to the port
powering off, or to activate the port prior to enabling
connection via a switch.
``not used`` refers to an internal port that is expected
to never have a device connected to it. These may be
empty internal ports, or ports that are not physically
exposed on a platform. Considered safe to be
powered-off at all times.
``unknown`` means platform firmware does not provide
information for this port. Most commonly refers to
external hub ports which should be considered 'hotplug'
for policy decisions.
.. note::
- since we are relying on the BIOS to get this ACPI
information correct, the USB port descriptions may
be missing or wrong.
- Take care in clearing ``pm_qos_no_power_off``. Once
power is off this port will
not respond to new connect events.
Once a child device is attached additional constraints are
applied before the port is allowed to poweroff.
``<child>/power/control``:
Must be ``auto``, and the port will not
power down until ``<child>/power/runtime_status``
reflects the 'suspended' state. Default
value is controlled by child device driver.
``<child>/power/persist``:
This defaults to ``1`` for most devices and indicates if
kernel can persist the device's configuration across a
power session loss (suspend / port-power event). When
this value is ``0`` (quirky devices), port poweroff is
disabled.
``<child>/driver/unbind``:
Wakeup capable devices will block port poweroff. At
this time the only mechanism to clear the usb-internal
wakeup-capability for an interface device is to unbind
its driver.
Summary of poweroff pre-requisite settings relative to a port device::
echo 0 > power/pm_qos_no_power_off
echo 0 > peer/power/pm_qos_no_power_off # if it exists
echo auto > power/control # this is the default value
echo auto > <child>/power/control
echo 1 > <child>/power/persist # this is the default value
Suggested Userspace Port Power Policy
-------------------------------------
As noted above userspace needs to be careful and deliberate about what
ports are enabled for poweroff.
The default configuration is that all ports start with
``power/pm_qos_no_power_off`` set to ``1`` causing ports to always remain
active.
Given confidence in the platform firmware's description of the ports
(ACPI _PLD record for a port populates 'connect_type') userspace can
clear pm_qos_no_power_off for all 'not used' ports. The same can be
done for 'hardwired' ports provided poweroff is coordinated with any
connection switch for the port.
A more aggressive userspace policy is to enable USB port power off for
all ports (set ``<hubdev-portX>/power/pm_qos_no_power_off`` to ``0``) when
some external factor indicates the user has stopped interacting with the
system. For example, a distro may want to enable power off all USB
ports when the screen blanks, and re-power them when the screen becomes
active. Smart phones and tablets may want to power off USB ports when
the user pushes the power button.
@@ -0,0 +1,234 @@
.. _typec:
USB Type-C connector class
==========================
Introduction
------------
The typec class is meant for describing the USB Type-C ports in a system to the
user space in unified fashion. The class is designed to provide nothing else
except the user space interface implementation in hope that it can be utilized
on as many platforms as possible.
The platforms are expected to register every USB Type-C port they have with the
class. In a normal case the registration will be done by a USB Type-C or PD PHY
driver, but it may be a driver for firmware interface such as UCSI, driver for
USB PD controller or even driver for Thunderbolt3 controller. This document
considers the component registering the USB Type-C ports with the class as "port
driver".
On top of showing the capabilities, the class also offer user space control over
the roles and alternate modes of ports, partners and cable plugs when the port
driver is capable of supporting those features.
The class provides an API for the port drivers described in this document. The
attributes are described in Documentation/ABI/testing/sysfs-class-typec.
User space interface
--------------------
Every port will be presented as its own device under /sys/class/typec/. The
first port will be named "port0", the second "port1" and so on.
When connected, the partner will be presented also as its own device under
/sys/class/typec/. The parent of the partner device will always be the port it
is attached to. The partner attached to port "port0" will be named
"port0-partner". Full path to the device would be
/sys/class/typec/port0/port0-partner/.
The cable and the two plugs on it may also be optionally presented as their own
devices under /sys/class/typec/. The cable attached to the port "port0" port
will be named port0-cable and the plug on the SOP Prime end (see USB Power
Delivery Specification ch. 2.4) will be named "port0-plug0" and on the SOP
Double Prime end "port0-plug1". The parent of a cable will always be the port,
and the parent of the cable plugs will always be the cable.
If the port, partner or cable plug supports Alternate Modes, every supported
Alternate Mode SVID will have their own device describing them. Note that the
Alternate Mode devices will not be attached to the typec class. The parent of an
alternate mode will be the device that supports it, so for example an alternate
mode of port0-partner will be presented under /sys/class/typec/port0-partner/.
Every mode that is supported will have its own group under the Alternate Mode
device named "mode<index>", for example /sys/class/typec/port0/<alternate
mode>/mode1/. The requests for entering/exiting a mode can be done with "active"
attribute file in that group.
Driver API
----------
Registering the ports
~~~~~~~~~~~~~~~~~~~~~
The port drivers will describe every Type-C port they control with struct
typec_capability data structure, and register them with the following API:
.. kernel-doc:: drivers/usb/typec/class.c
:functions: typec_register_port typec_unregister_port
When registering the ports, the prefer_role member in struct typec_capability
deserves special notice. If the port that is being registered does not have
initial role preference, which means the port does not execute Try.SNK or
Try.SRC by default, the member must have value TYPEC_NO_PREFERRED_ROLE.
Otherwise if the port executes Try.SNK by default, the member must have value
TYPEC_DEVICE, and with Try.SRC the value must be TYPEC_HOST.
Registering Partners
~~~~~~~~~~~~~~~~~~~~
After successful connection of a partner, the port driver needs to register the
partner with the class. Details about the partner need to be described in struct
typec_partner_desc. The class copies the details of the partner during
registration. The class offers the following API for registering/unregistering
partners.
.. kernel-doc:: drivers/usb/typec/class.c
:functions: typec_register_partner typec_unregister_partner
The class will provide a handle to struct typec_partner if the registration was
successful, or NULL.
If the partner is USB Power Delivery capable, and the port driver is able to
show the result of Discover Identity command, the partner descriptor structure
should include handle to struct usb_pd_identity instance. The class will then
create a sysfs directory for the identity under the partner device. The result
of Discover Identity command can then be reported with the following API:
.. kernel-doc:: drivers/usb/typec/class.c
:functions: typec_partner_set_identity
Registering Cables
~~~~~~~~~~~~~~~~~~
After successful connection of a cable that supports USB Power Delivery
Structured VDM "Discover Identity", the port driver needs to register the cable
and one or two plugs, depending if there is CC Double Prime controller present
in the cable or not. So a cable capable of SOP Prime communication, but not SOP
Double Prime communication, should only have one plug registered. For more
information about SOP communication, please read chapter about it from the
latest USB Power Delivery specification.
The plugs are represented as their own devices. The cable is registered first,
followed by registration of the cable plugs. The cable will be the parent device
for the plugs. Details about the cable need to be described in struct
typec_cable_desc and about a plug in struct typec_plug_desc. The class copies
the details during registration. The class offers the following API for
registering/unregistering cables and their plugs:
.. kernel-doc:: drivers/usb/typec/class.c
:functions: typec_register_cable typec_unregister_cable typec_register_plug typec_unregister_plug
The class will provide a handle to struct typec_cable and struct typec_plug if
the registration is successful, or NULL if it isn't.
If the cable is USB Power Delivery capable, and the port driver is able to show
the result of Discover Identity command, the cable descriptor structure should
include handle to struct usb_pd_identity instance. The class will then create a
sysfs directory for the identity under the cable device. The result of Discover
Identity command can then be reported with the following API:
.. kernel-doc:: drivers/usb/typec/class.c
:functions: typec_cable_set_identity
Notifications
~~~~~~~~~~~~~
When the partner has executed a role change, or when the default roles change
during connection of a partner or cable, the port driver must use the following
APIs to report it to the class:
.. kernel-doc:: drivers/usb/typec/class.c
:functions: typec_set_data_role typec_set_pwr_role typec_set_vconn_role typec_set_pwr_opmode
Alternate Modes
~~~~~~~~~~~~~~~
USB Type-C ports, partners and cable plugs may support Alternate Modes. Each
Alternate Mode will have identifier called SVID, which is either a Standard ID
given by USB-IF or vendor ID, and each supported SVID can have 1 - 6 modes. The
class provides struct typec_mode_desc for describing individual mode of a SVID,
and struct typec_altmode_desc which is a container for all the supported modes.
Ports that support Alternate Modes need to register each SVID they support with
the following API:
.. kernel-doc:: drivers/usb/typec/class.c
:functions: typec_port_register_altmode
If a partner or cable plug provides a list of SVIDs as response to USB Power
Delivery Structured VDM Discover SVIDs message, each SVID needs to be
registered.
API for the partners:
.. kernel-doc:: drivers/usb/typec/class.c
:functions: typec_partner_register_altmode
API for the Cable Plugs:
.. kernel-doc:: drivers/usb/typec/class.c
:functions: typec_plug_register_altmode
So ports, partners and cable plugs will register the alternate modes with their
own functions, but the registration will always return a handle to struct
typec_altmode on success, or NULL. The unregistration will happen with the same
function:
.. kernel-doc:: drivers/usb/typec/class.c
:functions: typec_unregister_altmode
If a partner or cable plug enters or exits a mode, the port driver needs to
notify the class with the following API:
.. kernel-doc:: drivers/usb/typec/class.c
:functions: typec_altmode_update_active
Multiplexer/DeMultiplexer Switches
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
USB Type-C connectors may have one or more mux/demux switches behind them. Since
the plugs can be inserted right-side-up or upside-down, a switch is needed to
route the correct data pairs from the connector to the USB controllers. If
Alternate or Accessory Modes are supported, another switch is needed that can
route the pins on the connector to some other component besides USB. USB Type-C
Connector Class supplies an API for registering those switches.
.. kernel-doc:: drivers/usb/typec/mux.c
:functions: typec_switch_register typec_switch_unregister typec_mux_register typec_mux_unregister
In most cases the same physical mux will handle both the orientation and mode.
However, as the port drivers will be responsible for the orientation, and the
alternate mode drivers for the mode, the two are always separated into their
own logical components: "mux" for the mode and "switch" for the orientation.
When a port is registered, USB Type-C Connector Class requests both the mux and
the switch for the port. The drivers can then use the following API for
controlling them:
.. kernel-doc:: drivers/usb/typec/class.c
:functions: typec_set_orientation typec_set_mode
If the connector is dual-role capable, there may also be a switch for the data
role. USB Type-C Connector Class does not supply separate API for them. The
port drivers can use USB Role Class API with those.
Illustration of the muxes behind a connector that supports an alternate mode::
------------------------
| Connector |
------------------------
| |
------------------------
\ Orientation /
--------------------
|
--------------------
/ Mode \
------------------------
/ \
------------------------ --------------------
| Alt Mode | / USB Role \
------------------------ ------------------------
/ \
------------------------ ------------------------
| USB Host | | USB Device |
------------------------ ------------------------
@@ -0,0 +1,122 @@
API for USB Type-C Alternate Mode drivers
=========================================
Introduction
------------
Alternate modes require communication with the partner using Vendor Defined
Messages (VDM) as defined in USB Type-C and USB Power Delivery Specifications.
The communication is SVID (Standard or Vendor ID) specific, i.e. specific for
every alternate mode, so every alternate mode will need a custom driver.
USB Type-C bus allows binding a driver to the discovered partner alternate
modes by using the SVID and the mode number.
:ref:`USB Type-C Connector Class <typec>` provides a device for every alternate
mode a port supports, and separate device for every alternate mode the partner
supports. The drivers for the alternate modes are bound to the partner alternate
mode devices, and the port alternate mode devices must be handled by the port
drivers.
When a new partner alternate mode device is registered, it is linked to the
alternate mode device of the port that the partner is attached to, that has
matching SVID and mode. Communication between the port driver and alternate mode
driver will happen using the same API.
The port alternate mode devices are used as a proxy between the partner and the
alternate mode drivers, so the port drivers are only expected to pass the SVID
specific commands from the alternate mode drivers to the partner, and from the
partners to the alternate mode drivers. No direct SVID specific communication is
needed from the port drivers, but the port drivers need to provide the operation
callbacks for the port alternate mode devices, just like the alternate mode
drivers need to provide them for the partner alternate mode devices.
Usage:
------
General
~~~~~~~
By default, the alternate mode drivers are responsible for entering the mode.
It is also possible to leave the decision about entering the mode to the user
space (See Documentation/ABI/testing/sysfs-class-typec). Port drivers should not
enter any modes on their own.
``->vdm`` is the most important callback in the operation callbacks vector. It
will be used to deliver all the SVID specific commands from the partner to the
alternate mode driver, and vice versa in case of port drivers. The drivers send
the SVID specific commands to each other using :c:func:`typec_altmode_vdm()`.
If the communication with the partner using the SVID specific commands results
in need to reconfigure the pins on the connector, the alternate mode driver
needs to notify the bus using :c:func:`typec_altmode_notify()`. The driver
passes the negotiated SVID specific pin configuration value to the function as
parameter. The bus driver will then configure the mux behind the connector using
that value as the state value for the mux.
NOTE: The SVID specific pin configuration values must always start from
``TYPEC_STATE_MODAL``. USB Type-C specification defines two default states for
the connector: ``TYPEC_STATE_USB`` and ``TYPEC_STATE_SAFE``. These values are
reserved by the bus as the first possible values for the state. When the
alternate mode is entered, the bus will put the connector into
``TYPEC_STATE_SAFE`` before sending Enter or Exit Mode command as defined in USB
Type-C Specification, and also put the connector back to ``TYPEC_STATE_USB``
after the mode has been exited.
An example of working definitions for SVID specific pin configurations would
look like this::
enum {
ALTMODEX_CONF_A = TYPEC_STATE_MODAL,
ALTMODEX_CONF_B,
...
};
Helper macro ``TYPEC_MODAL_STATE()`` can also be used::
#define ALTMODEX_CONF_A = TYPEC_MODAL_STATE(0);
#define ALTMODEX_CONF_B = TYPEC_MODAL_STATE(1);
Cable plug alternate modes
~~~~~~~~~~~~~~~~~~~~~~~~~~
The alternate mode drivers are not bound to cable plug alternate mode devices,
only to the partner alternate mode devices. If the alternate mode supports, or
requires, a cable that responds to SOP Prime, and optionally SOP Double Prime
messages, the driver for that alternate mode must request handle to the cable
plug alternate modes using :c:func:`typec_altmode_get_plug()`, and take over
their control.
Driver API
----------
Alternate mode structs
~~~~~~~~~~~~~~~~~~~~~~
.. kernel-doc:: include/linux/usb/typec_altmode.h
:functions: typec_altmode_driver typec_altmode_ops
Alternate mode driver registering/unregistering
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. kernel-doc:: include/linux/usb/typec_altmode.h
:functions: typec_altmode_register_driver typec_altmode_unregister_driver
Alternate mode driver operations
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. kernel-doc:: drivers/usb/typec/bus.c
:functions: typec_altmode_enter typec_altmode_exit typec_altmode_attention typec_altmode_vdm typec_altmode_notify
API for the port drivers
~~~~~~~~~~~~~~~~~~~~~~~~
.. kernel-doc:: drivers/usb/typec/bus.c
:functions: typec_match_altmode
Cable Plug operations
~~~~~~~~~~~~~~~~~~~~~
.. kernel-doc:: drivers/usb/typec/bus.c
:functions: typec_altmode_get_plug typec_altmode_put_plug
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,152 @@
===============
USB3 debug port
===============
:Author: Lu Baolu <baolu.lu@linux.intel.com>
:Date: March 2017
GENERAL
=======
This is a HOWTO for using the USB3 debug port on x86 systems.
Before using any kernel debugging functionality based on USB3
debug port, you need to::
1) check whether any USB3 debug port is available in
your system;
2) check which port is used for debugging purposes;
3) have a USB 3.0 super-speed A-to-A debugging cable.
INTRODUCTION
============
The xHCI debug capability (DbC) is an optional but standalone
functionality provided by the xHCI host controller. The xHCI
specification describes DbC in the section 7.6.
When DbC is initialized and enabled, it will present a debug
device through the debug port (normally the first USB3
super-speed port). The debug device is fully compliant with
the USB framework and provides the equivalent of a very high
performance full-duplex serial link between the debug target
(the system under debugging) and a debug host.
EARLY PRINTK
============
DbC has been designed to log early printk messages. One use for
this feature is kernel debugging. For example, when your machine
crashes very early before the regular console code is initialized.
Other uses include simpler, lockless logging instead of a full-
blown printk console driver and klogd.
On the debug target system, you need to customize a debugging
kernel with CONFIG_EARLY_PRINTK_USB_XDBC enabled. And, add below
kernel boot parameter::
"earlyprintk=xdbc"
If there are multiple xHCI controllers in your system, you can
append a host controller index to this kernel parameter. This
index starts from 0.
Current design doesn't support DbC runtime suspend/resume. As
the result, you'd better disable runtime power management for
USB subsystem by adding below kernel boot parameter::
"usbcore.autosuspend=-1"
Before starting the debug target, you should connect the debug
port to a USB port (root port or port of any external hub) on
the debug host. The cable used to connect these two ports
should be a USB 3.0 super-speed A-to-A debugging cable.
During early boot of the debug target, DbC will be detected and
initialized. After initialization, the debug host should be able
to enumerate the debug device in debug target. The debug host
will then bind the debug device with the usb_debug driver module
and create the /dev/ttyUSB device.
If the debug device enumeration goes smoothly, you should be able
to see below kernel messages on the debug host::
# tail -f /var/log/kern.log
[ 1815.983374] usb 4-3: new SuperSpeed USB device number 4 using xhci_hcd
[ 1815.999595] usb 4-3: LPM exit latency is zeroed, disabling LPM.
[ 1815.999899] usb 4-3: New USB device found, idVendor=1d6b, idProduct=0004
[ 1815.999902] usb 4-3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 1815.999903] usb 4-3: Product: Remote GDB
[ 1815.999904] usb 4-3: Manufacturer: Linux
[ 1815.999905] usb 4-3: SerialNumber: 0001
[ 1816.000240] usb_debug 4-3:1.0: xhci_dbc converter detected
[ 1816.000360] usb 4-3: xhci_dbc converter now attached to ttyUSB0
You can use any communication program, for example minicom, to
read and view the messages. Below simple bash scripts can help
you to check the sanity of the setup.
.. code-block:: sh
===== start of bash scripts =============
#!/bin/bash
while true ; do
while [ ! -d /sys/class/tty/ttyUSB0 ] ; do
:
done
cat /dev/ttyUSB0
done
===== end of bash scripts ===============
Serial TTY
==========
The DbC support has been added to the xHCI driver. You can get a
debug device provided by the DbC at runtime.
In order to use this, you need to make sure your kernel has been
configured to support USB_XHCI_DBGCAP. A sysfs attribute under
the xHCI device node is used to enable or disable DbC. By default,
DbC is disabled::
root@target:/sys/bus/pci/devices/0000:00:14.0# cat dbc
disabled
Enable DbC with the following command::
root@target:/sys/bus/pci/devices/0000:00:14.0# echo enable > dbc
You can check the DbC state at anytime::
root@target:/sys/bus/pci/devices/0000:00:14.0# cat dbc
enabled
Connect the debug target to the debug host with a USB 3.0 super-
speed A-to-A debugging cable. You can see /dev/ttyDBC0 created
on the debug target. You will see below kernel message lines::
root@target: tail -f /var/log/kern.log
[ 182.730103] xhci_hcd 0000:00:14.0: DbC connected
[ 191.169420] xhci_hcd 0000:00:14.0: DbC configured
[ 191.169597] xhci_hcd 0000:00:14.0: DbC now attached to /dev/ttyDBC0
Accordingly, the DbC state has been brought up to::
root@target:/sys/bus/pci/devices/0000:00:14.0# cat dbc
configured
On the debug host, you will see the debug device has been enumerated.
You will see below kernel message lines::
root@host: tail -f /var/log/kern.log
[ 79.454780] usb 2-2.1: new SuperSpeed USB device number 3 using xhci_hcd
[ 79.475003] usb 2-2.1: LPM exit latency is zeroed, disabling LPM.
[ 79.475389] usb 2-2.1: New USB device found, idVendor=1d6b, idProduct=0010
[ 79.475390] usb 2-2.1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 79.475391] usb 2-2.1: Product: Linux USB Debug Target
[ 79.475392] usb 2-2.1: Manufacturer: Linux Foundation
[ 79.475393] usb 2-2.1: SerialNumber: 0001
The debug device works now. You can use any communication or debugging
program to talk between the host and the target.
@@ -0,0 +1,720 @@
=========================
Writing a MUSB Glue Layer
=========================
:Author: Apelete Seketeli
Introduction
============
The Linux MUSB subsystem is part of the larger Linux USB subsystem. It
provides support for embedded USB Device Controllers (UDC) that do not
use Universal Host Controller Interface (UHCI) or Open Host Controller
Interface (OHCI).
Instead, these embedded UDC rely on the USB On-the-Go (OTG)
specification which they implement at least partially. The silicon
reference design used in most cases is the Multipoint USB Highspeed
Dual-Role Controller (MUSB HDRC) found in the Mentor Graphics Inventra™
design.
As a self-taught exercise I have written an MUSB glue layer for the
Ingenic JZ4740 SoC, modelled after the many MUSB glue layers in the
kernel source tree. This layer can be found at
``drivers/usb/musb/jz4740.c``. In this documentation I will walk through the
basics of the ``jz4740.c`` glue layer, explaining the different pieces and
what needs to be done in order to write your own device glue layer.
.. _musb-basics:
Linux MUSB Basics
=================
To get started on the topic, please read USB On-the-Go Basics (see
Resources) which provides an introduction of USB OTG operation at the
hardware level. A couple of wiki pages by Texas Instruments and Analog
Devices also provide an overview of the Linux kernel MUSB configuration,
albeit focused on some specific devices provided by these companies.
Finally, getting acquainted with the USB specification at USB home page
may come in handy, with practical instance provided through the Writing
USB Device Drivers documentation (again, see Resources).
Linux USB stack is a layered architecture in which the MUSB controller
hardware sits at the lowest. The MUSB controller driver abstract the
MUSB controller hardware to the Linux USB stack::
------------------------
| | <------- drivers/usb/gadget
| Linux USB Core Stack | <------- drivers/usb/host
| | <------- drivers/usb/core
------------------------
⬍
--------------------------
| | <------ drivers/usb/musb/musb_gadget.c
| MUSB Controller driver | <------ drivers/usb/musb/musb_host.c
| | <------ drivers/usb/musb/musb_core.c
--------------------------
⬍
---------------------------------
| MUSB Platform Specific Driver |
| | <-- drivers/usb/musb/jz4740.c
| aka "Glue Layer" |
---------------------------------
⬍
---------------------------------
| MUSB Controller Hardware |
---------------------------------
As outlined above, the glue layer is actually the platform specific code
sitting in between the controller driver and the controller hardware.
Just like a Linux USB driver needs to register itself with the Linux USB
subsystem, the MUSB glue layer needs first to register itself with the
MUSB controller driver. This will allow the controller driver to know
about which device the glue layer supports and which functions to call
when a supported device is detected or released; remember we are talking
about an embedded controller chip here, so no insertion or removal at
run-time.
All of this information is passed to the MUSB controller driver through
a :c:type:`platform_driver` structure defined in the glue layer as::
static struct platform_driver jz4740_driver = {
.probe = jz4740_probe,
.remove = jz4740_remove,
.driver = {
.name = "musb-jz4740",
},
};
The probe and remove function pointers are called when a matching device
is detected and, respectively, released. The name string describes the
device supported by this glue layer. In the current case it matches a
platform_device structure declared in ``arch/mips/jz4740/platform.c``. Note
that we are not using device tree bindings here.
In order to register itself to the controller driver, the glue layer
goes through a few steps, basically allocating the controller hardware
resources and initialising a couple of circuits. To do so, it needs to
keep track of the information used throughout these steps. This is done
by defining a private ``jz4740_glue`` structure::
struct jz4740_glue {
struct device *dev;
struct platform_device *musb;
struct clk *clk;
};
The dev and musb members are both device structure variables. The first
one holds generic information about the device, since it's the basic
device structure, and the latter holds information more closely related
to the subsystem the device is registered to. The clk variable keeps
information related to the device clock operation.
Let's go through the steps of the probe function that leads the glue
layer to register itself to the controller driver.
.. note::
For the sake of readability each function will be split in logical
parts, each part being shown as if it was independent from the others.
.. code-block:: c
:emphasize-lines: 8,12,18
static int jz4740_probe(struct platform_device *pdev)
{
struct platform_device *musb;
struct jz4740_glue *glue;
struct clk *clk;
int ret;
glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
if (!glue)
return -ENOMEM;
musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
if (!musb) {
dev_err(&pdev->dev, "failed to allocate musb device\n");
return -ENOMEM;
}
clk = devm_clk_get(&pdev->dev, "udc");
if (IS_ERR(clk)) {
dev_err(&pdev->dev, "failed to get clock\n");
ret = PTR_ERR(clk);
goto err_platform_device_put;
}
ret = clk_prepare_enable(clk);
if (ret) {
dev_err(&pdev->dev, "failed to enable clock\n");
goto err_platform_device_put;
}
musb->dev.parent = &pdev->dev;
glue->dev = &pdev->dev;
glue->musb = musb;
glue->clk = clk;
return 0;
err_platform_device_put:
platform_device_put(musb);
return ret;
}
The first few lines of the probe function allocate and assign the glue,
musb and clk variables. The ``GFP_KERNEL`` flag (line 8) allows the
allocation process to sleep and wait for memory, thus being usable in a
locking situation. The ``PLATFORM_DEVID_AUTO`` flag (line 12) allows
automatic allocation and management of device IDs in order to avoid
device namespace collisions with explicit IDs. With :c:func:`devm_clk_get`
(line 18) the glue layer allocates the clock -- the ``devm_`` prefix
indicates that :c:func:`clk_get` is managed: it automatically frees the
allocated clock resource data when the device is released -- and enable
it.
Then comes the registration steps:
.. code-block:: c
:emphasize-lines: 3,5,7,9,16
static int jz4740_probe(struct platform_device *pdev)
{
struct musb_hdrc_platform_data *pdata = &jz4740_musb_platform_data;
pdata->platform_ops = &jz4740_musb_ops;
platform_set_drvdata(pdev, glue);
ret = platform_device_add_resources(musb, pdev->resource,
pdev->num_resources);
if (ret) {
dev_err(&pdev->dev, "failed to add resources\n");
goto err_clk_disable;
}
ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
if (ret) {
dev_err(&pdev->dev, "failed to add platform_data\n");
goto err_clk_disable;
}
return 0;
err_clk_disable:
clk_disable_unprepare(clk);
err_platform_device_put:
platform_device_put(musb);
return ret;
}
The first step is to pass the device data privately held by the glue
layer on to the controller driver through :c:func:`platform_set_drvdata`
(line 7). Next is passing on the device resources information, also privately
held at that point, through :c:func:`platform_device_add_resources` (line 9).
Finally comes passing on the platform specific data to the controller
driver (line 16). Platform data will be discussed in
:ref:`musb-dev-platform-data`, but here we are looking at the
``platform_ops`` function pointer (line 5) in ``musb_hdrc_platform_data``
structure (line 3). This function pointer allows the MUSB controller
driver to know which function to call for device operation::
static const struct musb_platform_ops jz4740_musb_ops = {
.init = jz4740_musb_init,
.exit = jz4740_musb_exit,
};
Here we have the minimal case where only init and exit functions are
called by the controller driver when needed. Fact is the JZ4740 MUSB
controller is a basic controller, lacking some features found in other
controllers, otherwise we may also have pointers to a few other
functions like a power management function or a function to switch
between OTG and non-OTG modes, for instance.
At that point of the registration process, the controller driver
actually calls the init function:
.. code-block:: c
:emphasize-lines: 12,14
static int jz4740_musb_init(struct musb *musb)
{
musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
if (!musb->xceiv) {
pr_err("HS UDC: no transceiver configured\n");
return -ENODEV;
}
/* Silicon does not implement ConfigData register.
* Set dyn_fifo to avoid reading EP config from hardware.
*/
musb->dyn_fifo = true;
musb->isr = jz4740_musb_interrupt;
return 0;
}
The goal of ``jz4740_musb_init()`` is to get hold of the transceiver
driver data of the MUSB controller hardware and pass it on to the MUSB
controller driver, as usual. The transceiver is the circuitry inside the
controller hardware responsible for sending/receiving the USB data.
Since it is an implementation of the physical layer of the OSI model,
the transceiver is also referred to as PHY.
Getting hold of the ``MUSB PHY`` driver data is done with ``usb_get_phy()``
which returns a pointer to the structure containing the driver instance
data. The next couple of instructions (line 12 and 14) are used as a
quirk and to setup IRQ handling respectively. Quirks and IRQ handling
will be discussed later in :ref:`musb-dev-quirks` and
:ref:`musb-handling-irqs`\ ::
static int jz4740_musb_exit(struct musb *musb)
{
usb_put_phy(musb->xceiv);
return 0;
}
Acting as the counterpart of init, the exit function releases the MUSB
PHY driver when the controller hardware itself is about to be released.
Again, note that init and exit are fairly simple in this case due to the
basic set of features of the JZ4740 controller hardware. When writing an
musb glue layer for a more complex controller hardware, you might need
to take care of more processing in those two functions.
Returning from the init function, the MUSB controller driver jumps back
into the probe function::
static int jz4740_probe(struct platform_device *pdev)
{
ret = platform_device_add(musb);
if (ret) {
dev_err(&pdev->dev, "failed to register musb device\n");
goto err_clk_disable;
}
return 0;
err_clk_disable:
clk_disable_unprepare(clk);
err_platform_device_put:
platform_device_put(musb);
return ret;
}
This is the last part of the device registration process where the glue
layer adds the controller hardware device to Linux kernel device
hierarchy: at this stage, all known information about the device is
passed on to the Linux USB core stack:
.. code-block:: c
:emphasize-lines: 5,6
static int jz4740_remove(struct platform_device *pdev)
{
struct jz4740_glue *glue = platform_get_drvdata(pdev);
platform_device_unregister(glue->musb);
clk_disable_unprepare(glue->clk);
return 0;
}
Acting as the counterpart of probe, the remove function unregister the
MUSB controller hardware (line 5) and disable the clock (line 6),
allowing it to be gated.
.. _musb-handling-irqs:
Handling IRQs
=============
Additionally to the MUSB controller hardware basic setup and
registration, the glue layer is also responsible for handling the IRQs:
.. code-block:: c
:emphasize-lines: 7,9-11,14,24
static irqreturn_t jz4740_musb_interrupt(int irq, void *__hci)
{
unsigned long flags;
irqreturn_t retval = IRQ_NONE;
struct musb *musb = __hci;
spin_lock_irqsave(&musb->lock, flags);
musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);
/*
* The controller is gadget only, the state of the host mode IRQ bits is
* undefined. Mask them to make sure that the musb driver core will
* never see them set
*/
musb->int_usb &= MUSB_INTR_SUSPEND | MUSB_INTR_RESUME |
MUSB_INTR_RESET | MUSB_INTR_SOF;
if (musb->int_usb || musb->int_tx || musb->int_rx)
retval = musb_interrupt(musb);
spin_unlock_irqrestore(&musb->lock, flags);
return retval;
}
Here the glue layer mostly has to read the relevant hardware registers
and pass their values on to the controller driver which will handle the
actual event that triggered the IRQ.
The interrupt handler critical section is protected by the
:c:func:`spin_lock_irqsave` and counterpart :c:func:`spin_unlock_irqrestore`
functions (line 7 and 24 respectively), which prevent the interrupt
handler code to be run by two different threads at the same time.
Then the relevant interrupt registers are read (line 9 to 11):
- ``MUSB_INTRUSB``: indicates which USB interrupts are currently active,
- ``MUSB_INTRTX``: indicates which of the interrupts for TX endpoints are
currently active,
- ``MUSB_INTRRX``: indicates which of the interrupts for TX endpoints are
currently active.
Note that :c:func:`musb_readb` is used to read 8-bit registers at most, while
:c:func:`musb_readw` allows us to read at most 16-bit registers. There are
other functions that can be used depending on the size of your device
registers. See ``musb_io.h`` for more information.
Instruction on line 18 is another quirk specific to the JZ4740 USB
device controller, which will be discussed later in :ref:`musb-dev-quirks`.
The glue layer still needs to register the IRQ handler though. Remember
the instruction on line 14 of the init function::
static int jz4740_musb_init(struct musb *musb)
{
musb->isr = jz4740_musb_interrupt;
return 0;
}
This instruction sets a pointer to the glue layer IRQ handler function,
in order for the controller hardware to call the handler back when an
IRQ comes from the controller hardware. The interrupt handler is now
implemented and registered.
.. _musb-dev-platform-data:
Device Platform Data
====================
In order to write an MUSB glue layer, you need to have some data
describing the hardware capabilities of your controller hardware, which
is called the platform data.
Platform data is specific to your hardware, though it may cover a broad
range of devices, and is generally found somewhere in the ``arch/``
directory, depending on your device architecture.
For instance, platform data for the JZ4740 SoC is found in
``arch/mips/jz4740/platform.c``. In the ``platform.c`` file each device of the
JZ4740 SoC is described through a set of structures.
Here is the part of ``arch/mips/jz4740/platform.c`` that covers the USB
Device Controller (UDC):
.. code-block:: c
:emphasize-lines: 2,7,14-17,21,22,25,26,28,29
/* USB Device Controller */
struct platform_device jz4740_udc_xceiv_device = {
.name = "usb_phy_gen_xceiv",
.id = 0,
};
static struct resource jz4740_udc_resources[] = {
[0] = {
.start = JZ4740_UDC_BASE_ADDR,
.end = JZ4740_UDC_BASE_ADDR + 0x10000 - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = JZ4740_IRQ_UDC,
.end = JZ4740_IRQ_UDC,
.flags = IORESOURCE_IRQ,
.name = "mc",
},
};
struct platform_device jz4740_udc_device = {
.name = "musb-jz4740",
.id = -1,
.dev = {
.dma_mask = &jz4740_udc_device.dev.coherent_dma_mask,
.coherent_dma_mask = DMA_BIT_MASK(32),
},
.num_resources = ARRAY_SIZE(jz4740_udc_resources),
.resource = jz4740_udc_resources,
};
The ``jz4740_udc_xceiv_device`` platform device structure (line 2)
describes the UDC transceiver with a name and id number.
At the time of this writing, note that ``usb_phy_gen_xceiv`` is the
specific name to be used for all transceivers that are either built-in
with reference USB IP or autonomous and doesn't require any PHY
programming. You will need to set ``CONFIG_NOP_USB_XCEIV=y`` in the
kernel configuration to make use of the corresponding transceiver
driver. The id field could be set to -1 (equivalent to
``PLATFORM_DEVID_NONE``), -2 (equivalent to ``PLATFORM_DEVID_AUTO``) or
start with 0 for the first device of this kind if we want a specific id
number.
The ``jz4740_udc_resources`` resource structure (line 7) defines the UDC
registers base addresses.
The first array (line 9 to 11) defines the UDC registers base memory
addresses: start points to the first register memory address, end points
to the last register memory address and the flags member defines the
type of resource we are dealing with. So ``IORESOURCE_MEM`` is used to
define the registers memory addresses. The second array (line 14 to 17)
defines the UDC IRQ registers addresses. Since there is only one IRQ
register available for the JZ4740 UDC, start and end point at the same
address. The ``IORESOURCE_IRQ`` flag tells that we are dealing with IRQ
resources, and the name ``mc`` is in fact hard-coded in the MUSB core in
order for the controller driver to retrieve this IRQ resource by
querying it by its name.
Finally, the ``jz4740_udc_device`` platform device structure (line 21)
describes the UDC itself.
The ``musb-jz4740`` name (line 22) defines the MUSB driver that is used
for this device; remember this is in fact the name that we used in the
``jz4740_driver`` platform driver structure in :ref:`musb-basics`.
The id field (line 23) is set to -1 (equivalent to ``PLATFORM_DEVID_NONE``)
since we do not need an id for the device: the MUSB controller driver was
already set to allocate an automatic id in :ref:`musb-basics`. In the dev field
we care for DMA related information here. The ``dma_mask`` field (line 25)
defines the width of the DMA mask that is going to be used, and
``coherent_dma_mask`` (line 26) has the same purpose but for the
``alloc_coherent`` DMA mappings: in both cases we are using a 32 bits mask.
Then the resource field (line 29) is simply a pointer to the resource
structure defined before, while the ``num_resources`` field (line 28) keeps
track of the number of arrays defined in the resource structure (in this
case there were two resource arrays defined before).
With this quick overview of the UDC platform data at the ``arch/`` level now
done, let's get back to the MUSB glue layer specific platform data in
``drivers/usb/musb/jz4740.c``:
.. code-block:: c
:emphasize-lines: 3,5,7-9,11
static struct musb_hdrc_config jz4740_musb_config = {
/* Silicon does not implement USB OTG. */
.multipoint = 0,
/* Max EPs scanned, driver will decide which EP can be used. */
.num_eps = 4,
/* RAMbits needed to configure EPs from table */
.ram_bits = 9,
.fifo_cfg = jz4740_musb_fifo_cfg,
.fifo_cfg_size = ARRAY_SIZE(jz4740_musb_fifo_cfg),
};
static struct musb_hdrc_platform_data jz4740_musb_platform_data = {
.mode = MUSB_PERIPHERAL,
.config = &jz4740_musb_config,
};
First the glue layer configures some aspects of the controller driver
operation related to the controller hardware specifics. This is done
through the ``jz4740_musb_config`` :c:type:`musb_hdrc_config` structure.
Defining the OTG capability of the controller hardware, the multipoint
member (line 3) is set to 0 (equivalent to false) since the JZ4740 UDC
is not OTG compatible. Then ``num_eps`` (line 5) defines the number of USB
endpoints of the controller hardware, including endpoint 0: here we have
3 endpoints + endpoint 0. Next is ``ram_bits`` (line 7) which is the width
of the RAM address bus for the MUSB controller hardware. This
information is needed when the controller driver cannot automatically
configure endpoints by reading the relevant controller hardware
registers. This issue will be discussed when we get to device quirks in
:ref:`musb-dev-quirks`. Last two fields (line 8 and 9) are also
about device quirks: ``fifo_cfg`` points to the USB endpoints configuration
table and ``fifo_cfg_size`` keeps track of the size of the number of
entries in that configuration table. More on that later in
:ref:`musb-dev-quirks`.
Then this configuration is embedded inside ``jz4740_musb_platform_data``
:c:type:`musb_hdrc_platform_data` structure (line 11): config is a pointer to
the configuration structure itself, and mode tells the controller driver
if the controller hardware may be used as ``MUSB_HOST`` only,
``MUSB_PERIPHERAL`` only or ``MUSB_OTG`` which is a dual mode.
Remember that ``jz4740_musb_platform_data`` is then used to convey
platform data information as we have seen in the probe function in
:ref:`musb-basics`.
.. _musb-dev-quirks:
Device Quirks
=============
Completing the platform data specific to your device, you may also need
to write some code in the glue layer to work around some device specific
limitations. These quirks may be due to some hardware bugs, or simply be
the result of an incomplete implementation of the USB On-the-Go
specification.
The JZ4740 UDC exhibits such quirks, some of which we will discuss here
for the sake of insight even though these might not be found in the
controller hardware you are working on.
Let's get back to the init function first:
.. code-block:: c
:emphasize-lines: 12
static int jz4740_musb_init(struct musb *musb)
{
musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
if (!musb->xceiv) {
pr_err("HS UDC: no transceiver configured\n");
return -ENODEV;
}
/* Silicon does not implement ConfigData register.
* Set dyn_fifo to avoid reading EP config from hardware.
*/
musb->dyn_fifo = true;
musb->isr = jz4740_musb_interrupt;
return 0;
}
Instruction on line 12 helps the MUSB controller driver to work around
the fact that the controller hardware is missing registers that are used
for USB endpoints configuration.
Without these registers, the controller driver is unable to read the
endpoints configuration from the hardware, so we use line 12 instruction
to bypass reading the configuration from silicon, and rely on a
hard-coded table that describes the endpoints configuration instead::
static const struct musb_fifo_cfg jz4740_musb_fifo_cfg[] = {
{ .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, },
{ .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, },
{ .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 64, },
};
Looking at the configuration table above, we see that each endpoints is
described by three fields: ``hw_ep_num`` is the endpoint number, style is
its direction (either ``FIFO_TX`` for the controller driver to send packets
in the controller hardware, or ``FIFO_RX`` to receive packets from
hardware), and maxpacket defines the maximum size of each data packet
that can be transmitted over that endpoint. Reading from the table, the
controller driver knows that endpoint 1 can be used to send and receive
USB data packets of 512 bytes at once (this is in fact a bulk in/out
endpoint), and endpoint 2 can be used to send data packets of 64 bytes
at once (this is in fact an interrupt endpoint).
Note that there is no information about endpoint 0 here: that one is
implemented by default in every silicon design, with a predefined
configuration according to the USB specification. For more examples of
endpoint configuration tables, see ``musb_core.c``.
Let's now get back to the interrupt handler function:
.. code-block:: c
:emphasize-lines: 18-19
static irqreturn_t jz4740_musb_interrupt(int irq, void *__hci)
{
unsigned long flags;
irqreturn_t retval = IRQ_NONE;
struct musb *musb = __hci;
spin_lock_irqsave(&musb->lock, flags);
musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);
/*
* The controller is gadget only, the state of the host mode IRQ bits is
* undefined. Mask them to make sure that the musb driver core will
* never see them set
*/
musb->int_usb &= MUSB_INTR_SUSPEND | MUSB_INTR_RESUME |
MUSB_INTR_RESET | MUSB_INTR_SOF;
if (musb->int_usb || musb->int_tx || musb->int_rx)
retval = musb_interrupt(musb);
spin_unlock_irqrestore(&musb->lock, flags);
return retval;
}
Instruction on line 18 above is a way for the controller driver to work
around the fact that some interrupt bits used for USB host mode
operation are missing in the ``MUSB_INTRUSB`` register, thus left in an
undefined hardware state, since this MUSB controller hardware is used in
peripheral mode only. As a consequence, the glue layer masks these
missing bits out to avoid parasite interrupts by doing a logical AND
operation between the value read from ``MUSB_INTRUSB`` and the bits that
are actually implemented in the register.
These are only a couple of the quirks found in the JZ4740 USB device
controller. Some others were directly addressed in the MUSB core since
the fixes were generic enough to provide a better handling of the issues
for others controller hardware eventually.
Conclusion
==========
Writing a Linux MUSB glue layer should be a more accessible task, as
this documentation tries to show the ins and outs of this exercise.
The JZ4740 USB device controller being fairly simple, I hope its glue
layer serves as a good example for the curious mind. Used with the
current MUSB glue layers, this documentation should provide enough
guidance to get started; should anything gets out of hand, the linux-usb
mailing list archive is another helpful resource to browse through.
Acknowledgements
================
Many thanks to Lars-Peter Clausen and Maarten ter Huurne for answering
my questions while I was writing the JZ4740 glue layer and for helping
me out getting the code in good shape.
I would also like to thank the Qi-Hardware community at large for its
cheerful guidance and support.
Resources
=========
USB Home Page: https://www.usb.org
linux-usb Mailing List Archives: https://lore.kernel.org/linux-usb
USB On-the-Go Basics:
https://www.maximintegrated.com/app-notes/index.mvp/id/1822
:ref:`Writing USB Device Drivers <writing-usb-driver>`
Texas Instruments USB Configuration Wiki Page:
https://web.archive.org/web/20201215135015/http://processors.wiki.ti.com/index.php/Usbgeneralpage
@@ -0,0 +1,328 @@
.. _writing-usb-driver:
==========================
Writing USB Device Drivers
==========================
:Author: Greg Kroah-Hartman
Introduction
============
The Linux USB subsystem has grown from supporting only two different
types of devices in the 2.2.7 kernel (mice and keyboards), to over 20
different types of devices in the 2.4 kernel. Linux currently supports
almost all USB class devices (standard types of devices like keyboards,
mice, modems, printers and speakers) and an ever-growing number of
vendor-specific devices (such as USB to serial converters, digital
cameras, Ethernet devices and MP3 players). For a full list of the
different USB devices currently supported, see Resources.
The remaining kinds of USB devices that do not have support on Linux are
almost all vendor-specific devices. Each vendor decides to implement a
custom protocol to talk to their device, so a custom driver usually
needs to be created. Some vendors are open with their USB protocols and
help with the creation of Linux drivers, while others do not publish
them, and developers are forced to reverse-engineer. See Resources for
some links to handy reverse-engineering tools.
Because each different protocol causes a new driver to be created, I
have written a generic USB driver skeleton, modelled after the
pci-skeleton.c file in the kernel source tree upon which many PCI
network drivers have been based. This USB skeleton can be found at
drivers/usb/usb-skeleton.c in the kernel source tree. In this article I
will walk through the basics of the skeleton driver, explaining the
different pieces and what needs to be done to customize it to your
specific device.
Linux USB Basics
================
If you are going to write a Linux USB driver, please become familiar
with the USB protocol specification. It can be found, along with many
other useful documents, at the USB home page (see Resources). An
excellent introduction to the Linux USB subsystem can be found at the
USB Working Devices List (see Resources). It explains how the Linux USB
subsystem is structured and introduces the reader to the concept of USB
urbs (USB Request Blocks), which are essential to USB drivers.
The first thing a Linux USB driver needs to do is register itself with
the Linux USB subsystem, giving it some information about which devices
the driver supports and which functions to call when a device supported
by the driver is inserted or removed from the system. All of this
information is passed to the USB subsystem in the :c:type:`usb_driver`
structure. The skeleton driver declares a :c:type:`usb_driver` as::
static struct usb_driver skel_driver = {
.name = "skeleton",
.probe = skel_probe,
.disconnect = skel_disconnect,
.suspend = skel_suspend,
.resume = skel_resume,
.pre_reset = skel_pre_reset,
.post_reset = skel_post_reset,
.id_table = skel_table,
.supports_autosuspend = 1,
};
The variable name is a string that describes the driver. It is used in
informational messages printed to the system log. The probe and
disconnect function pointers are called when a device that matches the
information provided in the ``id_table`` variable is either seen or
removed.
The fops and minor variables are optional. Most USB drivers hook into
another kernel subsystem, such as the SCSI, network or TTY subsystem.
These types of drivers register themselves with the other kernel
subsystem, and any user-space interactions are provided through that
interface. But for drivers that do not have a matching kernel subsystem,
such as MP3 players or scanners, a method of interacting with user space
is needed. The USB subsystem provides a way to register a minor device
number and a set of :c:type:`file_operations` function pointers that enable
this user-space interaction. The skeleton driver needs this kind of
interface, so it provides a minor starting number and a pointer to its
:c:type:`file_operations` functions.
The USB driver is then registered with a call to usb_register(),
usually in the driver's init function, as shown here::
static int __init usb_skel_init(void)
{
int result;
/* register this driver with the USB subsystem */
result = usb_register(&skel_driver);
if (result < 0) {
pr_err("usb_register failed for the %s driver. Error number %d\n",
skel_driver.name, result);
return -1;
}
return 0;
}
module_init(usb_skel_init);
When the driver is unloaded from the system, it needs to deregister
itself with the USB subsystem. This is done with usb_deregister()
function::
static void __exit usb_skel_exit(void)
{
/* deregister this driver with the USB subsystem */
usb_deregister(&skel_driver);
}
module_exit(usb_skel_exit);
To enable the linux-hotplug system to load the driver automatically when
the device is plugged in, you need to create a ``MODULE_DEVICE_TABLE``.
The following code tells the hotplug scripts that this module supports a
single device with a specific vendor and product ID::
/* table of devices that work with this driver */
static struct usb_device_id skel_table [] = {
{ USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, skel_table);
There are other macros that can be used in describing a struct
:c:type:`usb_device_id` for drivers that support a whole class of USB
drivers. See :ref:`usb.h <usb_header>` for more information on this.
Device operation
================
When a device is plugged into the USB bus that matches the device ID
pattern that your driver registered with the USB core, the probe
function is called. The :c:type:`usb_device` structure, interface number and
the interface ID are passed to the function::
static int skel_probe(struct usb_interface *interface,
const struct usb_device_id *id)
The driver now needs to verify that this device is actually one that it
can accept. If so, it returns 0. If not, or if any error occurs during
initialization, an errorcode (such as ``-ENOMEM`` or ``-ENODEV``) is
returned from the probe function.
In the skeleton driver, we determine what end points are marked as
bulk-in and bulk-out. We create buffers to hold the data that will be
sent and received from the device, and a USB urb to write data to the
device is initialized.
Conversely, when the device is removed from the USB bus, the disconnect
function is called with the device pointer. The driver needs to clean
any private data that has been allocated at this time and to shut down
any pending urbs that are in the USB system.
Now that the device is plugged into the system and the driver is bound
to the device, any of the functions in the :c:type:`file_operations` structure
that were passed to the USB subsystem will be called from a user program
trying to talk to the device. The first function called will be open, as
the program tries to open the device for I/O. We increment our private
usage count and save a pointer to our internal structure in the file
structure. This is done so that future calls to file operations will
enable the driver to determine which device the user is addressing. All
of this is done with the following code::
/* increment our usage count for the device */
kref_get(&dev->kref);
/* save our object in the file's private structure */
file->private_data = dev;
After the open function is called, the read and write functions are
called to receive and send data to the device. In the ``skel_write``
function, we receive a pointer to some data that the user wants to send
to the device and the size of the data. The function determines how much
data it can send to the device based on the size of the write urb it has
created (this size depends on the size of the bulk out end point that
the device has). Then it copies the data from user space to kernel
space, points the urb to the data and submits the urb to the USB
subsystem. This can be seen in the following code::
/* we can only write as much as 1 urb will hold */
size_t writesize = min_t(size_t, count, MAX_TRANSFER);
/* copy the data from user space into our urb */
copy_from_user(buf, user_buffer, writesize);
/* set up our urb */
usb_fill_bulk_urb(urb,
dev->udev,
usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr),
buf,
writesize,
skel_write_bulk_callback,
dev);
/* send the data out the bulk port */
retval = usb_submit_urb(urb, GFP_KERNEL);
if (retval) {
dev_err(&dev->interface->dev,
"%s - failed submitting write urb, error %d\n",
__func__, retval);
}
When the write urb is filled up with the proper information using the
:c:func:`usb_fill_bulk_urb` function, we point the urb's completion callback
to call our own ``skel_write_bulk_callback`` function. This function is
called when the urb is finished by the USB subsystem. The callback
function is called in interrupt context, so caution must be taken not to
do very much processing at that time. Our implementation of
``skel_write_bulk_callback`` merely reports if the urb was completed
successfully or not and then returns.
The read function works a bit differently from the write function in
that we do not use an urb to transfer data from the device to the
driver. Instead we call the :c:func:`usb_bulk_msg` function, which can be used
to send or receive data from a device without having to create urbs and
handle urb completion callback functions. We call the :c:func:`usb_bulk_msg`
function, giving it a buffer into which to place any data received from
the device and a timeout value. If the timeout period expires without
receiving any data from the device, the function will fail and return an
error message. This can be shown with the following code::
/* do an immediate bulk read to get data from the device */
retval = usb_bulk_msg (skel->dev,
usb_rcvbulkpipe (skel->dev,
skel->bulk_in_endpointAddr),
skel->bulk_in_buffer,
skel->bulk_in_size,
&count, 5000);
/* if the read was successful, copy the data to user space */
if (!retval) {
if (copy_to_user (buffer, skel->bulk_in_buffer, count))
retval = -EFAULT;
else
retval = count;
}
The :c:func:`usb_bulk_msg` function can be very useful for doing single reads
or writes to a device; however, if you need to read or write constantly to
a device, it is recommended to set up your own urbs and submit them to
the USB subsystem.
When the user program releases the file handle that it has been using to
talk to the device, the release function in the driver is called. In
this function we decrement our private usage count and wait for possible
pending writes::
/* decrement our usage count for the device */
--skel->open_count;
One of the more difficult problems that USB drivers must be able to
handle smoothly is the fact that the USB device may be removed from the
system at any point in time, even if a program is currently talking to
it. It needs to be able to shut down any current reads and writes and
notify the user-space programs that the device is no longer there. The
following code (function ``skel_delete``) is an example of how to do
this::
static inline void skel_delete (struct usb_skel *dev)
{
kfree (dev->bulk_in_buffer);
if (dev->bulk_out_buffer != NULL)
usb_free_coherent (dev->udev, dev->bulk_out_size,
dev->bulk_out_buffer,
dev->write_urb->transfer_dma);
usb_free_urb (dev->write_urb);
kfree (dev);
}
If a program currently has an open handle to the device, we reset the
flag ``device_present``. For every read, write, release and other
functions that expect a device to be present, the driver first checks
this flag to see if the device is still present. If not, it releases
that the device has disappeared, and a ``-ENODEV`` error is returned to the
user-space program. When the release function is eventually called, it
determines if there is no device and if not, it does the cleanup that
the ``skel_disconnect`` function normally does if there are no open files
on the device (see Listing 5).
Isochronous Data
================
This usb-skeleton driver does not have any examples of interrupt or
isochronous data being sent to or from the device. Interrupt data is
sent almost exactly as bulk data is, with a few minor exceptions.
Isochronous data works differently with continuous streams of data being
sent to or from the device. The audio and video camera drivers are very
good examples of drivers that handle isochronous data and will be useful
if you also need to do this.
Conclusion
==========
Writing Linux USB device drivers is not a difficult task as the
usb-skeleton driver shows. This driver, combined with the other current
USB drivers, should provide enough examples to help a beginning author
create a working driver in a minimal amount of time. The linux-usb-devel
mailing list archives also contain a lot of helpful information.
Resources
=========
The Linux USB Project:
http://www.linux-usb.org/
Linux Hotplug Project:
http://linux-hotplug.sourceforge.net/
linux-usb Mailing List Archives:
https://lore.kernel.org/linux-usb/
Programming Guide for Linux USB Device Drivers:
https://lmu.web.psi.ch/docu/manuals/software_manuals/linux_sl/usb_linux_programming_guide.pdf
USB Home Page: https://www.usb.org