We are currently migrating Bugzilla to GitHub issues.
Any changes made to the bug tracker now will be lost, so please do not post new bugs or make changes to them.
When we're done, all bug URLs will redirect to their equivalent location on the new bug tracker.

Bug 4951 - Linux controller support, libusb vs libudev
Summary: Linux controller support, libusb vs libudev
Status: RESOLVED FIXED
Alias: None
Product: SDL
Classification: Unclassified
Component: joystick (show other bugs)
Version: HG 2.1
Hardware: x86_64 Linux
: P2 normal
Assignee: Sam Lantinga
QA Contact: Sam Lantinga
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2020-01-15 05:01 UTC by Anthony Pesch
Modified: 2020-02-05 19:30 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Anthony Pesch 2020-01-15 05:01:09 UTC
Hey Sam,

I recently enabled HIDAPI support on Linux (defining SDL_JOYSTICK_HIDAPI, SDL_USE_LIBUDEV and SDL_LIBUSB_DYNAMIC), and noticed that PS4 controllers on my Raspberry Pi stopped working.

Using only libusb works, but with SDL_USE_LIBUDEV enabled libusb gets unloaded during init and libudev fails I believe because my RPI setup doesn't have any /dev/input/hidraw* nodes without creating some extra udev rules.

It seems libusb and libudev both have their downsides here and I'm having a hard time understanding what's the ideal solution. The code unloading libusb if libudev is loaded makes it seem that libudev is preferred, but given that the PS4 controllers aren't working out the box on Raspbian with that makes it seem like there's some room for improvement.
Comment 1 Anthony Pesch 2020-01-15 05:41:08 UTC
Actually, never mind most of what I wrote - I misread some of the code at 1 AM and went down the wrong path.

The issue here was defining SDL_JOYSTICK_HIDAPI at all. Doing this causes the PS4 controller to end up going through SDL_hidapijoystick.c (vs linux/SDL_sysjoystick.c) which ultimately fails when SDL_LIBUSB_DYNAMIC is defined on this RPI4.

I'll debug this more tomorrow, but if you have some high-level info on what's the ideal setup here I'd love to hear it.
Comment 2 Anthony Pesch 2020-01-15 06:06:12 UTC
Last note for the night, adding the udev rules from https://steamcommunity.com/app/221410/discussions/0/1693795812304458372/ causes /dev/hidraw0 to show up which fixes this issue.

However, I would expect this to fallback to the support that is provided by linux/SDL_sysjoystick.c (which was working) in the event the HIDAPI path fails. It seems that doesn't work because of this line:

https://github.com/spurious/SDL-mirror/blob/master/src/joystick/linux/SDL_sysjoystick.c#L153

This seems to assume that the device can be opened by the HIDAPI code if the HIDAPI code says it exists, and therefor doesn't bother with it. I wonder if HIDAPI_IsDevicePresent can be modified to, somewhere down the line, not register the device if the device path can't be stat'd or some such.
Comment 3 Sam Lantinga 2020-01-16 06:26:48 UTC
FYI, here are the udev rules from the Steam Link app, which are recommended for use with SDL:
--- 55-steamlink.rules --
# USB devices
SUBSYSTEM=="usb", GROUP="plugdev"

# HID devices
KERNEL=="hidraw*", GROUP="input", MODE:="0660"
--

Then do:
sudo usermod -a -G input,plugdev $(id -un)
Comment 4 Sam Lantinga 2020-01-16 06:43:26 UTC
I looked at the libusb code but I didn't see a way to test to see if the device could be opened without trying to open it.

This is actually why the hidapi code isn't built by default. You can't just deploy it to a random target system and assume it will work. However, if you find a way to properly check whether a USB device can be opened, please let me know!
Comment 5 Sam Lantinga 2020-01-26 20:52:36 UTC
Fixed!
https://hg.libsdl.org/SDL/rev/596f725418ea
Comment 6 Anthony Pesch 2020-02-05 13:14:41 UTC
Hey Sam, just updated last night and can confirm that fixed the issue. Thanks a lot!
Comment 7 Sam Lantinga 2020-02-05 19:30:32 UTC
Great, thanks!