mirror of
https://github.com/hathach/tinyusb.git
synced 2026-08-18 11:02:16 +00:00
dcd_ci_fs: disarm sibling BDT on short-packet OUT completion
A multi-packet OUT transfer speculatively arms both even/odd BDTs to avoid NAK. When the host ends the transfer early with a short packet, the sibling BDT was left armed (own=1), desyncing the even/odd ping-pong so the next OUT packet landed at buffer+max_packet_size instead of buffer and the stack read stale data. Disarm the sibling on completion. Fixes device/mtp on Kinetis (GetDeviceInfo command was received into the wrong buffer half -> hang). Pre-existing (MSC only arms single-packet command receives so it never hit the double-buffer path). HIL: frdm_kl25z & frdm_k64f device 13/13. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ExGPLP5eU43LR7o6yYLpNi
This commit is contained in:
@ -175,6 +175,17 @@ static void process_tokdne(uint8_t rhport)
|
||||
return;
|
||||
}
|
||||
const unsigned length = ep->length;
|
||||
|
||||
/* Transfer is complete. For OUT, a multi-packet transfer speculatively arms the
|
||||
* sibling (even/odd) BDT to avoid NAK. When the transfer ends early - e.g. the host
|
||||
* sends a short packet before filling both buffers - that sibling is left armed
|
||||
* (own=1). A leftover armed BDT desyncs the even/odd ping-pong so the next OUT
|
||||
* packet lands in the wrong buffer half (buffer + max_packet_size instead of
|
||||
* buffer), making the stack read stale data. Disarm it here. */
|
||||
if (dir == TUSB_DIR_OUT) {
|
||||
_dcd.bdt[epnum][dir][odd ^ 1].own = 0;
|
||||
}
|
||||
|
||||
dcd_event_xfer_complete(rhport,
|
||||
tu_edpt_addr(epnum, dir),
|
||||
length - remaining, XFER_RESULT_SUCCESS, true);
|
||||
|
||||
Reference in New Issue
Block a user