acrn-kernel/Documentation/usb/raw-gadget.rst

95 lines
3.7 KiB
ReStructuredText
Raw Permalink Normal View History

==============
USB Raw Gadget
==============
USB Raw Gadget is a gadget driver that gives userspace low-level control over
the gadget's communication process.
Like any other gadget driver, Raw Gadget implements USB devices via the
USB gadget API. Unlike most gadget drivers, Raw Gadget does not implement
any concrete USB functions itself but requires userspace to do that.
Raw Gadget is currently a strictly debugging feature and should not be used
in production. Use GadgetFS instead.
Enabled with CONFIG_USB_RAW_GADGET.
Comparison to GadgetFS
~~~~~~~~~~~~~~~~~~~~~~
Raw Gadget is similar to GadgetFS but provides more direct access to the
USB gadget layer for userspace. The key differences are:
1. Raw Gadget passes every USB request to userspace to get a response, while
GadgetFS responds to some USB requests internally based on the provided
descriptors. Note that the UDC driver might respond to some requests on
its own and never forward them to the gadget layer.
2. Raw Gadget allows providing arbitrary data as responses to USB requests,
while GadgetFS performs sanity checks on the provided USB descriptors.
This makes Raw Gadget suitable for fuzzing by providing malformed data as
responses to USB requests.
3. Raw Gadget provides a way to select a UDC device/driver to bind to,
while GadgetFS currently binds to the first available UDC. This allows
having multiple Raw Gadget instances bound to different UDCs.
usb: raw-gadget: fix gadget endpoint selection Currently automatic gadget endpoint selection based on required features doesn't work. Raw Gadget tries iterating over the list of available endpoints and finding one that has the right direction and transfer type. Unfortunately selecting arbitrary gadget endpoints (even if they satisfy feature requirements) doesn't work, as (depending on the UDC driver) they might have fixed addresses, and one also needs to provide matching endpoint addresses in the descriptors sent to the host. The composite framework deals with this by assigning endpoint addresses in usb_ep_autoconfig() before enumeration starts. This approach won't work with Raw Gadget as the endpoints are supposed to be enabled after a set_configuration/set_interface request from the host, so it's too late to patch the endpoint descriptors that had already been sent to the host. For Raw Gadget we take another approach. Similarly to GadgetFS, we allow the user to make the decision as to which gadget endpoints to use. This patch adds another Raw Gadget ioctl USB_RAW_IOCTL_EPS_INFO that exposes information about all non-control endpoints that a currently connected UDC has. This information includes endpoints addresses, as well as their capabilities and limits to allow the user to choose the most fitting gadget endpoint. The USB_RAW_IOCTL_EP_ENABLE ioctl is updated to use the proper endpoint validation routine usb_gadget_ep_match_desc(). These changes affect the portability of the gadgets that use Raw Gadget when running on different UDCs. Nevertheless, as long as the user relies on the information provided by USB_RAW_IOCTL_EPS_INFO to dynamically choose endpoint addresses, UDC-agnostic gadgets can still be written with Raw Gadget. Fixes: f2c2e717642c ("usb: gadget: add raw-gadget interface") Signed-off-by: Andrey Konovalov <andreyknvl@google.com> Signed-off-by: Felipe Balbi <balbi@kernel.org>
2020-05-08 01:06:56 +08:00
4. Raw Gadget explicitly exposes information about endpoints addresses and
capabilities. This allows the user to write UDC-agnostic gadgets.
5. Raw Gadget has an ioctl-based interface instead of a filesystem-based
one.
Userspace interface
~~~~~~~~~~~~~~~~~~~
The user can interact with Raw Gadget by opening ``/dev/raw-gadget`` and
issuing ioctl calls; see the comments in include/uapi/linux/usb/raw_gadget.h
for details. Multiple Raw Gadget instances (bound to different UDCs) can be
used at the same time.
A typical usage scenario of Raw Gadget:
1. Create a Raw Gadget instance by opening ``/dev/raw-gadget``.
2. Initialize the instance via ``USB_RAW_IOCTL_INIT``.
3. Launch the instance with ``USB_RAW_IOCTL_RUN``.
4. In a loop issue ``USB_RAW_IOCTL_EVENT_FETCH`` to receive events from
Raw Gadget and react to those depending on what kind of USB gadget must
be implemented.
Note that some UDC drivers have fixed addresses assigned to endpoints, and
therefore arbitrary endpoint addresses cannot be used in the descriptors.
Nevertheless, Raw Gadget provides a UDC-agnostic way to write USB gadgets.
Once ``USB_RAW_EVENT_CONNECT`` is received via ``USB_RAW_IOCTL_EVENT_FETCH``,
``USB_RAW_IOCTL_EPS_INFO`` can be used to find out information about the
endpoints that the UDC driver has. Based on that, userspace must choose UDC
endpoints for the gadget and assign addresses in the endpoint descriptors
correspondingly.
Raw Gadget usage examples and a test suite:
https://github.com/xairy/raw-gadget
Internal details
~~~~~~~~~~~~~~~~
Every Raw Gadget endpoint read/write ioctl submits a USB request and waits
until its completion. This is done deliberately to assist with coverage-guided
fuzzing by having a single syscall fully process a single USB request. This
feature must be kept in the implementation.
Potential future improvements
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Report more events (suspend, resume, etc.) through
``USB_RAW_IOCTL_EVENT_FETCH``.
- Support ``O_NONBLOCK`` I/O. This would be another mode of operation, where
Raw Gadget would not wait until the completion of each USB request.
- Support USB 3 features (accept SS endpoint companion descriptor when
enabling endpoints; allow providing ``stream_id`` for bulk transfers).
- Support ISO transfer features (expose ``frame_number`` for completed
requests).