2 unstable releases
Uses new Rust 2024
| new 0.2.0 | Dec 20, 2025 |
|---|---|
| 0.1.0 | Dec 7, 2025 |
#73 in Game dev
45KB
821 lines

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
Modes
- Priority (default): Assist controller overrides when active
- Axes: Prioritize when Assist exceeds deadzone
- Buttons: OR'ed between controllers
- Ideal for partial and asynchronous assistance
- E.g. Assist for movement while Primary for actions
- Axes: Prioritize when Assist exceeds deadzone
- Average: Blend weighted inputs from both controllers
- Axes: Averaged when both exceed deadzone
- Buttons: OR'ed between controllers
- Ideal for cooperative input and subtle corrections
- E.g. For counter steer/brake assist in racing games
- Axes: Averaged when both exceed deadzone
- Toggle: Switch active controller on demand
- All inputs forwarded from currently active controller
- Toggle active controller via the Mode button on Assist
- Ideal when fine-grain conflict-free control is needed
- E.g. Game menu navigation or precise interventions
- All inputs forwarded from currently active controller
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- https://rust-lang.org/tools/install/
- configure
PATHper Notes linked above
Install
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
Detected controllers:
ID: 0 - Name: Microsoft Xbox One
ID: 1 - Name: PS4 Controller
mux
Multiplex first two detected controllers by default:
$ ctrlassist mux
Connected controllers:
Primary: ID: 0 - Name: Microsoft Xbox One
Assist: ID: 1 - Name: PS4 Controller
Virtual: ID: 2 - Name: CtrlAssist Virtual Gamepad
Optional: Specify Device Mapping
Manually specify Primary and Assist controllers via IDs:
$ ctrlassist mux --primary 1 --assist 0
Connected controllers:
Primary: ID: 1 - Name: PS4 Controller
Assist: ID: 0 - Name: Microsoft Xbox One
Virtual: ID: 2 - Name: CtrlAssist Virtual Gamepad
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
...
Hiding controllers... (requires root)
Assist mode active. Press Ctrl+C to exit.
^C
Shutting down.
Restoring controllers...
Optional: Spoof Virtual Device
Mimic controller hardware for in-game layout recognition:
$ ctrlassist mux --spoof primary
Connected controllers:
Primary: ID: 0 - Name: Microsoft Xbox One
Assist: ID: 1 - Name: PS4 Controller
Virtual: ID: 2 - Name: Microsoft X-Box One pad (Firmware 2015)
Limitations
- Hiding physical input devices requires root access
- temporarily modifies group permissions for selected devices
- Hiding is by merely matching vendor and product IDs
- Any controller with similar IDs may also be hidden
- 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
Background
Dependencies
~4.5–9MB
~175K SLoC