This repository was archived by the owner on Mar 26, 2026. It is now read-only.
Commit 539adf8
Add SETUP_EP0_OUT_BUF(), for OUT control transfers.
When processing OUT control transfers, the EP0 buffer is armed when
wriging EP0BCL, while SDPAUTO is high. At this stage it's not
necessary to set HSNAK, because that bit has an effect on the status
stage, not on the data stage.
Beyond it being not necessary to write HSNAK early, it introduces a
race condition, because the host sees the status stage complete early,
before we have fully processed the content of EP0BUF, and as such it
thinks it can send more control transfers. If the host actually sends
more control transfers, then EP0BUF might be overwritten before we have
completed processing EP0BUF, and this can cause data corruption.
The clean way to handle this, is to force the host to wait in the status
stage until we have fully processed the EP0BUF, by NAK-ink the status
stage. This does not mean that the packets in the Data stage will be
NAK'd because, that is controlled by whether the buffer is armed or not.
This commit deprecates `SETUP_EP0_BUF(length)`, and introduces:
- `SETUP_EP0_IN_BUF(length)` as a direct replacement for IN transfers
- `SETUP_EP0_OUT_BUF()` as a new macro to perform OUT transfers
The new recommended way to do OUT control transfers is:
```c
for (each_expected_packet) {
SETUP_EP0_OUT_BUF();
handle_packet(EP0BUF, EP0BCL);
// EP0BCL will have the size of the received packet
}
ACK_EP0();
```
That is: only call `ACK_EP0()`, which clears HSNAK by writing 1 to it,
after we know it's safe to overwrite EP0BUF.
Note: a simple way to reproduce the issue when not following this
procedure, is to run:
```bash
while true; do lsusb -v -d $(DEVICE_VID):$(DEVICE_PID) > /dev/null; done
```
In a terminal. (replacing DEVICE_VID/DEVICE_PID with correct values)
While this loop is running, we expected most applications doing control
out transfers with the old method to become unusable.
Technically speaking a single run of `lsusb` could even cause trouble if
it happes at the wrong time, and I think this could be triggered in
other situations as well, this is just the easiest way to reproduce the
problem.1 parent cdebf41 commit 539adf8
1 file changed
Lines changed: 41 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
53 | 53 | | |
54 | 54 | | |
55 | 55 | | |
56 | | - | |
57 | | - | |
58 | | - | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
59 | 72 | | |
60 | 73 | | |
61 | 74 | | |
| |||
64 | 77 | | |
65 | 78 | | |
66 | 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 | + | |
67 | 105 | | |
68 | 106 | | |
69 | 107 | | |
| |||
0 commit comments