85 lines
3.4 KiB
ReStructuredText
85 lines
3.4 KiB
ReStructuredText
==============
|
|
USB Raw Gadget
|
|
==============
|
|
|
|
USB Raw Gadget is a kernel module that provides a userspace interface for
|
|
the USB Gadget subsystem. Essentially it allows to emulate USB devices
|
|
from userspace. Enabled with CONFIG_USB_RAW_GADGET. Raw Gadget is
|
|
currently a strictly debugging feature and shouldn't be used in
|
|
production, use GadgetFS instead.
|
|
|
|
Comparison to GadgetFS
|
|
~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Raw Gadget is similar to GadgetFS, but provides a more low-level and
|
|
direct access to the USB Gadget layer for the userspace. The key
|
|
differences are:
|
|
|
|
1. Every USB request is passed to the userspace to get a response, while
|
|
GadgetFS responds to some USB requests internally based on the provided
|
|
descriptors. However note, that the UDC driver might respond to some
|
|
requests on its own and never forward them to the Gadget layer.
|
|
|
|
2. GadgetFS performs some sanity checks on the provided USB descriptors,
|
|
while Raw Gadget allows you to provide arbitrary 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.
|
|
|
|
4. Raw Gadget explicitly exposes information about endpoints addresses and
|
|
capabilities allowing a user to write UDC-agnostic gadgets.
|
|
|
|
5. Raw Gadget has ioctl-based interface instead of a filesystem-based one.
|
|
|
|
Userspace interface
|
|
~~~~~~~~~~~~~~~~~~~
|
|
|
|
To create a Raw Gadget instance open /dev/raw-gadget. Multiple raw-gadget
|
|
instances (bound to different UDCs) can be used at the same time. The
|
|
interaction with the opened file happens through the ioctl() calls, see
|
|
comments in include/uapi/linux/usb/raw_gadget.h for details.
|
|
|
|
The typical usage of Raw Gadget looks like:
|
|
|
|
1. Open Raw Gadget instance via /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 calls to receive events from
|
|
Raw Gadget and react to those depending on what kind of USB device
|
|
needs to be emulated.
|
|
|
|
Note, that some UDC drivers have fixed addresses assigned to endpoints, and
|
|
therefore arbitrary endpoint addresses can't be used in the descriptors.
|
|
Nevertheles, Raw Gadget provides a UDC-agnostic way to write USB gadgets.
|
|
Once a USB_RAW_EVENT_CONNECT event is received via USB_RAW_IOCTL_EVENT_FETCH,
|
|
the USB_RAW_IOCTL_EPS_INFO ioctl can be used to find out information about
|
|
endpoints that the UDC driver has. Based on that information, the user must
|
|
chose UDC endpoints that will be used for the gadget being emulated, and
|
|
properly assign addresses in endpoint descriptors.
|
|
|
|
You can find usage examples (along with a test suite) here:
|
|
|
|
https://github.com/xairy/raw-gadget
|
|
|
|
Internal details
|
|
~~~~~~~~~~~~~~~~
|
|
|
|
Currently every endpoint read/write ioctl submits a USB request and waits until
|
|
its completion. This is the desired mode for coverage-guided fuzzing (as we'd
|
|
like all USB request processing happen during the lifetime of a syscall),
|
|
and must be kept in the implementation. (This might be slow for real world
|
|
applications, thus the O_NONBLOCK improvement suggestion below.)
|
|
|
|
Potential future improvements
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
- Report more events (suspend, resume, etc.) through USB_RAW_IOCTL_EVENT_FETCH.
|
|
|
|
- Support O_NONBLOCK I/O.
|
|
|
|
- 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).
|