Skip to content

HID: asus: emit PROG1/PROG2 for the AC/CC front buttons - #9

Open
jlobue10 wants to merge 15 commits into
NeroReflex:allyfrom
jlobue10:ally-front-ac-cc
Open

HID: asus: emit PROG1/PROG2 for the AC/CC front buttons#9
jlobue10 wants to merge 15 commits into
NeroReflex:allyfrom
jlobue10:ally-front-ac-cc

Conversation

@jlobue10

@jlobue10 jlobue10 commented Aug 6, 2026

Copy link
Copy Markdown

Follow-up to #8 ("Now only AC/CC are missing"): maps the two front buttons to stable keycodes on short and long presses.

button short long keycode
AC (hexagon; top-LEFT on Xbox Ally X, hw-confirmed) raw 0xA6 (was F16) kbd usage 0x70 KEY_PROG1
CC (top-RIGHT on Xbox Ally X) vendor 0x93 kbd usage 0x71 KEY_PROG2

Design notes:

  • Raw 0x38/0xA7 keep PROG1 — 0x38 follows the ROG-key convention, and 0xA7 is the long-press companion of the 0xA6 button on the ROG Ally X, so short/long must agree. Net effect: the ROG Ally X gets the same per-scancode behavior as the Xbox Ally X even though its physical button placement differs.
  • Vendor-page 0xa6/0xa7 (original ROG Ally, where CC/QAM really is 0xa6) become PROG2/PROG1 by name; the laptop ROG key path is untouched.
  • Comments identify buttons by name only — placement differs between Ally generations.
  • Resume ghost-release + input capabilities follow the new keycodes (F16/F17 dropped, PROG2 added).

One open question: does the gen-1 Ally ever deliver 0xA6/0xA7 through the raw 0x5A path (handle_ally_event)? If it does, its CC button would emit PROG1 there instead of the vendor-page PROG2 — happy to gate that differently if so.

Validated on Xbox Ally X (RC73XA, MCU 0b05:1B4C) against ally head eb5d9d5:

  • 4/4 guided front-button checks — left short/long → PROG1 (long scan 0x70070), right short/long → PROG2 (short scan 0xff310093, long 0x70071), no stray F16/F17/F21/F22
  • full 25-button matrix pass
  • 41/41 checks across 3 suspend/resume cycles (ghost-release exercised on every resume)

🤖 Generated with Claude Code

NeroReflex and others added 14 commits July 28, 2026 17:34
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

Assisted-by: Claude:claude-fable-5
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>
Signed-off-by: Jonathan LoBue <jlobue10@gmail.com>
Add the base configuration structures for the gamepad configuration,
detect capabilities and initialize the device in a known state.

Assisted-by: Claude:claude-fable-5
Signed-off-by: Denis Benato <denis.benato@linux.dev>
Signed-off-by: Luke Jones <luke@ljones.dev>
Signed-off-by: Jonathan LoBue <jlobue10@gmail.com>
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.

Assisted-by: claude-fable-5
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>
Signed-off-by: Jonathan LoBue <jlobue10@gmail.com>
Add support for buttons remapping: the ability to assign different
button events to each one of the physical button on the device.

Assisted-by: Claude:claude-fable-5
Signed-off-by: Luke Jones <luke@ljones.dev>
Signed-off-by: Denis Benato <denis.benato@linux.dev>
Signed-off-by: John LoBue Jonathan LoBue <jlobue10@gmail.com>
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>
ASUS ROG laptops supports a protocol called Aura to control LEDs over
multiple zones: this protocol allows changing effects, colors,
brightness and transitioning speed across different colors on certain
effects.

Add support for said protocol to allow complete customization of
LEDs mounted on the ROG ally and laid out the foundation for all
other laptops.

Assisted-by: glm-5.2
Assisted-by: claude-fable-5
Signed-off-by: Denis Benato <denis.benato@linux.dev>
Signed-off-by: Khamunetri Clark <khamunetriclark@gmail.com>
Map the two front buttons to stable, DE-consumable keycodes on both
short and long presses (previously F16/F17 shorts with F21/F22-derived
longs):

  AC button -> KEY_PROG1: raw 0xA6 short (was F16) and keyboard usage
  0x70 long-press.  Sides hw-confirmed on the Xbox Ally X: the AC
  (hexagon) button is the top-LEFT front button there.
  CC button -> KEY_PROG2: vendor usage 0x93 short and keyboard usage
  0x71 long-press.

Raw 0x38 and 0xA7 keep PROG1: 0x38 follows the established ROG-key
convention, and 0xA7 is the long-press companion of the 0xA6 button on
the ROG Ally X, so short and long must agree.  Vendor-page 0xa6/0xa7
(original ROG Ally, where CC/QAM really is 0xa6) become PROG2/PROG1 by
name; the laptop ROG key path is untouched.  Comments identify buttons
by name only since physical placement differs between Ally generations.

The resume ghost-release workaround and input capabilities follow the
new keycodes (F16/F17 dropped, PROG2 added).

Also document the M1/M2 rear paddle orientation while here: M1 is the
right rear paddle and M2 the left one.  Annotated at the button-id
enum, the remap code table, the vendor-page 0xa5 mapping, and the turbo
config struct (whose M2-before-M1 field order matches the firmware
payload).  Comment-only.

Validated on Xbox Ally X (RC73XA, MCU 0b05:1B4C) against the ally
branch head eb5d9d5: 4/4 guided front-button checks (longs
discriminated by MSC_SCAN 0x70070/0x70071), full 25-button matrix, and
41/41 checks across 3 suspend/resume cycles with no stray F16/F17
events.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@jlobue10

jlobue10 commented Aug 6, 2026

Copy link
Copy Markdown
Author

Updated: squashed in comment-only documentation of the M1/M2 rear paddle orientation (M1 = right rear, M2 = left rear) while touching this file — annotated at the button-id enum, the remap code table, the vendor-page 0xa5 mapping, and the turbo config struct (whose M2-before-M1 field order matches the firmware payload). No functional change beyond the original scope; still a single commit (7fee37e).

The MCU holds kbd usage 0x70 (AC button) / 0x71 (CC button) down from
~200ms into the press until the button is released (measured on the
Xbox Ally X, FW FGA80100.RC73XA.325). Mapped through the generic path
the long press behaves like a held key and autorepeats (hid-input
enables EV_REP on keyboard nodes), so one long press delivered 100+
PROG events while held.

Strip the usages from the keyboard report in asus_raw_event() before
the generic parser sees them, track the held state, and synthesize the
complete press+release pair (with the matching MSC_SCAN) on the break,
so short and long presses alike deliver exactly one PROG event pair.
Clear the tracked state on resume so a break lost across suspend
cannot turn the next keyboard report into a phantom pair.
@jlobue10

jlobue10 commented Aug 7, 2026

Copy link
Copy Markdown
Author

Follow-up: pushed 1698eeb ("HID: asus: emit Ally front-button long-press once, on release") — hardware-validated on the Xbox Ally X (FW FGA80100.RC73XA.325, 7.2.0-rc4 base).

The gap

The v2 mapping delivered the right keycodes, but a long press behaved as a held key: evdev capture shows PROG down ~200ms into the press, continuous autorepeat while held (115–125 repeat events over a ~4.5s hold), and up at release. The set_bit(EV_REP) lines in v2 turn out to be no-ops either way — hid-input already enables EV_REP on keyboard nodes, which is where the repeats come from.

Transport ground truth from a raw evdev dump of the unpatched build (all four gestures cued so press/release instants are known):

gesture wire edge behavior
AC short vendor 0x5A/0xA6, no scan synthesized tap
AC long kbd usage 0x70, scan 0x70070 down ~200ms after press, EV_REP repeats, up at release
CC short vendor 0x93, scan 0xff310093 press/release pair
CC long kbd usage 0x71, scan 0x70071 same held-key shape as AC long

Two corrections to earlier statements: the long-press make lands ~200ms after the physical press (the MCU threshold — not ~2s as I previously wrote), and taps under that threshold never emit the kbd usage at all.

The fix (1698eeb)

Same approach as the existing 0xA8 → 0x00 rewrite: asus_raw_event() strips usages 0x70/0x71 from the keyboard report (6-slot array + NKRO bitmap, report ID 0x01) before the generic parser sees them, tracks held state in drvdata, and synthesizes the complete press+release pair — with the matching MSC_SCAN — on the break. The tracked state is cleared in both resume paths so a break lost across suspend can't turn the next keyboard report into a phantom pair.

Result: short and long presses deliver the identical shape — exactly one PROG1 (AC) / PROG2 (CC) press+release pair, nothing while the button is held, no autorepeat.

Validation (same boot, srcversion 0AC33637 memory-swap of this branch's file)

test result
front-button matrix, v2 baseline 6/8 — both longs fail on autorepeat-while-held (the gap above)
front-button matrix, this commit 8/8 — longs emit once, on the release edge (first event t=5.47s/5.73s vs release cue t=5.01s), correct scancodes preserved
full 25-button matrix (sticks, triggers, paddles, fronts) 25/25
suspend/resume s2idle ×3 (front-button checks each cycle) 41/41, kmsg clean
suspend/resume mcu_powersave ×2 (forces reset_resume) 29/29, kmsg clean

Happy to rework or squash into the v2 commit if you'd rather keep the branch to one commit.

@NeroReflex
NeroReflex force-pushed the ally branch 3 times, most recently from 5eb0768 to ecdba22 Compare August 13, 2026 14:39
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.

2 participants