Skip to content

Input device interface

Simon McVittie requested to merge wip/input-interface into master

Based on !164 (merged), please review that first.

This WIP branch adds an API for input devices, with the following implementations:

  • SrtDirectInputDeviceMonitor: direct (inotify, /dev, /sys; cannot get udev properties)
  • SrtUdevInputDeviceMonitor: udev (doesn't work in containers)
  • SrtPortalInputDeviceMonitor: a portal API across a private socket or the D-Bus session bus (incomplete) - moved to !159

Still to do:

  • API for opening device nodes: the default implementation used by the udev and direct backends will be to just get_dev_node() and open it, but a portal might have to go across the container boundary and ask a remote portal service to do it

Future work (not going to be in this branch, it's big enough already):

  • specifically detecting known controller models (Steam, Xbox, PS4, etc.)
  • diagnostics to detect wrong permissions etc. (rebasing/expanding !58)
  • parsing the output of steam-runtime-input-monitor into a series of SrtInputDevice objects
    • actually this wasn't so hard, so I added it
  • perhaps a SDL backend?

I'm not sure yet which of these routes we will follow to solve #11 (closed):

  1. Merge !159, and use the portal; modify Wine and SDL to dlopen and use libsteam-runtime-tools if they detect a pressure-vessel container; it will use the portal when run in containers.

  2. Merge !159, and ship the portal, but instead of dlopening libsteam-runtime-tools, reimplement the equivalent of SrtPortalInputDeviceMonitor separately in each of Wine and SDL, using libdbus, GDBus or sd-bus.

  3. Keep only this but not the rest of !159, modify Wine and SDL to dlopen and use libsteam-runtime-tools if they detect a container (it'll use the SrtDirectInputDeviceMonitor); we can switch to (1) without significant API changes.

  4. Keep only this and use it for diagnostic tools, but don't use !159, and instead:

    • SDL already has a code path similar to SrtDirectInputDeviceMonitor; fix it to:
      • use inotify instead of polling so it can detect devices being removed
      • have a better heuristic (taking inspiration from libmanette )
    • add the equivalent of SrtDirectInputDeviceMonitor to Wine, as an alternative to its current udev code, and automatically use that code path in containers
    • make steam-runtime-system-info list controllers (using steam-runtime-input-monitor --once), compare their udev properties with what we would guess from the evdev capabilities, and warn if there is a mismatch

At the moment I'm leaning towards (4).


  • input-device: Add skeleton API for enumeration and monitoring

    This includes:

    • a public interface implemented by input device monitors
    • a public interface to be implemented by the input devices they signal
    • a mock implementation for unit-testing
    • a unit test for the API
    • a simple implementation in terms of inotify on /dev
    • a monitor that can print input devices in JSON format on stdout, and optionally monitor them

    Implementations in terms of udev, SDL, or a portal service are not yet included. Details of the devices, beyond their paths in /dev and /sys, are also not included.

  • input-device: Add a monitor based on dlopening libudev

    This is the same approach used by SDL. It doesn't work well in most containers.

    To facilitate testing this, change sysroot/run-in-sysroot.py so that it doesn't share /run with the host, and signals "we're in a container" by creating /run/host.

  • input-device: Add udev properties

  • input-device: Add the uevent data structure

  • input-device: Add HID, input and usb_device ancestor devices

    Wine/Proton needs these for some of its HID functionality.

  • input-device: Add interface flags

    The name is to leave space for "type flags" (joystick, etc.) later.

  • input-device: Add device identity (vendor ID, etc.)

  • input-device: Add evdev capability flags

    This is the official way to determine what an input device is, at the kernel level.

  • input-device: Add evdev input properties

    These are a useful input for guessing what an input device is.

  • input-device: Add device-type flags

    These are what we really want for SDL and Wine: they're broadly equivalent to the udev ID_INPUT_FOO properties, and identify which devices are desired at a high level.

    Also add test coverage for the device-type-guessing heuristic. Thanks to various people in Collabora, Codeweavers and #debian-uk for providing sudo evemu-describe output for their devices.

  • input-device: Factor out a base class for self-contained implementations

  • input-device: Implement and test parsing input-device-monitor output

    We can use this later, in diagnostic tools.

  • input-device: Add an API for opening the device node

    We'll need this if the portal provides a way to open device nodes that don't exist in the container.

Edited by Simon McVittie

Merge request reports