mirror of
https://github.com/hathach/tinyusb.git
synced 2026-06-25 06:24:18 +00:00
dcd/wch: drop toggle-mismatched OUT packets on all USBFS variants
The OUT data-toggle check -- drop a packet whose DATA0/DATA1 doesn't match the expected toggle (a host retransmit after a lost ACK, or a host that doesn't alternate the toggle) -- only ran on CH58x. The auto-toggle parts (V103/V20x/V307/ X035) never checked it, so a duplicate/retransmitted OUT was processed twice. HiFiPhile confirmed it: a host patched to send DATA0-only had CH32V305 accept every packet. Move the TOG_OK gate out of the CH58x-only block so it runs on every variant; the manual toggle flip stays CH58x-only. EP0 keeps its own toggle via the SETUP/status flow and is exempt. Verified on ci.lan HIL: ch582m_evt (CH58x), ch32v103r_r1_1v0 (V103), nanoch32v203 (V203) all pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@ -335,17 +335,15 @@ void dcd_int_handler(uint8_t rhport) {
|
||||
|
||||
switch (token) {
|
||||
case PID_OUT: {
|
||||
// Drop an OUT packet whose data toggle doesn't match what we expect -- a host retransmit
|
||||
// after a lost ACK, or a host that doesn't alternate DATA0/DATA1. The hardware auto-toggle
|
||||
// does not reject these on its own, so the check is needed on every variant. EP0 keeps its
|
||||
// own toggle via the SETUP/status flow and is exempt.
|
||||
if (ep != 0 && !(int_st & USBFS_INT_ST_TOG_OK)) { break; }
|
||||
#ifdef CH32_USBFS_EP_MANUAL_TOG
|
||||
// Manual toggle. EP0 has no hardware auto-toggle (RB_UEP_AUTO_TOG covers only EP1/2/3/5/6/7),
|
||||
// so advance its RX toggle on every OUT and always process it; a control-OUT data stage
|
||||
// longer than the EP0 packet size would otherwise stall on the second packet. For the other
|
||||
// endpoints, drop toggle-mismatched OUT (host retransmit) and flip the expected RX toggle.
|
||||
if (ep == 0) {
|
||||
EP_CTRL(0) ^= USBFS_EPC_R_TOG;
|
||||
} else {
|
||||
if (!(int_st & USBFS_INT_ST_TOG_OK)) { break; }
|
||||
EP_CTRL(ep) ^= USBFS_EPC_R_TOG;
|
||||
}
|
||||
// CH58x has no hardware auto-toggle: advance the expected RX toggle after each accepted packet
|
||||
// (EP0 included -- it also has no auto-toggle and a control-OUT data stage can span packets).
|
||||
EP_CTRL(ep) ^= USBFS_EPC_R_TOG;
|
||||
#endif
|
||||
update_out(rhport, ep, rx_len);
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user