[GH-ISSUE #45] Make virtual input device identifiers (VID/PID/name) configurable #14

Closed
opened 2026-10-15 12:51:12 +00:00 by bsakaguchi · 2 comments
Owner

Originally created by @mwatola-glitch on GitHub (Jul 6, 2026).
Original GitHub issue: https://github.com/games-on-whales/inputtino/issues/45

Is your feature request related to a problem?

The virtual uinput devices created by inputtino use hardcoded identifiers: vendor 0xBEEF, product 0xDEAD, and fixed names like Mouse passthrough, Keyboard passthrough. Since both Sunshine and Wolf create their devices through inputtino, and the identifiers are identical for every caller, it is impossible to tell apart the virtual devices created by two independent host instances running on the same machine.

Concrete use case: I run two Sunshine instances on one Linux host - one streaming my own KDE/seat0 desktop, and one as a headless per-user session (headless sway + its own Sunshine) for a second user. Both instances create byte-identical uinput devices: 0xBEEF:0xDEAD, the same names, empty phys/uniq. As a result:

  • The compositor on seat0 (KWin) enumerates both instances' virtual devices, so the remote client's mouse input for the headless session leaks into my physical desktop (and vice versa).
  • There is no udev-matchable attribute (name / vendor / product / phys / uniq are all identical or empty) to target just one instance's devices, so no udev rule, ID_SEAT assignment, or per-device compositor setting can isolate one instance from the other.

This is the core blocker behind LizardByte/Sunshine#3768 ("Multiple Input Isolation").

Describe the solution you'd like

Let callers override the uinput device descriptor (name, vendor id, product id) when creating virtual devices, defaulting to the current hardcoded values for full backward compatibility. Something like:

struct DeviceDefinition {
  std::string name;          // default: current value ("Mouse passthrough", ...)
  uint16_t    vendor_id  = 0xBEEF;
  uint16_t    product_id = 0xDEAD;
  // ...existing fields...
};

With this, a second instance can be given a distinct VID (e.g. 0xF00D) or a name suffix, and then standard tooling (a udev ID_SEAT rule, or per-device enable/disable in the compositor) can isolate it cleanly - no hacks required.

What people have to do today (workaround)

Without configurable identifiers, the only way to distinguish instances is to patch the device identity from outside the process. In my case I LD_PRELOAD a small shim into one Sunshine instance that intercepts ioctl(UI_DEV_SETUP) and rewrites id.vendor 0xBEEF -> 0xF00D, then isolate that vendor in the compositor. It works, but:

  • it requires rewriting the device identity from outside the process, and
  • it is blocked when the Sunshine binary carries file capabilities (cap_sys_admin for KMS capture), because LD_PRELOAD is ignored under AT_SECURE - forcing a second, non-capped copy of the binary for the instance that only needs wlr capture.

A small config option in inputtino (surfaced by Sunshine/Wolf) would make all of this unnecessary and would unblock multi-instance isolation in general.

I'm happy to open a PR - an inputtino descriptor change (backward-compatible defaults) plus the config wiring in Sunshine - if the maintainers are open to this approach.

Originally created by @mwatola-glitch on GitHub (Jul 6, 2026). Original GitHub issue: https://github.com/games-on-whales/inputtino/issues/45 **Is your feature request related to a problem?** The virtual `uinput` devices created by inputtino use hardcoded identifiers: vendor `0xBEEF`, product `0xDEAD`, and fixed names like `Mouse passthrough`, `Keyboard passthrough`. Since both Sunshine and Wolf create their devices through inputtino, and the identifiers are identical for every caller, it is impossible to tell apart the virtual devices created by two independent host instances running on the same machine. **Concrete use case:** I run two Sunshine instances on one Linux host - one streaming my own KDE/seat0 desktop, and one as a headless per-user session (headless `sway` + its own Sunshine) for a second user. Both instances create byte-identical uinput devices: `0xBEEF:0xDEAD`, the same names, empty `phys`/`uniq`. As a result: - The compositor on `seat0` (KWin) enumerates *both* instances' virtual devices, so the remote client's mouse input for the headless session leaks into my physical desktop (and vice versa). - There is no udev-matchable attribute (name / vendor / product / phys / uniq are all identical or empty) to target just one instance's devices, so no udev rule, `ID_SEAT` assignment, or per-device compositor setting can isolate one instance from the other. This is the core blocker behind LizardByte/Sunshine#3768 ("Multiple Input Isolation"). **Describe the solution you'd like** Let callers override the uinput device descriptor (name, vendor id, product id) when creating virtual devices, defaulting to the current hardcoded values for full backward compatibility. Something like: ```cpp struct DeviceDefinition { std::string name; // default: current value ("Mouse passthrough", ...) uint16_t vendor_id = 0xBEEF; uint16_t product_id = 0xDEAD; // ...existing fields... }; ``` With this, a second instance can be given a distinct VID (e.g. `0xF00D`) or a name suffix, and then standard tooling (a udev `ID_SEAT` rule, or per-device enable/disable in the compositor) can isolate it cleanly - no hacks required. **What people have to do today (workaround)** Without configurable identifiers, the only way to distinguish instances is to patch the device identity from outside the process. In my case I `LD_PRELOAD` a small shim into one Sunshine instance that intercepts `ioctl(UI_DEV_SETUP)` and rewrites `id.vendor` `0xBEEF -> 0xF00D`, then isolate that vendor in the compositor. It works, but: - it requires rewriting the device identity from outside the process, and - it is blocked when the Sunshine binary carries file capabilities (`cap_sys_admin` for KMS capture), because `LD_PRELOAD` is ignored under `AT_SECURE` - forcing a second, non-capped copy of the binary for the instance that only needs `wlr` capture. A small config option in inputtino (surfaced by Sunshine/Wolf) would make all of this unnecessary and would unblock multi-instance isolation in general. I'm happy to open a PR - an inputtino descriptor change (backward-compatible defaults) plus the config wiring in Sunshine - if the maintainers are open to this approach.
Author
Owner

@ABeltramo commented on GitHub (Jul 7, 2026):

Let callers override the uinput device descriptor (name, vendor id, product id) when creating virtual devices

That is already the case:

github.com/games-on-whales/inputtino@b887f6a37a/include/inputtino/input.hpp (L22-L30)

Example usage:

github.com/games-on-whales/inputtino@b887f6a37a/tests/testUHID.cpp (L471-L482)

<!-- gh-comment-id:4901451914 --> @ABeltramo commented on GitHub (Jul 7, 2026): > Let callers override the uinput device descriptor (name, vendor id, product id) when creating virtual devices That is already the case: https://github.com/games-on-whales/inputtino/blob/b887f6a37a4f6babea66ee7b9a79bc8f520d7554/include/inputtino/input.hpp#L22-L30 Example usage: https://github.com/games-on-whales/inputtino/blob/b887f6a37a4f6babea66ee7b9a79bc8f520d7554/tests/testUHID.cpp#L471-L482
Author
Owner

@mwatola-glitch commented on GitHub (Jul 7, 2026):

Thanks @ABeltramo, you're right - I missed that inputtino already exposes name/vendor/product via DeviceDefinition. So the gap is purely on the consumer side: Sunshine creates the devices with the defaults and doesn't expose a way to override them per instance. I'll pursue that on the Sunshine side (LizardByte/Sunshine#3768). Appreciate the pointers!

<!-- gh-comment-id:4901507903 --> @mwatola-glitch commented on GitHub (Jul 7, 2026): Thanks @ABeltramo, you're right - I missed that inputtino already exposes name/vendor/product via `DeviceDefinition`. So the gap is purely on the consumer side: Sunshine creates the devices with the defaults and doesn't expose a way to override them per instance. I'll pursue that on the Sunshine side (LizardByte/Sunshine#3768). Appreciate the pointers!
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
games-on-whales/inputtino#14
No description provided.