{"id":19852720,"url":"https://github.com/shadowblip/inputplumber","last_synced_at":"2026-01-05T19:22:10.774Z","repository":{"id":204828940,"uuid":"712697057","full_name":"ShadowBlip/InputPlumber","owner":"ShadowBlip","description":"Open source input router and remapper daemon for Linux ","archived":false,"fork":false,"pushed_at":"2025-07-27T19:26:35.000Z","size":1994,"stargazers_count":239,"open_issues_count":59,"forks_count":28,"subscribers_count":8,"default_branch":"main","last_synced_at":"2025-07-27T21:30:50.885Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ShadowBlip.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-11-01T02:05:22.000Z","updated_at":"2025-07-25T13:59:35.000Z","dependencies_parsed_at":null,"dependency_job_id":"111ab45c-6c46-44ea-875d-dfcbe958de87","html_url":"https://github.com/ShadowBlip/InputPlumber","commit_stats":null,"previous_names":["shadowblip/handbus","shadowblip/inputplumber"],"tags_count":193,"template":false,"template_full_name":null,"purl":"pkg:github/ShadowBlip/InputPlumber","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ShadowBlip%2FInputPlumber","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ShadowBlip%2FInputPlumber/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ShadowBlip%2FInputPlumber/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ShadowBlip%2FInputPlumber/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ShadowBlip","download_url":"https://codeload.github.com/ShadowBlip/InputPlumber/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ShadowBlip%2FInputPlumber/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268448168,"owners_count":24251994,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-02T02:00:12.353Z","response_time":74,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-12T14:04:07.776Z","updated_at":"2025-12-30T12:21:29.348Z","avatar_url":"https://github.com/ShadowBlip.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/ShadowBlip/InputPlumber/main/icon.svg\" alt=\"InputPlumber Logo\" width=\"200\"\u003e\n  \u003cbr\u003e\n  InputPlumber\n\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/ShadowBlip/InputPlumber/stargazers\"\u003e\u003cimg src=\"https://img.shields.io/github/stars/ShadowBlip/InputPlumber\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/ShadowBlip/InputPlumber/blob/main/LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/github/license/ShadowBlip/InputPlumber\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://discord.gg/Ea9ABXhtkv\"\u003e\u003cimg alt=\"Discord\" src=\"https://img.shields.io/discord/721211671124770837?label=discord\" /\u003e\u003c/a\u003e\n  \u003cbr\u003e\n\u003c/p\u003e\n\nTable of Contents:\n- [About](#about)\n    - [Features](#features)\n- [Install](#install)\n- [Documentation](#documentation)\n- [Usage](#usage)\n    - [Input Profiles](#input-profiles)\n    - [Intercept Mode](#intercept-mode)\n    - [Virtual Keyboard](#virtual-keyboard)\n    - [Device Compositing \u0026 Capability Maps](#device-compositing--capability-maps)\n    - [Troubleshooting](#troubleshooting)\n- [License](#license)\n\n## About\n\nInputPlumber is an open source input routing and control daemon for Linux. It can\nbe used to combine any number of input devices (like gamepads, mice, and keyboards)\nand translate their input to a variety of virtual device formats.\n\n### Features\n\n- [x] Combine multiple input devices\n- [x] Emulate mouse, keyboard, and gamepad inputs\n- [x] Intercept and route input over DBus for overlay interface control\n- [x] Input mapping profiles to translate source input into the desired target input\n- [ ] Route input over the network\n\n## Install\n\nInputPlumber requires the following system dependencies:\n\n- `libevdev`\n- `libiio`\n\nYou can install with:\n\n```bash\nmake build\nsudo make install\n```\n\nIf you are using Arch Linux or any of its derivatives,\nyou can install InputPlumber from the official repositories:\n\n```bash\nsudo pacman -S inputplumber\n```\n\nThen start the service with:\n\n```bash\nsudo systemctl enable inputplumber\nsudo systemctl enable inputplumber-suspend\nsudo systemctl start inputplumber\n```\n\n## Documentation\n\nXML specifications for all interfaces can be found in [bindings/dbus-xml](./bindings/dbus-xml).\n\n## Usage\n\nWhen InputPlumber is running as a service, you can interact with it over DBus.\nThere are various DBus libraries available for popular programming languages\nlike Python, Rust, C++, etc.\n\nYou can also interface with DBus using the `busctl` command:\n\n```bash\nbusctl tree org.shadowblip.InputPlumber\n```\n\n### Input Profiles\n\nInputPlumber is capable of loading input device profiles to translate inputs into\nany other supported input event. Input profiles are defined as YAML configuration\nfiles that can be loaded on-demand for any device that InputPlumber manages. The\nformat of an input profile config is defined by the [Device Profile Schema](rootfs/usr/share/inputplumber/schema/device_profile_v1.json) to make it easier to create profiles.\n\nTypically input profiles should be generated using an external tool, but you\ncan manually create your own profiles using any text editor. If you use an editor\nthat supports the [YAML Language Server](https://github.com/redhat-developer/yaml-language-server)\nyou can write profiles with auto-complete and usage information.\n\nHere is a short example:\n\n```yaml\n# yaml-language-server: $schema=https://raw.githubusercontent.com/ShadowBlip/InputPlumber/main/rootfs/usr/share/inputplumber/schema/device_profile_v1.json\nversion: 1\nkind: DeviceProfile\nname: Start Button to Escape Key\ndescription: Profile to map a gamepad's start button to the Escape keyboard key\n\nmapping:\n  - name: Menu\n    source_event:\n      gamepad:\n        button: Start\n    target_events:\n      - keyboard: KeyEsc\n```\n\nThis example will remap the `Start` button from a gamepad to the `ESC` key.\n\nTo load the input profile, you can use the `LoadProfilePath` method on the input\ndevice you want the profile applied to. You can also do this from the command\nline using `busctl`:\n\n```bash\nbusctl call org.shadowblip.InputPlumber \\\n  /org/shadowblip/InputPlumber/CompositeDevice0 \\\n  org.shadowblip.Input.CompositeDevice \\\n  LoadProfilePath \"s\" /usr/share/inputplumber/profiles/mouse_keyboard_wasd.yaml\n```\n\n### Intercept Mode\n\nIntercept Mode is a feature of InputPlumber that can allow external applications\nto intercept input events from an input device and re-route them over DBus\ninstead. The primary use case for this feature is typically to allow overlay\napplications (like [OpenGamepadUI](https://github.com/ShadowBlip/OpenGamepadUI))\nto stop input from reaching other running applications (like a game),\nallowing the overlay to process inputs without those inputs leaking into other\nrunning apps.\n\nYou can set the intercept mode by setting the `InterceptMode` property on the\ninput device you want to intercept input from. The intercept mode can be one\nof three values:\n\n- `0` (NONE) - No inputs are intercepted and re-routed\n- `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).\n- `2` (ALL) - All inputs are intercepted and re-routed over DBus\n- `3` (GAMEPAD_ONLY) - All gamepad inputs are intercepted and re-routed over DBus\n\nTypically the intercept mode should be handled by an external application, but\nyou can also set the intercept mode from the command line using `busctl`:\n\n```bash\nbusctl set-property org.shadowblip.InputPlumber \\\n  /org/shadowblip/InputPlumber/CompositeDevice0 \\\n  org.shadowblip.Input.CompositeDevice \\\n  InterceptMode u 2\n```\n\n### Virtual Keyboard\n\nWhen InputPlumber is running, a virtual keyboard is created that is used for\nsending keyboard inputs. You can also use this keyboard to send keyboard events\nusing the DBus interface with the `SendKey` method. You can do this from the\ncommand line using `busctl`:\n\n```bash\nbusctl call org.shadowblip.InputPlumber \\\n  /org/shadowblip/InputPlumber/devices/target/keyboard0 \\\n  org.shadowblip.Input.Keyboard \\\n  SendKey sb KEY_ESC 1\n```\n\n### Device Compositing \u0026 Capability Maps\n\nOne feature of InputPlumber is the ability to combine multiple input devices\ntogether into a single logical input device called a \"Composite Device\". This is\noften required for many handheld gaming PCs that have built-in gamepads with\nspecial non-standard buttons that show up as multiple independent input devices.\n\nComposite devices are defined as YAML configuration files that follow the\n[Composite Device Schema](./rootfs/usr/share/inputplumber/schema/composite_device_v1.json)\nto combine the defined input devices together. When InputPlumber starts up, it\nlooks at all the input devices on the system and checks to see if they match a\ncomposite device configuration. If they do, the input devices are combined into\na single logical composite device.\n\nA composite device configuration looks like this:\n\n```yaml\n# yaml-language-server: $schema=https://raw.githubusercontent.com/ShadowBlip/InputPlumber/main/rootfs/usr/share/inputplumber/schema/composite_device_v1.json\nversion: 1\nkind: CompositeDevice\nname: OneXPlayer Intel\n\n# Only check for source devices if *any* of the given data matches. If this list is\n# empty, then the source devices will *always* be checked.\nmatches:\n  - dmi_data:\n      product_name: ONEXPLAYER\n      sys_vendor: ONE-NETBOOK\n      cpu_vendor: GenuineIntel\n  - dmi_data:\n      product_name: ONE XPLAYER\n      sys_vendor: ONE-NETBOOK TECHNOLOGY CO., LTD.\n      cpu_vendor: GenuineIntel\n\n# One or more source devices to combine into a single virtual device. The events\n# from these devices will be watched and translated according to the capability map.\nsource_devices:\n  - group: gamepad\n    evdev:\n      name: OneXPlayer Gamepad\n      phys_path: usb-0000:00:14.0-9/input0\n  - group: keyboard\n    evdev:\n      name: AT Translated Set 2 keyboard\n      phys_path: isa0060/serio0/input0\n\n# The target input device(s) that will be created for this composite device\ntarget_devices:\n  - gamepad\n  - mouse\n  - keyboard\n\n# The ID of a device capability mapping in the 'capability_maps' folder\ncapability_map_id: oxp1\n```\n\nIn addition to combining multiple input devices together, composite devices can\nalso have a \"Capability Map\" to define the real capabilities of the input\ndevice. This is commonly necessary for handheld gaming PCs where special\nnon-standard buttons will emit keyboard events (like `CTRL`+`ALT`+`DEL`) instead\nof actual gamepad events.\n\nCapability maps are defined in a separate YAML configuration file that follows\nthe [Capability Map Schema](./rootfs/usr/share/inputplumber/schema/capability_map_v1.json)\nand are referenced by their unique ID.\n\nA capability map configuration looks like this:\n\n```yaml\n# yaml-language-server: $schema=https://raw.githubusercontent.com/ShadowBlip/InputPlumber/main/rootfs/usr/share/inputplumber/schema/capability_map_v2.json\nversion: 2\nkind: CapabilityMap\nname: OneXPlayer Type 1\nid: oxp1\n\n# List of mapped events\nmapping:\n  - name: A to B\n    source_events:\n      - evdev:\n          event_type: KEY\n          event_code: BTN_SOUTH\n          value_type: button\n    target_event:\n      gamepad:\n        button: East\n\n  - name: B to A\n    source_events:\n      - evdev:\n          event_type: KEY\n          event_code: BTN_EAST\n          value_type: button\n    target_event:\n      gamepad:\n        button: South\n\n  - name: X + Y to Start\n    mapping_type:\n      evdev: chord\n    source_events:\n      - evdev:\n          event_type: KEY\n          event_code: BTN_WEST\n          value_type: button\n      - evdev:\n          event_type: KEY\n          event_code: BTN_NORTH\n          value_type: button\n    target_event:\n      gamepad:\n        button: Start\n\n  - name: X to Y delay\n    mapping_type:\n      evdev: delayed_chord\n    source_events:\n      - evdev:\n          event_type: KEY\n          event_code: BTN_NORTH\n          value_type: button\n    target_event:\n      gamepad:\n        button: West\n```\n\n### Troubleshooting\n\nFind the InputPlumber version:\n\n```bash\ninputplumber --version\n```\n```\ninputplumber 0.58.7\n```\n\nStart InputPlumber with debug logs enabled.\n\nTemporarily:\n\n```bash\nsudo systemctl stop inputplumber\nsudo LOG_LEVEL=debug inputplumber\n```\n\nPermanently:\n\n```bash\nsudo cp /usr/lib/systemd/system/inputplumber.service /etc/systemd/system/\nsudo sed -i 's/LOG_LEVEL=info/LOG_LEVEL=debug/g' /etc/systemd/system/inputplumber.service\nsudo systemctl daemon-reload\nsudo systemctl restart inputplumber\n```\n\nView debug logs:\n\n```bash\nsudo journalctl --unit inputplumber.service\n```\n\nList managed devices:\n\n```bash\ninputplumber devices list\n```\n```\n╭────┬───────────────╮\n│ Composite Devices  │\n├────┼───────────────┤\n│ Id │ Name          │\n├────┼───────────────┤\n│ 0  │ ASUS ROG Ally │\n╰────┴───────────────╯\nFound 1 composite device(s)\n```\n\nView the current intercept mode for the first managed device:\n\n```bash\ninputplumber device 0 intercept get\n```\n```\nCurrent intercept mode: none\n```\n\nChange the intercept mode of the first device:\n\n```bash\ninputplumber device 0 intercept set --help\ninputplumber device 0 intercept set $MODE\n```\n\nView what InputPlumber profiles are loaded and what event interfaces are being used:\n\n```bash\ninputplumber device 0 info\n```\n```\n╭────┬───────────────┬──────────────┬─────────────────────────────────────────────────────────────────────────────────────────────────────────╮\n│ Composite Device                                                                                                                            │\n├────┼───────────────┼──────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────┤\n│ Id │ Name          │ Profile Name │ Source Devices                                                                                          │\n├────┼───────────────┼──────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────┤\n│ 0  │ ASUS ROG Ally │ Default      │ [\"/dev/hidraw2\", \"/dev/input/event3\", \"/dev/input/event4\", \"/dev/input/event5\", \"/dev/iio:device0\", \"\"] │\n╰────┴───────────────┴──────────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────╯\n```\n\nFind the related configuration file (replace \"ASUS ROG Ally\" with the \"Name\" from the previous output):\n\n```bash\ngrep --recursive --files-with-matches --basic-regexp \"name: ASUS ROG Ally$\" /usr/share/inputplumber/devices/\n```\n```\n/usr/share/inputplumber/devices/50-rog_ally.yaml\n```\n\nStart the built-in test tool (recommended to run in a separate window):\n\n```bash\ninputplumber device 0 test\n```\n\nView what input devices are being emulated for the first device:\n\n```bash\ninputplumber device 0 targets list\n```\n```\n╭────────────┬───────────────────────────────╮\n│ Target Devices                             │\n├────────────┼───────────────────────────────┤\n│ Id         │ Name                          │\n├────────────┼───────────────────────────────┤\n│ mouse      │ InputPlumber Mouse            │\n├────────────┼───────────────────────────────┤\n│ keyboard   │ InputPlumber Keyboard         │\n├────────────┼───────────────────────────────┤\n│ xbox-elite │ Microsoft X-Box One Elite pad │\n╰────────────┴───────────────────────────────╯\n```\n\nView what events are being captured by InputPlumber:\n\n```bash\nsudo evtest\n```\n```\nNo device specified, trying to scan all of /dev/input/event*\nAvailable devices:\n/dev/input/event0:\tPower Button\n/dev/input/event1:\tSleep Button\n/dev/input/event10:\tHD-Audio Generic HDMI/DP,pcm=3\n/dev/input/event11:\tHD-Audio Generic Mic\n/dev/input/event12:\tHD-Audio Generic Mic\n/dev/input/event13:\tHD-Audio Generic Headphone\n/dev/input/event14:\tMicrosoft X-Box One Elite 2 pad\n/dev/input/event15:\tInputPlumber Mouse\n/dev/input/event16:\tInputPlumber Keyboard\n/dev/input/event2:\tAT Translated Set 2 keyboard\n/dev/input/event3:\tMicrosoft X-Box 360 pad\n/dev/input/event4:\tROG Ally Keyboard\n/dev/input/event5:\tROG Ally Mouse\n/dev/input/event6:\tNVTK0603:00 0603:F200\n/dev/input/event7:\tVideo Bus\n/dev/input/event8:\tPC Speaker\n/dev/input/event9:\tAsus WMI hotkeys\nSelect the device event number [0-16]: 14\n```\n\nStop InputPlumber and then view what events are being captured by the physical device:\n\n```bash\nsudo systemctl stop inputplumber\nsudo evtest\n```\n```\nNo device specified, trying to scan all of /dev/input/event*\nAvailable devices:\n/dev/input/event0:\tPower Button\n/dev/input/event1:\tSleep Button\n/dev/input/event10:\tHD-Audio Generic HDMI/DP,pcm=3\n/dev/input/event11:\tHD-Audio Generic Mic\n/dev/input/event12:\tHD-Audio Generic Mic\n/dev/input/event13:\tHD-Audio Generic Headphone\n/dev/input/event2:\tAT Translated Set 2 keyboard\n/dev/input/event3:\tMicrosoft X-Box 360 pad\n/dev/input/event4:\tROG Ally Keyboard\n/dev/input/event5:\tROG Ally Mouse\n/dev/input/event6:\tNVTK0603:00 0603:F200\n/dev/input/event7:\tVideo Bus\n/dev/input/event8:\tPC Speaker\n/dev/input/event9:\tAsus WMI hotkeys\nSelect the device event number [0-13]: 3\n```\n\n## License\n\nInputPlumber is licensed under THE GNU GPLv3+. See [LICENSE](LICENSE) for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshadowblip%2Finputplumber","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshadowblip%2Finputplumber","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshadowblip%2Finputplumber/lists"}