Skip to content

USB gadget: speed auto-negotiation, robust host reset/suspend handling (fixes ITX Llama boot detection)#671

Open
danifunker wants to merge 2 commits into
rsta2:developfrom
danifunker:usb-autonegotiation-and-handle-resets
Open

USB gadget: speed auto-negotiation, robust host reset/suspend handling (fixes ITX Llama boot detection)#671
danifunker wants to merge 2 commits into
rsta2:developfrom
danifunker:usb-autonegotiation-and-handle-resets

Conversation

@danifunker
Copy link
Copy Markdown
Contributor

Summary

This PR makes the DWC2 USB gadget stack resilient to real-world host behavior
— full-speed-only hosts/hubs, warm reboots, and BIOS-time enumeration. The
headline features are USB speed auto-negotiation for the MSD gadget and rework
of suspend/reset handling so the device survives a host warm reboot, which
enables boot detection on the ITX Llama (and other PC BIOSes that enumerate
during POST). Addresses issue #591.

USB Auto-Negotiation

The MSD gadget previously presented a fixed high-speed configuration (512-byte
bulk packets) regardless of what the host actually negotiated, which breaks
against full-speed-only hosts/hubs.

  • New CDWUSBGadget::GetNegotiatedUSBSpeed() reads the enumerated speed from
    the DWC2 device status register (DSTS.ENUMSPD, new DWHCI_DEV_STS definitions
    in dwhci.h).
  • New virtual OnNegotiatedSpeed() hook, invoked from HandleEnumerationDone(),
    lets gadgets adapt their EP parameters when the negotiated speed differs from
    the configured one.
  • CUSBMSDGadget overrides it: the configuration descriptor is now a
    per-instance copy (m_ConfigurationDescriptor) whose bulk wMaxPacketSize is
    rewritten to 64 (FS) / 512 (HS) on enumeration, and the EP hardware is updated
    live via the new CDWUSBGadgetEndpoint::SetMaxPacketSize() (rewrites MPS in
    the IN/OUT EP control register).
  • CBW reception now requests wMaxPacketSize bytes instead of exactly 31, and
    accepts nLength >= SIZE_CBW, because hosts may pad the CBW to the packet
    boundary.

Robust suspend/reset handling (ITX Llama boot detection)

A PC BIOS enumerating during POST/warm reboot exposed several windows where
the gadget went deaf or crashed:

  • Suspend is no longer treated as a disconnect. HandleUSBSuspend() previously
    fired a PnP event leading to full EP teardown and core re-init, leaving the
    device unresponsive for >100 ms — a host that resets and enumerates inside
    that window gets hardware ACKs but the software never sees ENUMDONE/SETUP. Now
    we only abort in-flight transfers, enter StateSuspended, and let the next USB
    reset re-initialize the EPs at IRQ level.
  • Resets from StateSuspended/StateResetDone cancel EP0's stale SETUP transfer.
    Otherwise the next SETUP completes against the old transfer and is dropped
    with a wrong length (host reset storms, warm reboots).
  • EP0 is armed for SETUP already in HandleUSBReset() (matching Linux dwc2
    behavior), closing the window between ENUMDONE and OnActivate() where a fast
    host's first SETUP was ACKed by the core but dropped with length 0.
    OnActivate() is now idempotent via the new IsTransferActive() guard.
  • Malformed SETUPs no longer assert-crash. A SETUP completing with an
    unexpected length is logged, dropped, and EP0 is re-armed cleanly.
  • IN EP interrupts arriving while suspended are acknowledged without
    processing instead of tripping a state assert.

Diagnostics

Added always-on LOGNOTE traces for suspend, bus reset (with state),
enumeration done (with negotiated speed), and every EP0 SETUP request — to
diagnose hosts that bounce between speeds or reset repeatedly (issue #591).

Testing

  • Verified ITX Llama BIOS now detects the MSD gadget on cold and warm boot.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant