Skip to content

[FROM-ML] HID: ayaneo: Add AYANEO 3 detachable controller driver - #101

Open
matmartinez wants to merge 1 commit into
OpenGamingCollective:features/ayaneofrom
matmartinez:hid-ayaneo
Open

matmartinez wants to merge 1 commit into
OpenGamingCollective:features/ayaneofrom
matmartinez:hid-ayaneo

Conversation

@matmartinez

Copy link
Copy Markdown

Adds a HID driver for the AYANEO 3's detachable controller ("Magic Modules"), restoring the module functionality that was lost when Bazzite 44 dropped Handheld Daemon (see ShadowBlip/OpenGamepadUI#528, ublue-os/bazzite context).

What it does

Binds the controller's vendor HID interface (1c4f:0002, application usage 0xff000001; DMI-gated to the AYANEO 3 since the VID/PID is a generic SigmaMicro ID) and provides:

  • Module identification: module_left / module_right sysfs attributes (raw firmware module-type IDs; bits 0–5 type, bit 6 rotated)
  • Software eject: eject sysfs attribute (left/right/both), blocks until the firmware confirms the release handshake
  • RGB: multicolor LED class device ayaneo:rgb:joystick_rings — the name InputPlumber's 50-ayaneo_3.yaml already expects
  • reset: quick controller config reset

EC power-off is deliberately left to userspace: the full pop-out flow is eject → write 0 to ayaneo-ec's controller_power, so orchestration/UX can live in OpenGamepadUI (plugin planned as the next step, per #528).

The protocol was reverse engineered in Handheld Daemon by Antheas Kapenekakis; this ports it onto the ayaneo-ec foundation (already in this tree since 6.19). Includes a Documentation/ABI/ entry and a MAINTAINERS entry; checkpatch --strict clean except the standard -ENOSYS output-report-fallback false positive.

Testing

Built and tested on an AYANEO 3 running Bazzite 44 (this tree's 7.2.0-ogc4.1 via kernel-packages):

  • probe identifies modules: hid-ayaneo 0003:1C4F:0002.0007: modules: left 0x04 right 0x50
  • RGB confirmed via the LED class device (both rings)
  • full physical cycle verified: eject → firmware confirm (~4s) → EC power off → module released → reinsert → controller_modules back to both → power on → controller re-enumerates (custom mode persists in controller flash) → driver rebinds

A companion PR to kernel-packages adds CONFIG_HID_AYANEO=m.

Marked [FOR-UPSTREAM]: I intend to submit this to LKML (linux-input) once the sysfs interface has been sanity-checked by the folks working on the AYANEO stack — feedback requested in ShadowBlip/OpenGamepadUI#528. Happy to adjust naming/semantics here first so the OGC tree matches what goes to the list.

@matmartinez

Copy link
Copy Markdown
Author

Per pastaq's guidance in ShadowBlip/OpenGamepadUI#528, this is now also submitted to the unstable review repo as OpenGamingCollective/linux-unstable#3 (same commit rebased onto its master). Happy to close either one — whichever fits your flow.

@pastaq

pastaq commented Sep 1, 2026

Copy link
Copy Markdown
Member

Please update this PR once you've submitted v3 to the mailing list.

The AYANEO 3 handheld has a detachable controller with swappable
modules ("Magic Modules"). The controller exposes three USB HID
interfaces behind 1c4f:0002 (a generic SigmaMicro VID/PID, hence the
DMI gate): a gamepad, a keyboard for the extra buttons, and a vendor
interface accepting 65-byte commands.

Add a driver for the vendor interface providing module identification
(module_left/module_right sysfs attributes), software eject of the
modules (eject sysfs attribute, blocking until the firmware confirms
the release handshake), and RGB control of the joystick rings as a
multicolor LED class device ("<device name>:rgb:joystick_rings";
userspace such as InputPlumber matches the function suffix). The
firmware's fixed breathing pattern is exposed through the hw_pattern
trigger ABI.

This complements the ayaneo-ec platform driver, which exposes module
attach state and controller power. A full physical eject is performed
by writing to eject and then cutting power through ayaneo-ec's
controller_power attribute; that orchestration is deliberately left
to userspace.

The protocol was reverse engineered in the Handheld Daemon project by
Antheas Kapenekakis. Tested on an AYANEO 3: module identification,
RGB solid and breathing, a full eject/reinsert/repower cycle, and
repeated driver unbinds under a concurrent brightness-write load.
Signed-off-by: Matías Martínez <hello@matias.me>
Reviewed-by: Denis Benato <denis.benato@linux.dev>
Link: https://lore.kernel.org/r/20260917160722.89391-1-hello@matias.me
@matmartinez matmartinez changed the title [FOR-UPSTREAM] HID: ayaneo: Add AYANEO 3 detachable controller driver [FROM-ML] HID: ayaneo: Add AYANEO 3 detachable controller driver Sep 17, 2026
@matmartinez

Copy link
Copy Markdown
Author

v3 is on the list: https://lore.kernel.org/linux-input/20260917160722.89391-1-hello@matias.me/

Rebuilt this branch per your note on linux-unstable#11: a single [FROM-ML] commit off current features/ayaneo, carrying the ML Link trailer. No functional change vs v2; the delta is the rework from your linux-unstable#3 review (generic ayaneo_ plumbing, packed wire structs, scoped guards, LED_COLOR_ID_RGB, named timing constants), retested on hardware. The driver file matches what I run daily on Bazzite 44.

pastaq
pastaq previously approved these changes Sep 17, 2026

@pastaq pastaq left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great, thanks!

A few notes: When you submit a new version to LKML it is typically best to send it as a new thread vs as a reply to the original thread. Also, the last line should be your SOB, RB/TB should precede that.

@pastaq
pastaq dismissed their stale review September 17, 2026 18:43

Conflicts need addressing

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