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

Rudder pedals "CH Pro Pedals" incorrectly detected as accelerometer on Linux without udev #7500

Closed
felixhaedicke opened this issue Mar 18, 2023 · 8 comments · May be fixed by #7599
Closed
Milestone

Comments

@felixhaedicke
Copy link

When using SDL2 on Linux without udev enabled (e. g. in the Steam container runtime), the CH Pro Pedals are incorrectly detected as accelerometer, and not listed as a joystick. The CH Pro Pedals are a rudder pedals product.

Because it has three axes and no buttons, it is classified as an accelerometer in SDL_EVDEV_GuessDeviceClass() (see src/core/linux/SDL_evdev_capabilities.c).

Proposals for solution:

  • Make an exception for this particular device (detected by USB VID 0x068e / PID 0x00f2) not to classify as a joystick.
  • Rely on the property INPUT_PROP_ACCELEROMETER being set by the Linux kernel (since 4.0) instead of checking the number of axes / existence of buttons to detect accelerometers.

The algorithm systemd-udev uses to detect accelerometers is very similar to what SDL does. It also does not rely on the property INPUT_PROP_ACCELEROMETER, but also classifies devices with three axes and no buttons as accelerometers (see https://github.com/systemd/systemd/blob/v253/src/udev/udev-builtin-input_id.c#L185). However, for this particular product, there is a hwdb rule (see systemd/systemd@230ed4c).

felixhaedicke added a commit to felixhaedicke/SDL that referenced this issue Mar 18, 2023
…r when udev is not used

The CH Pro Pedals are incorrectly classified as accelerometer in
SDL_EVDEV_GuessDeviceClass(), because it has three axes and no buttons.

This introduces the new function IsExplicitlyKnwownAsJoystick() to check
if a device is known to be a joystick by checking the vendor / product
ID. For now, this functions checks for the CH Pro Pedals, and returns
SDL_FALSE for all other devices, to proceed with the check via
GuessIsJoystick() as before.

Furthermore, the call to GuessIsJoystick() is now done after product id
determination in IsJoystick(), to be able to perform the
IsExplicitlyKnwownAsJoystick() before calling GuessIsJoystick().

Fixes libsdl-org#7500.
@smcv
Copy link
Contributor

smcv commented Apr 3, 2023

Rely on the property INPUT_PROP_ACCELEROMETER being set by the Linux kernel (since 4.0) instead of checking the number of axes / existence of buttons to detect accelerometers.

Unfortunately, there's a backwards-compatibility issue there. Before INPUT_PROP_ACCELEROMETER was invented, the kernel would report accelerometers as a device with X, Y and Z axes and no buttons, with no special identifying flags that could distinguish them from three pedals with X, Y and Z axes and no buttons. SDL can't distinguish between the two reasons to not have that flag set: "it's an accelerometer, but your kernel or driver is too old to know that flag" and "it genuinely isn't an accelerometer".

If there was a flag that positively identified a device as a gaming input device (INPUT_PROP_JOYSTICK or INPUT_PROP_GAMING or something), then SDL could treat that as high-priority; but that doesn't currently exist.

smcv added a commit to smcv/SDL that referenced this issue Apr 11, 2023
These devices have been reported in various places to be detected as
either accelerometers or unknown devices, because they do not report
any of the buttons that we use to identify a likely joystick.

Resolves: libsdl-org#7500
Co-authored-by: Felix Hädicke <[email protected]>
Signed-off-by: Simon McVittie <[email protected]>
smcv added a commit to smcv/SDL that referenced this issue Jun 13, 2023
smcv added a commit to smcv/SDL that referenced this issue Jun 13, 2023
smcv added a commit to smcv/SDL that referenced this issue Jun 13, 2023
These simulation control devices are known to be joysticks, but don't
all have enough information in their evdev capabilities for us to be
able to distinguish them from an accelerometer by capabilities alone.
If we look at the bus type, vendor ID and product ID as well, then
that gives us enough information to distinguish.

Resolves: libsdl-org#7500
Co-authored-by: Felix Hädicke <[email protected]>
Signed-off-by: Simon McVittie <[email protected]>
@slouken slouken added this to the 3.2.0 milestone Nov 8, 2023
@twhitehead
Copy link
Contributor

Read the explanation over on the proton issue.

Got me thinking, maybe, even if you can't communicate with udev properly/reliably across the container boundary, you could use the hwdb. That is, instead of duplicating a chunk of the hwdb inside SDL, how about adding to SDL the ability to import and use the hwdb file?

It shouldn't be too hard to get this into the container environment. If it isn't felt that the binary format is stable enough, you can go with a text dump

systemd-analyze cat-config udev/hwdb.d

In the event the OS one cannot be had, it could use a static baked in one.

@twhitehead
Copy link
Contributor

twhitehead commented Nov 28, 2023

To be clear, I am thinking essentially having two separate databases (udev one and SDL) is good to avoid. It is a pain to have to put overrides in two places, they inevitably windup disagreeing, and that leads to confusing results.

@twhitehead
Copy link
Contributor

twhitehead commented Nov 29, 2023

Was just looking at the hwdb API and code. It just reads the hwdb.bin file, which is a trie for looking up the key strings. There isn't any fancy encoding beyond the trie, which would be expected given the API (it is all strings), and is evident from running strings on the hwdb.bin file.

It also is versioned with the API returning an error if it cannot load the file. From the actual code, it looks like there have been three versions, with the third being introduced over seven years ago (added a priority field to help resolve conflicts), and in a way that was actually still interoperable with the second. So that all seems pretty self contained, container friendly, and quite stable.

Wine actually has some pretty succinct udev code to determine a device type. The udev code is just a tiny wrapper around the sd-device functions, which are now recommend to be used instead. Scanning over this code, it looks to just pokes /sys and pull udev assigned attributes by reading plain text key value pairs from associated /run/udev/data/<device> files.

I know you mentioned there were problems with udev for device event notification across container boundaries due to different versions of udev. The sd-device (and even more so sd-hwdb) querying interface really doesn't seem to be doing that sort of thing though, so maybe there could be an option to just look up device type using sd-device or even just sd-hwdb between full udev and falling back to a baked in device ids?

@smcv
Copy link
Contributor

smcv commented Nov 29, 2023

I know you mentioned there were problems with udev for device event notification across container boundaries due to different versions of udev

There are two related concerns, which I think you might be mixing up here:

  • The format of the communication between udevd and the libudev/sd-device client libraries is not a stable format, so there is no guarantee that the container's libudev or libsystemd can communicate successfully with the host's dissimilar udevd version. Unfortunately, this includes /run/udev/data: the files in that directory are considered to be private to the specific version of udevd/libudev/libsystemd that is running on the host, and have no stability guarantee. This is a problem with dissimilar versions, and would equally affect legacy chroot environments. (In practice, /run/udev is sufficiently stable that it works more often than it fails, and Steam Linux Runtime containers do share it read-only with the container, on the basis that it sometimes helps and we've never observed it to hurt.)

  • And, udevd's device event notification - not the data in general, but specifically the change-notification - cannot successfully pass a user namespace boundary, which notably includes Flatpak and Steam Linux Runtime containers (because they are unable to verify that the netlink message was sent by root, as opposed to some malicious local user). This is a problem with the user-namespace boundary, and would apply equally even if the versions of udevd/libudev/libsystemd all matched exactly.

@twhitehead
Copy link
Contributor

Thanks very much for all the clarification. I think I have a pretty good understanding now, so I submitted a patch. 👍

@twhitehead
Copy link
Contributor

twhitehead commented Dec 3, 2023

If anyone want to try things with the patch, I rebuilt libSDL2 for all the current steam runtimes. You can get them here (see the README.txt file for how to install them).

Note that this may not effect all programs. You can check what libSDL2 a program is using by running

lsof -p <PID> | fgrep libSDL2

where <PID> is the process id obtained from looking the program up with ps -HU $USER. On my system, for example, while Proton uses the steam runtime libSDL2.so, steam itself uses my OS libSDL2.so.

@slouken
Copy link
Collaborator

slouken commented May 21, 2024

This patch has been merged, thanks!

@slouken slouken closed this as completed May 21, 2024
smcv added a commit to smcv/SDL that referenced this issue Aug 6, 2024
smcv added a commit to smcv/SDL that referenced this issue Aug 6, 2024
smcv added a commit to smcv/SDL that referenced this issue Aug 6, 2024
These simulation control devices are known to be joysticks, but don't
all have enough information in their evdev capabilities for us to be
able to distinguish them from an accelerometer by capabilities alone.
If we look at the bus type, vendor ID and product ID as well, then
that gives us enough information to distinguish.

Resolves: libsdl-org#7500
Co-authored-by: Felix Hädicke <[email protected]>
Signed-off-by: Simon McVittie <[email protected]>
smcv added a commit to smcv/SDL that referenced this issue Aug 6, 2024
smcv added a commit to smcv/SDL that referenced this issue Aug 6, 2024
smcv added a commit to smcv/SDL that referenced this issue Aug 6, 2024
These simulation control devices are known to be joysticks, but don't
all have enough information in their evdev capabilities for us to be
able to distinguish them from an accelerometer by capabilities alone.
If we look at the bus type, vendor ID and product ID as well, then
that gives us enough information to distinguish.

Resolves: libsdl-org#7500
Co-authored-by: Felix Hädicke <[email protected]>
Signed-off-by: Simon McVittie <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants