| ============== | |
| 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. | |
| 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 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
| - 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). |