HID: asus: wait for MCU ready before detecting Ally capabilities (cold-boot race leaves gamepad endpoint silent) - #7
Conversation
ally_config_create() issues the seven CMD_CHECK_* capability queries as
the first traffic on the configuration interface, before anything has
confirmed the MCU is ready. The queries are single-shot with no retry,
and a failed or garbled reply is indistinguishable from "unsupported".
On cold boot the MCU can still be starting up at probe time; when that
happens every support flag reads false, the turbo button attributes are
never created, and - because xbox_controller_support is also false -
CMD_SET_XBOX_CONTROLLER(1) is never sent, leaving the gamepad interrupt
endpoint silent until some userspace component happens to enable
reporting over hidraw. Warm reboots probe with the MCU already up and
work correctly, which makes the failure intermittent and easy to miss.
Field data (ROG Xbox Ally X, RC73XA): on an affected boot, sysfs showed
xbox_controller reading -ENODEV and all capability-gated attributes
missing, while a raw CMD_CHECK_XBOX_SUPPORT query (5a d1 0c 01 00)
issued moments later was answered "supported" (5a d1 0c 01 01); a
subsequent warm boot probed with xbox_controller=1 and the full
attribute tree present.
Fix: call ally_gamepad_check_ready() - which retries and waits - before
ally_detect_capabilities(), per that function's documented contract
("should be called ... after the asus handshake has been performed on
the configuration endpoint"; hid_asus_ally_init() already runs later in
the same probe path, so the handshake precondition holds here too). The
later ready check in hid_asus_ally_init() is kept: once the MCU is up
it is a single fast round-trip, and it still covers the resume path.
If the MCU never becomes ready, probe of the configuration interface
now fails in ally_config_create() instead of moments later in
hid_asus_ally_init() - the terminal outcome is unchanged.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01M3pWeekLNWsrqafc9erby3
Full diagnostic detail (for the record)Code path on the current
Downstream effects of the all-false race, all inside
Field investigation that isolated this (ROG Xbox Ally X,
Why the fix is shaped this way:
Cross-model: Compatibility with #6: verified beyond inspection — this patch applies cleanly on top of the #6 branch, and the combined tree (ally head + #6 + this) compiles Validation status: compile-tested only, by design — the race is cold-boot intermittent, so on-demand repro is slow. The diagnosis above is from live hardware. Offer stands to run a cold-boot soak of this branch (repeated cold boots checking |
Problem
ally_config_create()fires the sevenCMD_CHECK_*capability queries as the first traffic on the configuration interface — before anything has confirmed the MCU is ready. Each query is single-shot with no retry, and a failed/garbled reply is indistinguishable from "unsupported".ally_gamepad_check_ready()(which does retry) only runs afterwards, fromhid_asus_ally_init(), violating its own documented contract that it should precede this kind of traffic.On a cold boot the MCU can still be starting up at probe time. When the race fires, every support flag reads false, so:
-ENODEV;xbox_controller_supportis false,CMD_SET_XBOX_CONTROLLER(1)is never sent — the gamepad interrupt endpoint stays silent from boot unless some userspace component (e.g. InputPlumber) happens to enable reporting over hidraw on its own.Warm reboots probe with the MCU already up and work fine, which makes this intermittent and easy to blame on other components. We spent considerable effort on exactly that before isolating it (originally reported in the #2 test thread).
Field evidence (ROG Xbox Ally X, RC73XA)
xbox_controllerread-ENODEV, capability-gated attributes missing — yet a rawCMD_CHECK_XBOX_SUPPORT(5a d1 0c 01 00) issued moments later over the same hidraw answered supported (5a d1 0c 01 01), a reply the driver's own parser would accept.xbox_controller=1, full attribute tree present, driver sent the enable itself — same kernel, same module.Fix
Call
ally_gamepad_check_ready()at the top ofally_config_create(), beforeally_detect_capabilities(). One forward declaration + one call site; the existing retry policy is unchanged. The later ready check inhid_asus_ally_init()is kept — once the MCU is up it's a single fast round-trip, and it still covers the resume path. If the MCU never becomes ready, cfg-interface probe now fails inally_config_create()instead of moments later inhid_asus_ally_init()— same terminal outcome as today.Cross-model:
CMD_CHECK_READYis common MCU protocol used identically for all Ally models on this interface; the change only reorders traffic on the same endpoint under the same handshake precondition (hid_asus_ally_init()already runs later in this probe path).Validation
Compile-tested
W=1clean against the 7.2 ally headers. Runtime: the bug's cold-boot intermittency makes on-demand reproduction slow; diagnosis above is from live hardware, and I'm happy to run a cold-boot soak of this branch on the Xbox Ally X if you want field confirmation before merging.Independent of #6 (different functions; both branches are based on current
allyand won't conflict).🤖 Generated with Claude Code
https://claude.ai/code/session_01M3pWeekLNWsrqafc9erby3