Repository navigation
Tools: keep Renode OTG EP0 setup data until the data stage is armed - #34934
Open
qamar-gmail wants to merge 1 commit into
Open
qamar-gmail wants to merge 1 commit into
qamar-gmail wants to merge 1 commit into
Conversation
When EP0 OUT is armed only for SETUP reception (transfer size 0), DeliverOutData queued a zero-length OUT packet ahead of a control-OUT data stage. ChibiOS completed the stage with no data and sent the status ZLP, so the real bytes arrived late and were discarded. CDC SET_LINE_CODING over USB/IP was acknowledged but never applied. Leave pending data queued until firmware arms a non-zero transfer; the existing EPENA path then delivers it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fix the Renode STM32 OTG model so a control-OUT data stage (for example CDC
SET_LINE_CODING) is not completed with a spurious zero-length packet. Before this fix,SET_LINE_CODINGover USB/IP was acknowledged but never reached the firmware.Classification & Testing (check all that apply and add your own)
Tested in Renode with an unmodified official firmware:
7246115b), ELF SHA-25698c099b06bcc25208b322932199f92dba69bf94d767e36aad7babe8abab61375fbea4f40portable, as published underfirmware.ardupilot.org/Tools/Renode6743a33579.AP_STM32_OTG.csthere is identical to currentmaster(blobb57d1a3)Tools/renode/run.py CubeOrangePlus --vehicle arduplane --usb --usbip-port N, inside a private user/network namespace, withlogLevel 0 sysbus.usbOtgTools/renode/tests/usb_debug_transport.USB(userspace USB/IP, no VHCI). After an initialized heartbeat on the CDC MAVLink interface it sends, on interface 0,GET_LINE_CODING, thenSET_LINE_CODING9600 8N1, thenGET_LINE_CODING00960000000008(38400)00-96-00-00-00-00-08(unchanged)00960000000008(38400)80250000000008(9600)No firmware or ChibiOS change is involved.
Description
Symptom. USB enumeration, the CDC MAVLink heartbeat and parameter traffic work over USB/IP. A
SET_LINE_CODINGfollowed byGET_LINE_CODINGdoes not round-trip on either CDC interface. The GET returns empty data, times out, or returns the old coding.Root cause.
HandleSetupPacketstores the control-OUT payload insetupAdditionalDataand queues the SETUP. At that point firmware still has EP0 OUT enabled for SETUP reception withDOEPTSIZ.XFRSIZ = 0. WhenTryDeliverOut(0)runs,DeliverOutDatacomputesremaining = 0and thereforelength = 0. It treats that as a complete transfer, disables the endpoint and queues a zero-byte OUT-data RX status with XFRC. ChibiOS sees the data stage complete with no data and sends the status-stage IN ZLP, so the host's URB completes. The real 7 bytes are delivered only when firmware next re-arms EP0 OUT, by which point they are no longer part of the request.usbOtgdebug log forSET_LINE_CODINGbefore the fix:With the fix:
Fix. In
DeliverOutData, when the endpoint has no transfer space left (remaining == 0) but host data is still pending, return without queuing anything. The existing EPENA handler inWriteEndpointalready callsTryDeliverOutwithTransferred = 0once firmware arms the data-stage transfer. Genuine zero-length host packets (data.Length == 0) still go through unchanged, because the guard requiresoffset < data.Length. The guard also applies to non-zero endpoints. There, data is likewise only meaningful once firmware has armed a transfer, and holding it inactiveOut/pendingOutmatches the existing flow-control intent described in the comment besidestate.Enabled = false.This was found while qualifying production USB CDC behaviour with unmodified firmware in a Renode-based lab. A standalone reproducer script, built on
usb_debug_transport.py, is available on request.This change and the description were prepared with AI assistance (Claude Code) and reproduced on the setup above. The "Checked by a human programmer" box is deliberately left for the reviewer and submitter.
🤖 Generated with Claude Code