mirror of
https://github.com/hathach/tinyusb.git
synced 2026-08-18 11:02:16 +00:00
dcd/musb: harden EP0 DATA_OUT against short packet and host overrun
Mirror the IN-side short-packet fix on the OUT drain: end the data stage (-> STATUS_IN) when wLength is received OR a short OUT packet (count0 < CFG_TUD_ENDPOINT0_SIZE) signals the host's end-of-data, not only when remain_wlength hits exactly 0. Also clamp the remain_wlength subtraction so a host that overruns wLength can't underflow it and strand the transfer. Without this, a control-OUT whose host sends fewer bytes than wLength left pipe0 in DATA_OUT; usbd then armed STATUS IN and tripped the split's TU_ASSERT(!dir_in). Found by /code-review; conformant hosts send exactly wLength so HIL was already green. Verified: HIL pass on ek_tm4c123gxl and max32666fthr (13/13 each). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@ -566,12 +566,13 @@ static void process_ep0_isr(uint8_t rhport) {
|
||||
if (count0) {
|
||||
TU_ASSERT(pipe0->buf, );
|
||||
tu_hwfifo_read(&musb_regs->fifo[0], pipe0->buf, count0, NULL);
|
||||
pipe0->remain_wlength -= count0;
|
||||
pipe0->remain_wlength -= tu_min16(count0, pipe0->remain_wlength); // clamp: host may overrun
|
||||
}
|
||||
// RXRDY stays set until the next edpt0_xfer arm acks it (NAK flow control):
|
||||
// edpt0_xfer(DATA OUT) for a mid-stream packet, edpt0_xfer(STATUS IN) for the last.
|
||||
pipe0->rxrdy_consumed = true;
|
||||
if (pipe0->remain_wlength == 0) {
|
||||
// Last packet: wLength received, or a short packet (host's end-of-data).
|
||||
if (pipe0->remain_wlength == 0 || count0 < CFG_TUD_ENDPOINT0_SIZE) {
|
||||
pipe0->state = PIPE0_STATE_STATUS_IN;
|
||||
}
|
||||
dcd_event_xfer_complete(rhport, TU_EP0_OUT, count0, XFER_RESULT_SUCCESS, true);
|
||||
|
||||
Reference in New Issue
Block a user