Readme
CtrlAssist brings "controller assist" functionality to Linux gaming by allowing multiple physical controllers to operate as a single virtual input device. This enables collaborative play and customizable gamepad setups, making it easier for players of all ages and abilities to enjoy games together. While similar features exist on modern game consoles, CtrlAssist is an open source project that enhances accessibility for PC gaming, offering additional quality-of-life improvements through virtual input devices on Linux.
Features
Combine physical controllers into one virtual gamepad
Controllers are assigned as either Primary or Assist
Customizable multiplexing modes for buttons and axes
Logically merging or preempting events is flexible
Hide physical controllers for improved game compatibility
Avoid controller interference from conflicting inputs
Spoof gamepad vendor for in-game layout recognition
Mimic either Primary or Assist controller hardware
Rumble pass-through from virtual to physical devices
Forward force feedback to either or both controllers
Modes
Priority (default): Assist controller overrides when active
Axes: Prioritize Assist when active (exceeds deadzone)
Buttons: Prioritize Assist when button released
Triggers: Prioritize largest value from either
Ideal for partial and asynchronous assistance
E.g. Assist for movement while Primary for actions
Average : Blend weighted inputs from both controllers
Axes: Averaged when both are active (exceed deadzone)
Buttons: logically OR'ed between pressed controllers
Triggers: Averaged when both are active (exceed deadzone)
Ideal for cooperative input and subtle corrections
E.g. For counter steer/brake assist in racing games
Toggle : Switch Active controller on demand
All inputs forwarded from currently active controller
Toggle Active controller via the Mode button on Assist
Immediately synchronizes input to current Active state
Ideal when fine-grain conflict-free control is needed
E.g. Game menu navigation or precise interventions
Prerequisites
Linux system using udev (libudev-dev)
with user permissions to manage virtual devices
already pre-configured on most distributions
Rust toolchain with included cargo
Install
Add the --force flag to upgrade to latest version:
cargo install ctrlassist
Usage
Use the --help flag for information on each CLI subcommand:
$ ctrlassist -- help
Multiplex multiple controllers into virtual gamepad
Usage: ctrlassist < COMMAND>
Commands:
list List all detected controllers and respective IDs
mux Multiplex connected controllers into virtual gamepad
help Print this message or the help of the given subcommand(s )
Options:
-h, -- help Print help
-V, -- version Print version
list
List all detected controllers and respective IDs:
$ ctrlassist list
( 0 ) Microsoft Xbox One
( 1 ) PS4 Controller
mux
Multiplex first two detected controllers by default:
$ ctrlassist mux
Primary: (0 ) Microsoft Xbox One
Assist: (1 ) PS4 Controller
...
Mux Active. Press Ctrl+C to exit.
Optional: Specify Device Mapping
Manually specify Primary and Assist controllers via IDs:
$ ctrlassist mux -- primary 1 -- assist 0
Primary: (1 ) PS4 Controller
Assist: (0 ) Microsoft Xbox One
...
Optional: Specify Mux Mode
Manually specify mode for merging controllers:
$ ctrlassist mux -- mode priority
...
Optional: Hide Physical Devices
Avoiding in game conflicts by hiding physical controllers:
$ sudo ctrlassist mux -- hide
...
Optional: Spoof Virtual Device
Mimic controller hardware for in-game layout recognition:
$ ctrlassist mux -- spoof primary
Primary: (0 ) Microsoft Xbox One
Assist: (1 ) PS4 Controller
Virtual: (2 ) Microsoft X-Box One pad (Firmware 2015 )
Optional: Proxy Rumble Effects
Target force feedback to either or both physical controllers:
$ ctrlassist mux -- rumble both
...
Limitations
Hiding physical input devices requires root access
temporarily modifies group permissions for selected devices
Hiding must be done before starting games or launchers
processes with open file handles may retain device access
Reconnecting a hidden controller reverts its visibility
custom udev rules should be used for persistent permissions
Toggle mode requires pressing all buttons and axes after startup
gilrs lazily initializes gamepad state used for synchronization
Background