Fix Sunshine/Apollo virtual DualSense mapping on Linux (triggers read as right stick) - #263
Open
TechnicallyComputers wants to merge 1 commit into
Conversation
…t stick) Sunshine and its Apollo fork create their virtual DualSense through uhid, so it enumerates as a real HID device: bus 0x0005 (Bluetooth), Sony's genuine DualSense VID/PID 054c:0ce6 -- but bcdDevice 0x8111. A physical Bluetooth DualSense reports 0x8100 and matches the existing gamecontrollerdb entry; 0x8111 matches nothing, so SDL falls back to its built-in PS5 mapping. That fallback assumes hid-generic descriptor order (a2=RX, a3=L2, a4=R2, a5=RY). Modern kernels bind hid-playstation instead, which normalizes the axes to ABS_X/Y/Z/RX/RY/RZ -- a2=L2, a3=RX, a4=RY, a5=R2. The built-in mapping therefore reads both triggers as the right analog stick and the right stick as the triggers. Face buttons are wrong too: `a` reads circle, `x` reads cross, and guide/leftstick/rightstick point at R3/PS/L3. This only bites on Linux because osContInit sets SDL_HINT_JOYSTICK_HIDAPI=0 there (issue JRickey#193), so gamepads arrive over evdev rather than SDL's HIDAPI PS5 driver -- the latter parses the HID reports itself and never sees the kernel's axis numbering. Add a platform:Linux entry for 054c:0ce6 version 0x8111 matching the hid-playstation layout. The CRC field is zeroed, so the entry matches on VID/PID/version regardless of the device name string; any Sunshine fork that keeps the same uhid emulation is covered even if it renames the pad. Verified on kernel 7.1.4 / SDL 2.32.70 by loading the repo's gamecontrollerdb.txt through SDL_GameControllerAddMappingsFromFile with SDL_JOYSTICK_HIDAPI=0 -- the same call and hint state osContInit uses -- and confirming SDL resolves this entry for the live device instead of its built-in fallback. Gameplay confirmed over Moonlight. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WLkH9mM9ppQ9iekbeuJvXn
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This fixes an issue with trigger axes for Moonlight/Apollo/Sunshine's virtual DualSense controller spoofing a ps5 to have proper input handling, instead of treating L/R trigger axes as right analog stick.
Symptom
Playing over Moonlight with Sunshine's virtual DualSense on a Linux host, both triggers drive the right analog stick and the right stick drives the triggers. Face buttons are wrong too:
areads circle,xreads cross, andguide/leftstick/rightstickland on R3/PS/L3.It's not the client-side hardware — it reproduces with every physical controller attached to the streaming client, and
evteston the host shows the axes reported correctly.Root cause
Sunshine creates its virtual DualSense through uhid, so it enumerates as a genuine HID device — bus
0x0005(Bluetooth), Sony's real DualSense VID/PID054c:0ce6— but withbcdDevice = 0x8111.A physical Bluetooth DualSense reports
0x8100, which matches the existinggamecontrollerdb.txtentry.0x8111matches nothing, so SDL falls back to its built-in PS5 mapping — and that fallback assumeshid-genericdescriptor order.Modern kernels bind
hid-playstationinstead, which normalizes the axes toABS_X/Y/Z/RX/RY/RZ. The two layouts disagree exactly where it hurts:hid-playstationactually reportsrightx:a2ABS_Z= L2righty:a5ABS_RZ= R2lefttrigger:a3ABS_RXrighttrigger:a4ABS_RYThis is Linux-only because
osContInitsetsSDL_HINT_JOYSTICK_HIDAPI=0there (issue #193 — udev stall plus rumble regressions), so gamepads arrive over evdev. On Windows the HIDAPI PS5 driver parses the HID reports itself and never sees the kernel's axis numbering, so it's unaffected.The fix
One
platform:Linuxentry for054c:0ce6version0x8111matching thehid-playstationlayout. No code changes.The CRC field is deliberately zeroed so the entry matches on VID/PID/version regardless of the device name string — Sunshine forks that keep the same uhid emulation are covered even if they rename the pad.
Verification
Loaded the repo's
gamecontrollerdb.txtthroughSDL_GameControllerAddMappingsFromFilewithSDL_JOYSTICK_HIDAPI=0— the same call and hint stateosContInituses — and confirmed SDL resolves this entry for the live device instead of its built-in fallback. Gameplay then confirmed by hand over Moonlight: sticks, triggers, and face buttons all correct.Environment: kernel 7.1.4, SDL 2.32.70, Sunshine virtual DualSense.
Scope note
Verified against Sunshine. Apollo is a Sunshine fork and inherits the same uhid emulation, so it should present identical IDs, but I have not confirmed that on real hardware. Sunshine's virtual DS4 and X360 pads were not tested and may have the same version-mismatch problem.