Skip to content

Commit 620ab19

Browse files
committed
[ot] hw/opentitan: ot_usbdev: add initial host protocol and bus handling
This commit creates a new chardev for the USBDEV block over which the driver can communicate with a virtual USB host. The protocol (still under development) is documented and implemented. At the moment, only bus events (vbus handling, connection, reset, stub suspend/resume) are implemented. Signed-off-by: Amaury Pouly <[email protected]>
1 parent eb1610d commit 620ab19

File tree

5 files changed

+828
-90
lines changed

5 files changed

+828
-90
lines changed

docs/opentitan/earlgrey.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -269,9 +269,10 @@ See documentation in [`uart.md`](./uart.md).
269269

270270
### USBDEV
271271

272-
* `-chardev pty,id=usbdev` can be used to connect to the usbdev driver.
272+
* `-chardev pty,id=usbdev-cmd` can be used to connect to the usbdev driver (commands).
273+
* `-chardev pty,id=usbdev-host` can be used to connect to the usbdev driver (host).
273274

274-
See the [USBDEV documentation](usbdev.md)] for more details.
275+
See the [USBDEV documentation](usbdev.md) for more details.
275276

276277
## Useful debugging options
277278

docs/opentitan/usbdev.md

Lines changed: 111 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,22 @@
22

33
**Warning:** the USBDEV driver is still in development and not expected to work at the moment!
44

5-
## `usb` Chardev
5+
## `usbdev-cmd` Chardev
66

7-
The USBDEV driver exposes a chardev with ID `usbdev` which can used to control some aspects of the
7+
The USBDEV driver exposes a chardev with ID `usbdev-cmd` which can used to control some aspects of the
88
emulation.
99
Once connected, the driver accepts textual commands.
1010
Each command must end with a newline.
1111
The following commands are recognized:
12-
- `vbus_on`: turn on VBUS, see [#VBUS-handling](VBUS handling) for more details.
13-
- `vbus_off`: turn off VBUS, see [#VBUS-handling](VBUS handling) for more details.
12+
- `vbus_on`: turn on VBUS, see [VBUS handling](#VBUS-handling) for more details.
13+
- `vbus_off`: turn off VBUS, see [VBUS handling](#VBUS-handling) for more details.
14+
15+
## `usbdev-host` Chardev
16+
17+
The USBDEV driver exposes a chardev with ID `usbdev-host` which can used to simulate the presence of
18+
a USB host. The implementation is such that the USBDEV behaves as a server, waiting for a connection
19+
from a virtual host. Once connected, the host and device exchange binary commands following the protocol
20+
described in the [host simulation](#host-simulation) section.
1421

1522
## VBUS handling
1623

@@ -27,5 +34,103 @@ by the `vbus-override` property which can be set on the command-line by
2734
will be completely independent of the presence of a USB host.
2835
- `vbus-override=off`: in this mode, the `vbus_on` and `vbus_off` commands control a virtual "VBUS
2936
enable" gate. The VBUS sense pin will be reported as level high if and only if the VBUS enable
30-
gate is enabled **and** a USB host is connected to the driver.
31-
By default, the VBUS gate is disabled.
37+
gate is enabled **and** a USB host has enabled VBUS (see [host simulation](#host-simulation))
38+
By default, the VBUS gate is enabled.
39+
40+
## Host simulation
41+
42+
The QEMU USBDEV driver only simulates a USB device controller (UDC) which requires the presence
43+
of a USB host. A (virtual) host exchanges messages with the UDC over the [`udev-host` chardev](#usbdev-host-chardev).
44+
This binary protocol is somewhat similar to the [USB/IP][usbip]
45+
protocol but lower level. This protocol is also different from the [USB network redirection (a.k.a usbredir)][usbredir]
46+
protocol supported by QEMU.
47+
48+
[usbip]: (https://docs.kernel.org/usb/usbip_protocol.html)
49+
[usbredir]: (https://gitlab.freedesktop.org/spice/usbredir/-/blob/main/docs/usb-redirection-protocol.md)
50+
51+
### Rationale for a different protocol
52+
53+
Both the USB/IP and usbredir protocols are too high-level for the purpose of emulating and testing a low-level
54+
UDC driver. For example, both protocols require that the device be fully enumerated and configured before the
55+
host is even made aware of its presence. In contrast, we want to be able to fully emulate the enumeration sequence.
56+
Another big difference is bus management: USB/IP does not support bus resets and usbredir does not support resume/suspend,
57+
and neither models VBUS. This is a side-effect of the intended use case of these protocols: to connect a real USB device
58+
to a virtual USB host. However, this new protocol should be low-level enough that it is possible to implement a
59+
bridge from either usbredir or USB/IP to this protocol (while losing some features).
60+
61+
### High-level overview
62+
63+
This protocol does not specify which of the device or the host should be the client/guest.
64+
On connection, the client must send a [`Hello` command](#hello-command), to which the server
65+
must respond with another `Hello` command. After that, messages are exchanged asynchronously.
66+
67+
#### Bus states
68+
69+
The protocol reflects the low-level details of the USB bus and provides independent
70+
handling of VBUS (controlled by the host) and connection (controlled by the device).
71+
The host can turn VBUS on and off at any point. When VBUS is on, the device can freely
72+
connect or disconnect by asynchronously sending a message to the host. As on a real bus,
73+
turning off VBUS disconnects the device. VBUS is assumed to be initially off.
74+
75+
It is an error for the device to send a message when VBUS is not on and the host must ignore such
76+
messages. However due to the asynchronous nature of the protocol, it is possible for the host to
77+
receive a message event *after* sending a `VBUS Off` message which was sent *before* reception of
78+
this message by the device. The ID of the message makes it clear when this is the case so that
79+
the host can safely ignore those messages.
80+
81+
When VBUS is turned on, the host assumes that the device is *not* connected. The device must
82+
send a `Connect` message to notify the host.
83+
84+
While VBUS is turned on, the host can reset, suspend or resume the device. As on a real bus,
85+
the device will become unconfigured after a bus reset and an enumeration sequence must be performed.
86+
87+
**TODO** Clarify suspend/resume
88+
89+
### Packet format
90+
91+
The protocol is based on packets which are exchanged asynchronously by the device and host. Each packet starts
92+
with a header followed by a payload. All fields are in little-endian.
93+
94+
| **Field** | **Offset** | **Size** | **Value** |
95+
| --------- | ---------- | -------- | --------- |
96+
| Command | 0 | 4 | Command number (see below) |
97+
| Size | 4 | 4 | Size of the payload (header excluded)
98+
| Packet ID | 8 | 4 | Unique ID used to match responses |
99+
100+
The host must increase the ID of its message by one each time it sends a message.
101+
The ID used by the device is defined in the respective sections of their commands.
102+
103+
The following commands are defined.
104+
105+
| **Command** | **Value** | **Direction** | **Description** | **Reference** |
106+
| ----------- | --------- | ------------- | --------------- | ------------- |
107+
| Invalid | 0 | N/A | To avoid 0 meaning something | |
108+
| Hello | 1 | Both | First packet sent when connecting | [`Hello` command](#hello-command) |
109+
| VBUS On | 2 | Host to device | Turn VBUS on | [Bus commands](#bus-commands) |
110+
| VBUS Off | 3 | Host to device | Turn VBUS off | [Bus commands](#bus-commands) |
111+
| Connect | 4 | Device to host | Report device connection | [Bus commands](#bus-commands) |
112+
| Disconnect | 5 | Device to host | Report device disconnection | [Bus commands](#bus-commands) |
113+
| Reset | 6 | Host to device | Reset the device | [Bus commands](#bus-commands) |
114+
| Resume | 7 | Host to device | Resume the device | [Bus commands](#bus-commands) |
115+
| Suspend | 8 | Host to device | Suspend the device | [Bus commands](#bus-commands) |
116+
117+
**TODO** Add transfer commands
118+
119+
#### Hello command
120+
121+
The ID of this command must be 0.
122+
The payload of this command is defined as follows.
123+
124+
| **Field** | **Offset** | **Size** | **Value** |
125+
| --------- | ---------- | -------- | --------- |
126+
| Magic value | 0 | 4 | String `UDCX` |
127+
| Major version | 4 | 2 | 1 |
128+
| Minor version | 6 | 2 | 0 |
129+
130+
#### Bus commands
131+
132+
These commands (VBUS On/Off, (Dis)connection, Reset, Suspend/Resume) do not have any payload.
133+
See the [bus states](#bus-states) section for more detail.
134+
135+
For the Connect/Disconnect commands, which are sent by the device, the ID should be the ID of the *last command*
136+
processed by the device.

0 commit comments

Comments
 (0)