Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,9 @@ behind backend implementations.

- Gamepad profiles for generic HID, Xbox 360, Xbox One, Xbox Series,
DualShock 4, DualSense, and Nintendo Switch Pro-style controllers.
- Descriptor-driven Linux gamepads through `uhid`, plus keyboard, mouse,
touchscreen, trackpad, and pen tablet devices through `uinput`.
- Descriptor-driven Linux gamepads through `uhid`; Xbox Series gamepads plus
keyboard, mouse, touchscreen, trackpad, and pen tablet devices through
`uinput`.
- Windows gamepads through a user-mode UMDF2 control driver backed by Virtual
HID Framework, with keyboard and mouse support through normal Win32 APIs.
- Output callbacks for profile-specific feedback such as rumble, LEDs,
Expand Down
31 changes: 25 additions & 6 deletions docs/platform-support.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,34 @@ and signing details.
The Linux backend uses standard user-space kernel interfaces:

- `uhid` for descriptor-driven HID gamepads.
- `uinput` for keyboard, mouse, touchscreen, trackpad, and pen tablet devices.
- `uinput` for Generic, Xbox 360, Xbox One, and Xbox Series gamepads, plus
keyboard, mouse, touchscreen, trackpad, and pen tablet devices.
- `libevdev` internally for uinput device construction.
- X11/XTest only as a keyboard and mouse fallback when `uinput` cannot be used
and an X11 session is available.

Gamepad support prefers `uhid` because descriptors, raw HID identity, feature
reports, and output reports matter for controller compatibility. Keyboard and
pointer devices prefer `uinput` because those devices map naturally to Linux
input devices.
Gamepad support normally prefers `uhid` because descriptors, raw HID identity,
feature reports, and output reports matter for controller compatibility.
Generic and Xbox-family profiles instead use `uinput` so SDL, Steam, and other
evdev consumers receive canonical Linux gamepad events without interpreting a
standard or Xbox GIP descriptor. Face buttons, shoulders, menu buttons, stick
clicks, and Guide use their native evdev codes; sticks and the directional pad
use absolute axes; triggers remain independent analog `ABS_Z` and `ABS_RZ`
axes. Profiles with rumble support normalize force-feedback effects back into
the public callback.

Xbox 360 and Xbox One retain their public USB identities. Xbox Series uses the
Bluetooth product identity (`0x0B13`) only for its Linux uinput device; its
public profile retains the physical USB identity used by other backends. All
four uinput gamepad profiles preserve the sparse 15-slot Linux gamepad button
sequence expected by Steam. Unused `BTN_C`, `BTN_Z`, `BTN_TL2`, and `BTN_TR2`
slots are advertised but never pressed, keeping face buttons, shoulders, menu
buttons, Guide, L3, and R3 at their expected indices.

Descriptor-driven profiles remain on `uhid`. The Switch Pro profile keeps its
Nintendo identity but uses the virtual UHID bus on Linux, preventing
`hid-nintendo` from claiming the descriptor-only device and waiting for
physical-controller initialization handshakes.

The optional `virtualhid_control` diagnostic UI uses SDL3 and Dear ImGui through
the repository CPM lockfile. It is intended to stay on the same UI framework for
Expand Down Expand Up @@ -87,7 +106,7 @@ KERNEL=="hidraw*", ATTRS{name}=="Your App Controller*", GROUP="input", MODE="066
SUBSYSTEMS=="input", ATTRS{name}=="Your App Controller*", GROUP="input", MODE="0660", TAG+="uaccess"
```

For `uhid` gamepad support, install a modules-load entry such as
For descriptor-driven `uhid` gamepad support, install a modules-load entry such as
`/etc/modules-load.d/60-libvirtualhid.conf`:

```text
Expand Down
3 changes: 3 additions & 0 deletions docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,3 +178,6 @@ Profiles advertise support for features such as rumble, trigger rumble, RGB
LEDs, adaptive triggers, motion sensors, touchpads, battery state, profile
specific buttons, and raw output reports. Consumers should query profile and
backend capabilities before warning users about unsupported client features.
The `misc1` button represents Share/Capture/Mic Mute-style controls and is
available on the generic, Xbox Series, DualSense, and Switch Pro profiles; Xbox
360 and Xbox One do not advertise that extra button.
5 changes: 4 additions & 1 deletion src/core/backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ namespace lvh::detail {
*/
class FakeGamepad final: public BackendGamepad {
public:
OperationStatus submit(const std::vector<std::uint8_t> & /*report*/) override {
OperationStatus submit(
const GamepadState & /*state*/,
const std::vector<std::uint8_t> & /*report*/
) override {
return OperationStatus::success();
}

Expand Down
8 changes: 6 additions & 2 deletions src/core/backend.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,16 @@ namespace lvh::detail {
virtual ~BackendGamepad() = default;

/**
* @brief Submit a packed input report to the backend.
* @brief Submit normalized state and its packed input report to the backend.
*
* HID backends consume @p report, while native platform input backends may
* consume @p state.
*
* @param state Normalized gamepad state.
* @param report Packed HID input report.
* @return Submit status.
*/
virtual OperationStatus submit(const std::vector<std::uint8_t> &report) = 0;
virtual OperationStatus submit(const GamepadState &state, const std::vector<std::uint8_t> &report) = 0;

/**
* @brief Get platform-visible nodes associated with this backend device.
Expand Down
4 changes: 2 additions & 2 deletions src/core/gamepad_adapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,12 @@ namespace lvh {
using enum GamepadProfileKind;

case generic:
case xbox_360:
case xbox_one:
case xbox_series:
case dualsense:
case switch_pro:
return true;
case xbox_360:
case xbox_one:
case dualshock4:
return false;
}
Expand Down
Loading
Loading