Summary
Give src/gamepad_source/linux.zig a full gamepad STATE surface (buttons/axes/pump), so Linux desktop gamepad can run on the existing evdev/udev source with no SDL dependency — the intended end-state from the core#28 slice-5 decision (SDL opt-out by default on desktop; Linux uses udev). Today this is deferred because it can't be runtime-verified without bare-metal Linux hardware and would replace the working SDL Linux path.
Tracked locally as a deferred follow-up of core#28; filing it so it survives as a real issue.
Current state
gamepad_source/linux.zig is detection-only: it opens each /dev/input/event* node just long enough to read identity (EVIOCGID/EVIOCGNAME) then closes the fd. It implements init/deinit/pollEvents/describe but no update/isAvailable/isButtonDown/isButtonPressed/axisValue (the gamepad_source state contract treats those as optional, so it compiles — but Linux can't serve gamepad STATE).
- After core#28, the raylib/sokol desktop backends route gamepad through the shared SDL
backends/sdl_gamepad source on all desktop OSes incl. Linux.
- The SDL source is now CI-runtime-verified on Linux (assembler#279, 23/23 via an in-process SDL virtual gamecontroller) — but only the SDL joystick subsystem; it does not exercise the kernel device path.
Scope
- core —
gamepad_source/linux.zig: add the state surface mirroring backends/sdl_gamepad's Source exactly (canonical raylib-compatible numbering, sticks [-1,1], triggers [0,1], synthesized left/right_trigger_2 at the trigger threshold, per-slot prev/cur edge snapshot):
- keep the
event* fd open per tracked slot (close on disconnect/deinit),
update(): per frame, snapshot current state via EVIOCGKEY (button bitmap) + EVIOCGABS(axis) ioctls (recommended for parity with the SDL snapshot-and-edge model) or drain the evdev event stream,
isAvailable/isButtonDown/isButtonPressed/axisValue,
- the
KEY_*/ABS_* → canonical button/axis mapping + axis normalization from each axis's input_absinfo{min,max,flat} (read once at connect),
- matching no-op state methods on the non-Linux
FallbackSource so the file still cross-compiles everywhere.
- assembler — backend Impl routing: on a Linux desktop target, route raylib/sokol gamepad to
core.gamepad_source (udev) instead of sdl_gamepad, and don't link SDL2 there. (This is the per-OS 3-way selection sketched in the core#28 slice-5 plan.)
Acceptance (needs bare-metal Linux + a real pad)
The SDL virtual-device harness can't cover these — they're the kernel-path criteria (overlaps assembler#249):
- connect/disconnect hotplug via evdev/udev with a physically (re)plugged controller,
/dev/input/* permission handling + a clean unavailable_reason when denied,
- GUID/identity stability across replug,
- buttons/axes/edges read correctly for at least one real pad (Xbox + one other).
Why deferred
No bare-metal Linux hardware available to runtime-verify, and shipping an unverified evdev state path would replace the working, now-CI-verified SDL Linux path — a regression risk with nothing to catch it. Pick up when Linux hardware (or a Linux runtime-CI job with a real/virtual evdev device) is available.
Related
- core#28 — gamepad epic; this is its deferred Linux follow-up.
- assembler#249 — Linux evdev/udev + wasm detection sources (Phase 1); carries the wasm + permissions-UX scope and the kernel-path acceptance criteria.
- assembler#279 — hardware-free SDL gamepad CI harness (verifies the SDL Linux path, not the kernel path).
Summary
Give
src/gamepad_source/linux.ziga full gamepad STATE surface (buttons/axes/pump), so Linux desktop gamepad can run on the existing evdev/udev source with no SDL dependency — the intended end-state from the core#28 slice-5 decision (SDL opt-out by default on desktop; Linux uses udev). Today this is deferred because it can't be runtime-verified without bare-metal Linux hardware and would replace the working SDL Linux path.Tracked locally as a deferred follow-up of core#28; filing it so it survives as a real issue.
Current state
gamepad_source/linux.zigis detection-only: it opens each/dev/input/event*node just long enough to read identity (EVIOCGID/EVIOCGNAME) then closes the fd. It implementsinit/deinit/pollEvents/describebut noupdate/isAvailable/isButtonDown/isButtonPressed/axisValue(thegamepad_sourcestate contract treats those as optional, so it compiles — but Linux can't serve gamepad STATE).backends/sdl_gamepadsource on all desktop OSes incl. Linux.Scope
gamepad_source/linux.zig: add the state surface mirroringbackends/sdl_gamepad'sSourceexactly (canonical raylib-compatible numbering, sticks [-1,1], triggers [0,1], synthesizedleft/right_trigger_2at the trigger threshold, per-slotprev/curedge snapshot):event*fd open per tracked slot (close on disconnect/deinit),update(): per frame, snapshot current state viaEVIOCGKEY(button bitmap) +EVIOCGABS(axis)ioctls (recommended for parity with the SDL snapshot-and-edge model) or drain the evdev event stream,isAvailable/isButtonDown/isButtonPressed/axisValue,KEY_*/ABS_*→ canonical button/axis mapping + axis normalization from each axis'sinput_absinfo{min,max,flat}(read once at connect),FallbackSourceso the file still cross-compiles everywhere.core.gamepad_source(udev) instead ofsdl_gamepad, and don't link SDL2 there. (This is the per-OS 3-way selection sketched in the core#28 slice-5 plan.)Acceptance (needs bare-metal Linux + a real pad)
The SDL virtual-device harness can't cover these — they're the kernel-path criteria (overlaps assembler#249):
/dev/input/*permission handling + a cleanunavailable_reasonwhen denied,Why deferred
No bare-metal Linux hardware available to runtime-verify, and shipping an unverified evdev state path would replace the working, now-CI-verified SDL Linux path — a regression risk with nothing to catch it. Pick up when Linux hardware (or a Linux runtime-CI job with a real/virtual evdev device) is available.
Related