Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Controller hotplugging on Native applications does not function under Steam Linux Runtime #550

Open
ZereoX opened this issue Dec 16, 2022 · 3 comments

Comments

@ZereoX
Copy link

ZereoX commented Dec 16, 2022

Your system information

  • Steam Runtime Version: 1671133406
  • Distribution (e.g. Ubuntu 18.04): 20.04
  • Link to your full system information (Help -> System Information) in a Gist: https://gist.github.com/ZereoX/b1648fdd5a4d81ad3e6201db69528f58
  • Have you checked for system updates?: Yes
  • What compatibility tool are you using?: Steam Linux Runtime
  • If you are using Steam Linux Runtime for native Linux games: What versions are listed in SteamLinuxRuntime/VERSIONS.txt? 0.20220825.57 / v0.20220823.0-0-gcc4e44f
  • If you are using Steam Linux Runtime, or Proton 5.13 or newer: What versions are listed in SteamLinuxRuntime_soldier/VERSIONS.txt? 0.20221018.74 / 0.20221014.0 / v0.20220823.0-0-gcc4e44f / 0.20221017.1 (depot / p-v / scripts / soldier).

Please describe your issue in as much detail as possible:

In the title I MAED A GAM3 W1TH Z0MB1ES 1N IT!!!1, users are prompted to join in via the "A" button on a gamepad on the title screen. This leads to the primary point of failure that if controllers is not plugged in prior to launch, plugging one at this point will not allow the user to proceed. This therefore requires the game to be closed, controller plugged in, and title relaunched. The second point of failure is after starting a match if the controller is accidentally disconnected (batteries dies) or unplugged (faulty USB port) the game will automatically pause itself and only allow the player who paused to resume play. Once the controller is reconnected, the title no longer recognizes that gamepad. You are therefore stuck to use the keyboard to proceed. On Steam Deck, that isn't an option and you therefore have to force quit the game and relaunch.

The points of failure are the following:

  1. Title does not register controller input if the device is plugged in after launch.
  2. Title does not re-register a controller if it was previously unplugged or disconnected while the title is open.

Neither of these issues are present when the title is ran without Steam Linux Runtime or when the Windows build is ran using Proton (7.0-5).

SLR Log: slr-app1800730-t20221216T084942.log

Steps for reproducing this issue:

Pre-requisites / Setup:

  • Xbox Gamepad (360 / One / X) is required (an external controller is also required if reproducing on Steam Deck).
  • Download and install the free game I MAED A GAM3 W1TH Z0MB1ES 1N IT!!!1.
  • On the Game Details Page, select the "Gear" -> "Properties" -> "Compatibility" and check "Force the use of a specific [...]".
  • From the dropdown menu that appears, select "Steam Linux Runtime".

Issue 1:

  1. Make sure the Xbox controller is not plugged in.
  2. Select "Play" on the Game Details Page to launch the title.
  3. Once on the title screen, plug in the Xbox controller.
  4. Attempt to press "A" twice to join and ready up.

Issue 2:

  1. Make sure the Xbox controller is plugged in.
  2. Select "Play" on the Game Details Page to launch the title.
  3. Once on the title screen, press "A" twice to join and ready up.
  4. Once in-game, disconnect the controller.
  5. Reconnect the controller and attempt to resume.
@smcv
Copy link
Contributor

smcv commented Jan 5, 2023

This likely needs changes in that specific game, or in a middleware library that it uses, and cannot be solved from the runtime side. Controller hotplugging generally works in the container in games that use a sufficiently recent version of SDL, or Proton (because I contributed code to make that happen).

If the game uses some other middleware instead of SDL, or uses its own game-specific code instead of SDL, then it is up to that code to implement controller hotplug detection. The typical way to do that on Linux is monitoring udevd via libudev, but unfortunately that cannot work in either a Steam Linux Runtime or Flatpak container, for two reasons:

  • The signalling protocol between udevd and libudev is not compatible with crossing a user namespace boundary. For security, libudev needs to validate that the message was really sent by uid 0 (root), but the real system's uid 0 cannot be made visible inside the container as a result of a kernel security restriction, so all libudev can tell is that the message was sent by some other user. It cannot tell whether this is a genuine message or an attack by a malicious local user, and therefore ignores it.
  • Even without hotplug being involved, the communication between udevd and libudev is not container-friendly, because there is no guarantee that libudev will understand the device information shared by a different version of udevd. A large part of the point of container technologies like Flatpak and the Steam Linux Runtime is to give games a predictable version of shared libraries, but that predictable version is probably not the same as the version of udevd.

SDL and Proton both detect that they are in a container by checking for the existence of /run/host/container-manager; if they are, instead of using libudev, they enumerate game controllers more directly by reading /dev and /sys. The implementation in SDL would be a good example.

@smcv
Copy link
Contributor

smcv commented Jan 5, 2023

According to SteamDB, the game with zombies in contains a bundled copy of SDL 2. Resolving this might be as simple as moving that copy out of the way so that the one provided by the Steam Runtime is used.

@smcv
Copy link
Contributor

smcv commented Jan 5, 2023

This is working fine for me with the Steam Linux Runtime - soldier beta branch, on Debian testing, with an Xbox 360 wired controller. What exact controller are you reproducing this with? They are not all the same: Playstation and Nintendo controllers, and I think maybe some newer Xbox controllers?, use the standard HID interface, but older Xbox controllers like the one I have only support an Xbox-specific protocol.

The bundled copy of SDL 2 appears to be somewhere around 2.0.15 as far as I can tell, which is not ideal, but should mostly work. The container runtime currently provides SDL 2.24.x (in the default branch) or 2.26.0 (in the beta branch) and should get 2.26.2 soon, so using the runtime's SDL would probably be better than the game's.

The Steam Runtime provides a diagnostic tool for this sort of thing. If you run this command in a terminal:

~/.steam/root/ubuntu12_32/steam-runtime/amd64/usr/bin/steam-runtime-input-monitor --direct

you should see some information about the controllers you have plugged in right now ("coldplug"), then a line that says {"all-for-now": true}. After that, if you plug or unplug a controller, information about it should appear.

If you run the tool like that, it is running outside the container, but using the same logic that SDL would select when run inside the container.

Similarly, if you run

~/.steam/root/ubuntu12_32/steam-runtime/amd64/usr/bin/steam-runtime-input-monitor --udev

it will discover controllers and other input devices via udev (which will also show keyboards, mice, touchscreens, sound cards with headphone detection, and more).

For games that run in the container, if you set a game's launch options to

PRESSURE_VESSEL_SHELL=instead %command%

and launch the game, you will get a terminal where you can try the same commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants