summaryrefslogtreecommitdiff
path: root/src/portable/linux/raw_gadget/README.md
blob: ab0aaef3f9b0c4de4bb6f23bdb672c56a432f4ec (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# Linux Raw Gadget device controller driver

This directory implements a TinyUSB device controller driver (DCD) for the
Linux Raw Gadget userspace API. It allows TinyUSB device examples and tests to
run as software USB devices through a Linux USB device controller, normally
`dummy_hcd`/`dummy_udc`.

## Architecture

The port consists of two layers:

- `dcd_raw_gadget.c` adapts the TinyUSB DCD API to the platform-neutral Raw
  Gadget HAL.
- `raw_gadget_*.c` implements the Linux Raw Gadget lifecycle, UDC discovery,
  endpoint management, event handling and asynchronous transfers.

Raw Gadget ioctls block while waiting for USB activity. The implementation
therefore uses one event worker and at most one transfer worker per endpoint
address. TinyUSB callbacks are serialized and are always delivered with
`in_isr == false`.

Endpoint zero requires special handling because TinyUSB and Raw Gadget expose
different control-transfer semantics:

- TinyUSB may submit an IN data stage in several endpoint-sized chunks, while
  Raw Gadget expects the complete EP0 IN data stage in one ioctl. The HAL
  aggregates these chunks before issuing `USB_RAW_IOCTL_EP0_WRITE`.
- Raw Gadget completes the status stage as part of data-bearing control
  requests. The subsequent logical zero-length status transfer submitted by
  TinyUSB is therefore completed synthetically.
- Requests without a data stage use Raw Gadget's delayed-status mechanism and
  require a real EP0 ioctl.

A transfer generation counter prevents completions from transfers cancelled by
a bus reset from reaching the new TinyUSB device state.

## Requirements

- Linux with `CONFIG_USB_RAW_GADGET` enabled
- `raw_gadget` kernel module
- A userspace-accessible `/dev/raw-gadget`
- A USB device controller visible in `/sys/class/udc`
- `dummy_hcd` when no physical UDC is used
- POSIX threads

The current UDC discovery maps TinyUSB root-hub port `n` to a UDC named
`dummy_udc.n`.

## Supported functionality

The port supports the transfer types provided reliably by the Linux Raw Gadget
interface:

- Control
- Bulk
- Interrupt

The implementation has been exercised with TinyUSB CDC ACM, including
enumeration, class control requests, interrupt endpoint configuration,
bidirectional bulk transfers, zero-length packets and a 256 KiB echo transfer.

## Limitations

### Isochronous transfers

Isochronous endpoints are intentionally not supported. Linux Raw Gadget does
not provide complete isochronous transfer support, so
`dcd_edpt_iso_alloc()` and `dcd_edpt_iso_activate()` return `false`. This is a
platform limitation, not an unimplemented transfer path in the DCD.

### Software disconnect and remote wakeup

Raw Gadget does not expose a reversible software-disconnect ioctl or a remote
wakeup operation. `dcd_disconnect()` and `dcd_remote_wakeup()` therefore have
no effect. Closing the Raw Gadget file descriptor disconnects and destroys the
instance during DCD deinitialization.

### Start-of-frame events

Raw Gadget does not expose SOF events. `dcd_sof_enable()` is a no-op.

### Endpoint FIFO API

The optional `dcd_edpt_xfer_fifo()` API is not implemented. TinyUSB uses the
normal buffer transfer API for this port.

## Threading and callback rules

The HAL owns all worker threads. Application code must not call the HAL
functions directly; TinyUSB accesses them through `dcd_raw_gadget.c`.

Raw Gadget event callbacks:

- may run on an implementation-owned worker thread;
- are serialized by the HAL;
- must not block indefinitely;
- must not retain pointers to event objects after returning.

## Security and permissions

Access to `/dev/raw-gadget` normally requires elevated privileges. Prefer a
narrow udev rule or dedicated group over running the complete test application
as root. The exact policy is distribution-specific and is intentionally not
installed by this port.