HID: asus: fix CMD_SET_MAPPING packet layout + Xbox Ally X long-press codes (full test report inside) - #2
HID: asus: fix CMD_SET_MAPPING packet layout + Xbox Ally X long-press codes (full test report inside)#2jlobue10 wants to merge 15 commits into
Conversation
The ROG ally needs to have the EC string sent back after resuming from s2idle since the USB device can be turned completely off by the firmware when mcu_powersave firmware-attribute is set to 1. This may also be true for other laptops and certain features might stop working after the device exit from sleep. Signed-off-by: Denis Benato <denis.benato@linux.dev>
Implement the core functionality for ASUS handhelds: - extend functionality of hid-asus if driver is enabled - initialise the device to a "ready" state - implement Ally X input mapping - emit a single proper event for AC button long press Signed-off-by: Khamunetri Clark <khamunetriclark@gmail.com> Signed-off-by: Denis Benato <denis.benato@linux.dev> Signed-off-by: Matthew Schwartz <matthew.schwartz@linux.dev> Signed-off-by: Luke Jones <luke@ljones.dev>
Add the base configuration structures for the gamepad configuration, detect capabilities and initialize the device in a known state. Signed-off-by: Denis Benato <denis.benato@linux.dev> Signed-off-by: Luke Jones <luke@ljones.dev>
ASUS ROG Ally handhelds support the vibration strength to be configured: add sysfs attributes to allow userspace configure motors vibration intensity. Signed-off-by: Denis Benato <denis.benato@linux.dev> Signed-off-by: Luke Jones <luke@ljones.dev>
ROG Ally devices supports configuring joysticks inner and outer range: add sysfs attributes to allow userspace modifying the sensitivity of those controllers. Signed-off-by: Denis Benato <denis.benato@linux.dev> Signed-off-by: Luke Jones <luke@ljones.dev>
ROG Ally devices allows configuring inner and outer ranges for triggers buttons on the back: allow userspace to configure the sesitivity by exposing sysfs attributes. Signed-off-by: Denis Benato <denis.benato@linux.dev> Signed-off-by: Luke Jones <luke@ljones.dev>
ROG Ally devices allow configuring the anti-deadzone parameter for the resistive joysticks devices as over time those develops drift, therefore allow userspace to configure the anti-deadzone by exposing relevant sysfs attributes. Signed-off-by: Denis Benato <denis.benato@linux.dev> Signed-off-by: Luke Jones <luke@ljones.dev>
ROG ally devices allows configuring the response curve of both joysticks, therefore add the ability of userspace to modify the response curve by exposing relevant sysfs attributes. Signed-off-by: Denis Benato <denis.benato@linux.dev> Signed-off-by: Luke Jones <luke@ljones.dev>
ROG ally devices supports a feature called turbo buttons that allows the user to quickly toggle button state by keeping a button pressed, therefore allow userspace to configure the feature by exposing relevant sysfs attributes. Signed-off-by: Denis Benato <denis.benato@linux.dev> Signed-off-by: Khamunetri Clark <khamunetriclark@gmail.com> Signed-off-by: Luke Jones <luke@ljones.dev>
Add support for buttons remapping: the ability to assign different button events to each one of the physical button on the device. Signed-off-by: Luke Jones <luke@ljones.dev> Signed-off-by: Denis Benato <denis.benato@linux.dev>
ROG Ally devices can emulate either a mouse+keyboard (desktop mode) or an gamepad device (xbox360 controller in ROG ally and a custom DInput device on newer models): add support for switching the current controller mode. Signed-off-by: Luke Jones <luke@ljones.dev> Signed-off-by: Denis Benato <denis.benato@linux.dev>
Unlike ROG ally the X version and following ones uses DInput protocol and the force feedback needs to be implemented as its protocol is vendor-specific, therefore add support for FF_RUMBLE with magnitude scaling on a work-queue based approach to avoid using possibly sleeping calls in atomic context. Assisted-by: gpt-5.3-codex Signed-off-by: Denis Benato <denis.benato@linux.dev> Signed-off-by: Khamunetri Clark <khamunetriclark@gmail.com> Signed-off-by: Luke Jones <luke@ljones.dev>
The MCU mapping block is four consecutive 11-byte BTN_CODE entries
starting at buf[5]: first remap 5-15, first macro 16-26, second remap
27-37, second macro 38-48 (cf. __btn_pair_to_pkt / BTN_CODE_LEN in
hid-asus-ally). ally_set_button_mapping() had two independent errors:
1. Remap blocks were serialized as 10 bytes with the macro type bytes
at buf[15]/buf[37], one byte early, misaligning everything after
the first remap block.
2. The value byte position is per-type (pad=1, kb=2, media=3, mouse=4)
but pad/kb/media were lumped together at byte 2, so pad mappings
were sent as {0x01, 0x00, code, ...} and the MCU read value 0x00.
Either error alone makes the MCU unmap BOTH buttons of the written
pair (the packet always carries the full pair), and the state persists
in MCU NVRAM until a correct packet is sent.
Verified on ROG Xbox Ally X (RC73YA): writing btn_a/remap killed A and
B until this fix; with it, re-sending the pair restores both buttons
(clean BTN_SOUTH/BTN_EAST press+release in evdev capture).
The Xbox Ally X (RC73YA) sends its front-button long-press events as plain keyboard-page usages F21 (0x70) and F22 (0x71) through the generic HID path, instead of the original Ally's vendor codes 0xA7 and 0x38 -- those handlers never fire on this hardware. Verified codes: left AC button: short 0xA6 -> KEY_F16, long usage 0x70 (F21) right AC button: short 0x93 -> KEY_PROG1, long usage 0x71 (F22) Remap 0x70->KEY_F17 and 0x71->KEY_F19 (scoped to QUIRK_ROG_ALLY_XPAD) so userspace sees the same codes across Ally generations. MSC_SCAN still carries the raw usage. Note these are real held keys (press/autorepeat/release), unlike the synthetic instant press+release handle_ally_event() produces for 0xA7/0x38 on the original Ally. Related pre-existing inconsistency left untouched: 0x38 maps to KEY_PROG1 in asus_input_mapping() but to KEY_F19 in handle_ally_event().
Xbox Ally X (RC73YA) — round 2 test results + new findingsFollow-up to the original test report in this PR. All testing on real hardware Validation summary (all PASS)
New driver findings1.
|
|
Follow-up to my earlier test report: I extended the suspend/resume matrix with dedicated coverage for the two front buttons (short and long press), since those have historically been the problematic inputs on this hardware, and re-ran it on the Xbox Ally X. Result: front buttons fully survive suspend/resume — every check passed on every cycle. Test setup
Results
Across both baselines and all 5 resume cycles the mapping was completely stable:
No legacy F21/F22 events (long-press remap working after resume), no lost or swapped codes after any cycle, all 6 HID interfaces re-bound to Logs: |
f759008 to
bbd3c71
Compare
7c00659 to
9bc9553
Compare
Full test report for the
allybranch (b9a5f6e) on a ROG Xbox Ally X (RC73YA), plus fixes for the two bugs found. Everything below was verified live on hardware, on a 7.2-rc4 base with the series applied (the patchedhid-asusis the sole claimant of0B05:1B4Con that tree); fixes were validated by rebuilding the module out-of-tree and re-testing.Requested checks — all pass (with the fixes in this PR)
find /sys -name 'gamepad*'.0003gamepad_modedesktop/gamepad round-tripbtn_a/turbo_period4, 10)btn_a/remap→ PAD_B, restore)Commit 1 —
CMD_SET_MAPPINGpacket malformed; writing any remap/macro attr kills BOTH buttons of the pairWriting e.g.
btn_a/remapsent a packet the MCU parses as garbage: it unmaps A and B (the packet always carries the full pair), the buttons stop emitting events entirely, and the state persists in MCU NVRAM until a correct mapping packet is sent. Two independent errors inally_set_button_mapping(), either one alone is fatal:buf[5]: first remap 5–15, first macro 16–26, second remap 27–37, second macro 38–48 (cf.__btn_pair_to_pkt/BTN_CODE_LENin hid-asus-ally). The code copied the remap blocks as 10 bytes and wrote the macro type bytes atbuf[15]/buf[37]— one byte early.{0x01, 0x00, code, ...}and the MCU read value0x00= unmapped.Empirical proof: only the AB pair was ever written during testing, and only A/B died while every untouched pair kept working. Fixing only error 1 did not restore them; fixing both and re-sending the pair restored A/B immediately (clean
BTN_SOUTH/BTN_EASTpress+release in raw evdev capture).Commit 2 — Xbox Ally X front-button long-presses (verified codes)
0xA6→ KEY_F160x93→ KEY_PROG1The original Ally's
0xA7→F17 and0x38→F19 paths never fire on this hardware — long-presses arrive as plain keyboard-page usages through the generic HID path. The commit remaps 0x70→KEY_F17 and 0x71→KEY_F19 (scoped toQUIRK_ROG_ALLY_XPAD) so userspace sees the same codes across Ally generations.MSC_SCANstill carries the raw usage. Behavioral note: these are real held keys (press/autorepeat/release), unlike the synthetic instant press+release fromhandle_ally_event().Not fixed here, for your consideration
ally_config.left/right_trigger_min/maxare only written by the sysfs stores, so readback ofrange_upper_limitshows0(outside its own advertised70 100range) — and worse, the first write to any ONE trigger-range attr callsally_set_trigger_ranges()with the other three cached zeros, pushing a zero-width trigger range to the hardware until all four attrs are written once. Suggested: init mins=0/maxes=100 at probe (or query the device).0x38is mapped to KEY_PROG1 inasus_input_mapping()("ROG key") but to KEY_F19 inhandle_ally_event()— two contradictory handlers for the same code.Test environment
7.2-rc4 (CachyOS base; mt76/mac80211 untouched by its patches) + this series. Unrelated: 7.2-rc4 has an mt76/MT7922 regression on this device (WiFi MCU dead at probe → rtnl-held D-state cascade); all testing was done with
mt7921eblacklisted — being reported to linux-wireless separately, mentioned so nobody chases phantom hid-asus hangs.🤖 Generated with Claude Code