summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorAidan MacDonald <amachronic@protonmail.com>2021-09-19 11:44:38 +0100
committerAidan MacDonald <amachronic@protonmail.com>2021-10-16 15:58:43 -0400
commitec164c389c99d8129f9d6cacda2731bde9b08257 (patch)
tree224a2f675de8e6ce82f179b38cbe44326db30ddd /docs
parent71cc1e78fd81818428cbd1b55fcf096979b529ef (diff)
downloadrockbox-ec164c389c99d8129f9d6cacda2731bde9b08257.tar.gz
rockbox-ec164c389c99d8129f9d6cacda2731bde9b08257.zip
usb: introduce new control request API
Change-Id: I6545d8985ab683c026f28f6a7c0e23b40d0a6506
Diffstat (limited to 'docs')
-rw-r--r--docs/usb-api.md144
1 files changed, 144 insertions, 0 deletions
diff --git a/docs/usb-api.md b/docs/usb-api.md
new file mode 100644
index 0000000000..a21d6fd703
--- /dev/null
+++ b/docs/usb-api.md
@@ -0,0 +1,144 @@
1Handling USB control requests
2=============================
3
4API overview
5------------
6
7 enum usb_control_response {
8 USB_CONTROL_ACK,
9 USB_CONTROL_STALL,
10 USB_CONTROL_RECEIVE,
11 };
12
13 void usb_core_control_request(struct usb_ctrlrequest* req, void* reqdata);
14 void usb_core_control_complete(int status);
15 void usb_drv_control_response(enum usb_control_response resp,
16 void* data, int length);
17
18The two `usb_core` functions are common to all targets with a USB stack and
19are implemented in `usb_core.c`. The USB driver calls them to inform the core
20when a control request arrives or is completed.
21
22Each USB driver implements `usb_drv_control_response()`. The core calls this
23to let the driver know how to respond to each control request.
24
25### Legacy API
26
27 void usb_core_legacy_control_request(struct usb_ctrlrequest* req);
28
29The old control request API is available through this function. Drivers which
30don't yet implement the new API can use the legacy API instead. To support
31legacy drivers, the USB core implements all functions in the new API and
32emulates the old control request handling behavior, bugs included.
33
34This is intended as a stopgap measure so that old drivers keep working as-is.
35The core can start using the new API right away, and drivers can be ported
36one-by-one as time allows. Once all drivers are ported to the new API, all
37legacy driver support can be removed.
38
39Request handling process
40------------------------
41
42The driver submits control requests to the USB core one at a time. Once a
43request is submitted, it must be completed before the next request can be
44submitted. This mirrors normal USB operation.
45
46When the USB driver receives a setup packet from the host, it submits it
47to the core to begin handling the control transfer. The driver calls
48`usb_core_control_request(req, NULL)`, passing the setup packet in `req`.
49The second argument, `reqdata`, is not used at this time and is passed
50as `NULL`.
51
52The core processes the setup packet and calls `usb_drv_control_response()`
53when it's done. The allowed responses depend on the type of control transfer
54being processed.
55
56### Non-data transfers
57
58- `USB_CONTROL_ACK`, to indicate the request was processed successfully.
59- `USB_CONTROL_STALL`, if the request is unsupported or cannot be processed.
60
61### Control read transfers
62
63- `USB_CONTROL_ACK`, to indicate the request was processed successfully.
64 The core must provide a valid `data` buffer with `length` not exceeding
65 the `wLength` field in the setup packet; otherwise, driver behavior is
66 undefined. The driver will transfer this data to the host during the
67 data phase of the control transfer, and then acknowledge the host's OUT
68 packet to complete the transfer successfully.
69- `USB_CONTROL_STALL`, if the request is unsupported or cannot be processed.
70
71### Control write transfers
72
73The driver calls `usb_core_control_request()` twice to handle control writes.
74The first call allows the core to handle the setup packet, and if the core
75decides to accept the data phase, the second call is made when the data has
76been received without error.
77
78#### Setup phase
79
80The first call is made at the end of the setup phase, after receiving the
81setup packet. The driver passes `reqdata = NULL` to indicate this.
82
83The core can decide whether it wants to receive the data phase:
84
85- `USB_CONTROL_RECEIVE`, if the core wishes to continue to the data phase.
86 The core must provide a valid `data` buffer with `length` greater than or
87 equal to the `wLength` specified in the setup packet; otherwise, driver
88 behavior is undefined. The driver will proceed to the data phase and store
89 received data into the provided buffer.
90- `USB_CONTROL_STALL`, if the request is unsupported or cannot be processed.
91
92If the core accepts the data phase, the driver will re-submit the request
93when the data phase is completed correctly. If any error occurs during the
94data phase, the driver will not re-submit the request; instead, it will
95call `usb_core_control_complete()` with a non-zero status code.
96
97#### Status phase
98
99The second call to `usb_core_control_request()` is made at the end of the data
100phase. The `reqdata` passed by the driver is the same one that the core passed
101in its `USB_CONTROL_RECEIVE` response.
102
103The core's allowed responses are:
104
105- `USB_CONTROL_ACK`, to indicate the request was processed successfully.
106- `USB_CONTROL_STALL`, if the request is unsupported or cannot be processed.
107
108### Request completion
109
110The driver will notify the core when a request has completed by calling
111`usb_core_control_complete()`. A status code of zero means the request was
112completed successfully; a non-zero code means it failed. Note that failure
113can occur even if the request was successful from the core's perspective.
114
115If the core response is `USB_CONTROL_STALL` at any point, the request is
116considered complete. In this case, the driver won't deliver a completion
117notification because it would be redundant.
118
119The driver may only complete a request after the core has provided a response
120to any pending `usb_core_control_request()` call. Specifically, if the core
121has not yet responded to a request, the driver needs to defer the completion
122notification until it sees the core's response. If the core's response is a
123stall, then the notification should be silently dropped.
124
125### Notes
126
127- Driver behavior is undefined if the core makes an inappropriate response
128 to a request, for example, responding with `USB_CONTROL_ACK` in the setup
129 phase of a control write or `USB_CONTROL_RECEIVE` to a non-data request.
130 The only permissible responses are the documented ones.
131
132- If a response requires a buffer, then `data` must be non-NULL unless the
133 `length` is also zero. If a buffer is not required, the core must pass
134 `data = NULL` and `length = 0`. Otherwise, driver behavior is undefined.
135 There are two responses which require a buffer:
136 + `USB_CONTROL_ACK` to a control read
137 + `USB_CONTROL_RECEIVE` to the setup phase of a control write
138
139- Drivers must be prepared to accept a setup packet at any time, including
140 in the middle of a control request. In such a case, devices are required
141 to abort the ongoing request and start handling the new request. (This is
142 intended as an error recovery mechanism and should not be abused by hosts
143 in normal operation.) The driver must take care to notify the core of the
144 current request's failure, and then submit the new request.