summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorhathach <[email protected]>2026-06-17 16:27:03 +0700
committerhathach <[email protected]>2026-06-18 15:56:23 +0700
commit6d74543ce6b3d79c2ba24e11f23fccad52571464 (patch)
tree182af4da33de7771851db81926b65fc639ae005c /src
parentde341b14abe3bc3e25962cbb26aa61bc0126adcf (diff)
dcd/stm32_fsdev: restore CH32 EP0 CONTROL type when stalling
The CH32 workaround only restored EP0 to CONTROL in edpt_xfer(). When the stack rejects a control write with data (handle_ctr_setup having already switched EP0 to BULK) it stalls EP0 via dcd_edpt_stall() without ever calling dcd_edpt_xfer(), leaving EP0 typed BULK+STALL. As SETUP recognition is tied to CONTROL-typed endpoints, the host's recovery SETUP (which should auto-clear the stall) would be ignored, wedging EP0 until a bus reset. Restore CONTROL for EP0 in the same exclusive write that sets the STALL status. DFU download-in-wrong-state is a concrete trigger. Co-Authored-By: Claude Fable 5 <[email protected]>
Diffstat (limited to 'src')
-rw-r--r--src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c8
1 files changed, 8 insertions, 0 deletions
diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
index 6279f8102..f5a8beb65 100644
--- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
+++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
@@ -833,6 +833,14 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) {
ep_reg &= U_EPREG_MASK | EP_STAT_MASK(dir);
ep_change_status(&ep_reg, dir, EP_STAT_STALL);
+#if defined(TUP_USBIP_FSDEV_CH32)
+ // Stall ends the transfer without edpt_xfer() (the only other CONTROL restore); else a rejected
+ // control-write leaves EP0 typed BULK and the host's recovery SETUP is ignored until bus reset.
+ if (ep_num == 0u) {
+ ep_reg = (ep_reg & ~U_EP_T_FIELD) | U_EP_CONTROL;
+ }
+#endif
+
ep_write(ep_idx, ep_reg, true);
}