/InputPlumber

Open source input router and remapper daemon for Linux

Primary LanguageRustGNU General Public License v3.0GPL-3.0

InputPlumber Logo
InputPlumber


About

InputPlumber is an open source input routing and control daemon for Linux. It can be used to combine any number of input devices (like gamepads, mice, and keyboards) and translate their input to a variety of virtual device formats.

Features

  • Combine multiple input devices
  • Emulate mouse, keyboard, and gamepad inputs
  • Intercept and route input over DBus for overlay interface control
  • Input mapping profiles to translate source input into the desired target input
  • Route input over the network

Install

InputPlumber requires the following system dependencies:

  • libevdev
  • libiio

You can install with:

make build
sudo make install

If you are using ArchLinux, you can install InputPlumber from the AUR:

yay -S inputplumber-bin

Then start the service with:

sudo systemctl enable inputplumber
sudo systemctl start inputplumber

Documentation

XML specifications for all interfaces can be found in bindings/dbus-xml.

Usage

When InputPlumber is running as a service, you can interact with it over DBus. There are various DBus libraries available for popular programming languages like Python, Rust, C++, etc.

You can also interface with DBus using the busctl command:

busctl tree org.shadowblip.InputPlumber

Input Profiles

InputPlumber is capable of loading input device profiles to translate inputs into any other supported input event. Input profiles are defined as YAML configuration files that can be loaded on-demand for any device that InputPlumber manages. The format of an input profile config is defined by the Device Profile Schema to make it easier to create profiles.

Typically input profiles should be generated using an external tool, but you can manually create your own profiles using any text editor. If you use an editor that supports the YAML Language Server you can write profiles with auto-complete and usage information.

Here is a short example:

# yaml-language-server: $schema=https://raw.githubusercontent.com/ShadowBlip/InputPlumber/main/rootfs/usr/share/inputplumber/schema/device_profile_v1.json
version: 1
kind: DeviceProfile
name: Start Button to Escape Key
description: Profile to map a gamepad's start button to the Escape keyboard key

mapping:
  - name: Menu
    source_event:
      gamepad:
        button: Start
    target_events:
      - keyboard: KeyEsc

This example will remap the Start button from a gamepad to the ESC key.

To load the input profile, you can use the LoadProfilePath method on the input device you want the profile applied to. You can also do this from the command line using busctl:

busctl call org.shadowblip.InputPlumber \
  /org/shadowblip/InputPlumber/CompositeDevice0 \
  org.shadowblip.Input.CompositeDevice \
  LoadProfilePath "s" /usr/share/inputplumber/profiles/mouse_keyboard_wasd.yaml

Intercept Mode

Intercept Mode is a feature of InputPlumber that can allow external applications to intercept input events from an input device and re-route them over DBus instead. The primary use case for this feature is typically to allow overlay applications (like OpenGamepadUI) to stop input from reaching other running applications (like a game), allowing the overlay to process inputs without those inputs leaking into other running apps.

You can set the intercept mode by setting the InterceptMode property on the input device you want to intercept input from. The intercept mode can be one of three values:

  • 0 (NONE) - No inputs are intercepted and re-routed
  • 1 (PASS) - No inputs are intercepted and re-routed except for gamepad Guide events. Upon receiving a gamepad Guide event, the device is automatically switched to intercept mode 2 (ALL).
  • 2 (ALL) - All inputs are intercepted and re-routed over DBus

Typically the intercept mode should be handled by an external application, but you can also set the intercept mode from the command line using busctl:

busctl set-property org.shadowblip.InputPlumber \
  /org/shadowblip/InputPlumber/CompositeDevice0 \
  org.shadowblip.Input.CompositeDevice \
  InterceptMode u 2

Virtual Keyboard

When InputPlumber is running, a virtual keyboard is created that is used for sending keyboard inputs. You can also use this keyboard to send keyboard events using the DBus interface with the SendKey method. You can do this from the command line using busctl:

busctl call org.shadowblip.InputPlumber \
  /org/shadowblip/InputPlumber/devices/target/keyboard0 \
  org.shadowblip.Input.Keyboard \
  SendKey sb KEY_ESC 1

Device Compositing & Capability Maps

One feature of InputPlumber is the ability to combine multiple input devices together into a single logical input device called a "Composite Device". This is often required for many handheld gaming PCs that have built-in gamepads with special non-standard buttons that show up as multiple independent input devices.

Composite devices are defined as YAML configuration files that follow the Composite Device Schema to combine the defined input devices together. When InputPlumber starts up, it looks at all the input devices on the system and checks to see if they match a composite device configuration. If they do, the input devices are combined into a single logical composite device.

A composite device configuration looks like this:

# yaml-language-server: $schema=https://raw.githubusercontent.com/ShadowBlip/InputPlumber/main/rootfs/usr/share/inputplumber/schema/composite_device_v1.json
version: 1
kind: CompositeDevice
name: OneXPlayer Intel

# Only check for source devices if *any* of the given data matches. If this list is
# empty, then the source devices will *always* be checked.
matches:
  - dmi_data:
      product_name: ONEXPLAYER
      sys_vendor: ONE-NETBOOK
      cpu_vendor: GenuineIntel
  - dmi_data:
      product_name: ONE XPLAYER
      sys_vendor: ONE-NETBOOK TECHNOLOGY CO., LTD.
      cpu_vendor: GenuineIntel

# One or more source devices to combine into a single virtual device. The events
# from these devices will be watched and translated according to the capability map.
source_devices:
  - group: gamepad
    evdev:
      name: OneXPlayer Gamepad
      phys_path: usb-0000:00:14.0-9/input0
  - group: keyboard
    evdev:
      name: AT Translated Set 2 keyboard
      phys_path: isa0060/serio0/input0

# The target input device(s) that will be created for this composite device
target_devices:
  - gamepad
  - mouse
  - keyboard

# The ID of a device capability mapping in the 'capability_maps' folder
capability_map_id: oxp1

In addition to combining multiple input devices together, composite devices can also have a "Capability Map" to define the real capabilities of the input device. This is commonly necessary for handheld gaming PCs where special non-standard buttons will emit keyboard events (like CTRL+ALT+DEL) instead of actual gamepad events.

Capability maps are defined in a separate YAML configuration file that follows the Capability Map Schema and are referenced by their unique ID.

A capability map configuration looks like this:

# yaml-language-server: $schema=https://raw.githubusercontent.com/ShadowBlip/InputPlumber/main/rootfs/usr/share/inputplumber/schema/capability_map_v1.json
version: 1
kind: CapabilityMap
name: OneXPlayer Type 1
id: oxp1

# List of mapped events that are activated by a specific set of activation keys.
mapping:
  - name: Orange Button
    source_events:
      - keyboard: KeyLeftMeta
      - keyboard: KeyD
    target_event:
      gamepad:
        button: Guide

License

InputPlumber is licensed under THE GNU GPLv3+. See LICENSE for details.