From 6d74543ce6b3d79c2ba24e11f23fccad52571464 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 17 Jun 2026 16:27:03 +0700 Subject: 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 --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 8 ++++++++ 1 file changed, 8 insertions(+) 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); } -- cgit v1.3.1