protonscr

Gamepad ignored.

steamopen Big PicturereviewedGeneral controller / Steam Input
ValveSoftware/steam-for-linux#1894 · opened 2013-02-19 by V10lator · updated 2021-11-02 · 20 comments · github
1 matching comments, n / p to jump
VV10lator 2013-02-19 github

Today I became a Logitech F710. While jstest and simple games like and yet it moves work valve software does not:
Steams system information doesn't show any gamepad related infos. Big Picture mode tells me there is no gamepad and no valve game (neither source nor goldSrc based) seems to detect it.

I tried both, the in kernel (xpad) driver as well as the userspace (xboxdrv) one, none worked.

$ xboxdrv -L
 id | wid | idVendor | idProduct | Name
----+-----+----------+-----------+--------------------------------------
  0 |   0 |   0x046d |    0xc21f | Logitech F710
$ js_demo
Joystick test program.
[SNIPPED THIS AS IT CLOSES THE CODE TAG]
Joystick 0: "Xbox Gamepad (userspace driver)"
Joystick 1 not detected
...
$ lsusb | grep F710
Bus 005 Device 003: ID 046d:c21f Logitech, Inc. F710 Wireless Gamepad [XInput Mode]
Sslouken 2013-03-08 github

I'm not sure, I just tried a wired XBox 360 controller and it worked fine.

You can debug this by downloading the debug runtime and using gdb:
STEAM_RUNTIME=debug DEBUGGER=gdb steam
(gdb) b SDL_SYS_JoystickInit
(say yes when prompted that this symbol doesn't exist)
(gdb) r
...
Then step through the code when you get to SDL_SYS_JoystickInit

Let me know what you find! :)

Ggdrewb-valve maintainer 2013-08-16 github

Is this issue still active?

Ggdrewb-valve maintainer 2013-08-19 github

Closing pending confirmation this still occurs.

Llexa2 2013-09-28 github

I have just the same gamepad and had been experiencing just the same problems on my linux system.
After a bit of debugging (it was somewhat problematic as steam.sh prepends $STEAMROOT/$PLATFORM to preconstructed LD_LIBRARY_PATH resulting ldd picking up stripped version of libSDL2.0.so and gdb failing to break on unexported symbol SDL_SYS_JoystickInit) it had turned out that the problem was caused by incompatibilities between Steam runtime's libudev and actual udev runtime installed on my system.

OS I use is CentOS 6 x86_64 install with an updated version of glibc 2.17 I had built from sources using Fedora 19 (which is expected to became RHEL7 in future) source RPM as a base. As a consequence udev version and ruleset is pretty different comparing to what libudev which is bundled with steam runtime expects.

Actual place where problem hit is that SDL2 joystick detection routine with udev-support compiled-in and libudev initialization succeeded. SDL2 expects joystick device files to have udev property "ID_INPUT_JOYSTICK" to exist and be set to "1". It is not the case for udev ruleset as supplied in CentOS6/RHEL6, it marks joystics with ID_CLASS=="joystick" instead. This one could easily be fixed by adding udev rule like this one to /etc/udev/rules.d/99-steam-controller-custom.rules:

SUBSYSTEM=="input", ENV{ID_CLASS}=="joystick", ENV{ID_INPUT_JOYSTICK}="1"

But it won't fix the problem due to the way libudev accesses this database. It is not done as a something like dbus call to udevd daemon service, instead libudev goes on and parses udevd database (located in /dev/.udev). Here is the problem as could be easily shown by exporting UDEV_LOG=6 and executing a simple testcase program listed below:

#include <stdio.h>
#include <libudev.h>
#include <sys/time.h>
#include <sys/types.h>

static struct udev *udev = NULL;

int
main(void)
{
    struct udev_enumerate *enumerate = NULL;
    struct udev_list_entry *devs = NULL;
    struct udev_list_entry *item = NULL;

    udev = udev_new();
    if (udev == NULL) {
        printf("udev_new() failed\n");
        return -1;
    }

    enumerate = udev_enumerate_new(udev);
    if (enumerate == NULL) {
        printf("udev_enumerate_new() failed\n");
        return -2;
    }

    udev_enumerate_add_match_subsystem(enumerate, "input");
    udev_enumerate_add_match_property(enumerate, "ID_INPUT_JOYSTICK", "1");
    udev_enumerate_scan_devices(enumerate);
    devs = udev_enumerate_get_list_entry(enumerate);
    for (item = devs; item; item = udev_list_entry_get_next(item)) {
        const char *path = udev_list_entry_get_name(item);
        printf("%s\n", path);
    }

    udev_enumerate_unref(enumerate);

    return 0;
}

Testcase results without udev debug logging enabled:

[lexa2@lx2linux Temp]$ gcc -gdwarf-3 ./udevtest.c -o./udevtest -ludev
[lexa2@lx2linux Temp]$ ./udevtest
/sys/devices/pci0000:00/0000:00:12.2/usb1/1-3/1-3.2/1-3.2:1.0/input/input14/event14
/sys/devices/pci0000:00/0000:00:12.2/usb1/1-3/1-3.2/1-3.2:1.0/input/input14/js0
[lexa2@lx2linux Temp]$ LD_PRELOAD=~/.local/share/Steam/ubuntu12_32/steam-runtime-debug_2013-09-05/amd64/lib/x86_64-linux-gnu/libudev.so.0.13.0 ./udevtest
[lexa2@lx2linux Temp]$

As could be easily seen with system libudev everything works as expected but with steam-runtime libudev version no joysticks are found.

Enabling debug logging reveals the truth:

[lexa2@lx2linux Temp]$ UDEV_LOG=6 ./udevtest
libudev: udev_device_new_from_syspath: device 0x1971400 has devpath '/devices/pci0000:00/0000:00:12.2/usb1/1-3/1-3.2/1-3.2:1.0/input/input14/js0'
libudev: udev_device_read_db: device 0x1971400 filled with db file data
libudev: udev_device_new_from_syspath: device 0x1975410 has devpath '/devices/virtual/input/mice'
libudev: udev_device_read_db: device 0x1975410 filled with db symlink data '/dev/input/mice'
libudev: udev_device_new_from_syspath: device 0x1975410 has devpath '/devices/pci0000:00/0000:00:14.2/sound/card0/input10/event10'
libudev: udev_device_read_db: device 0x1975410 filled with db file data
libudev: udev_device_new_from_syspath: device 0x1975410 has devpath '/devices/pci0000:00/0000:00:14.2/sound/card0/input11/event11'
libudev: udev_device_read_db: device 0x1975410 filled with db file data
libudev: udev_device_new_from_syspath: device 0x1975410 has devpath '/devices/pci0000:00/0000:00:02.0/0000:01:00.1/sound/card3/input12/event12'
libudev: udev_device_read_db: device 0x1975410 filled with db file data
libudev: udev_device_new_from_syspath: device 0x1975410 has devpath '/devices/pci0000:00/0000:00:02.0/0000:01:00.1/sound/card3/input13/event13'
libudev: udev_device_read_db: device 0x1975410 filled with db file data
libudev: udev_device_new_from_syspath: device 0x1975410 has devpath '/devices/pci0000:00/0000:00:12.2/usb1/1-3/1-3.2/1-3.2:1.0/input/input14/event14'
libudev: udev_device_read_db: device 0x1975410 filled with db file data
libudev: udev_device_new_from_syspath: device 0x1975410 has devpath '/devices/pci0000:00/0000:00:14.4/0000:05:06.0/rc/rc0/input15/event15'
libudev: udev_device_read_db: device 0x1975410 filled with db file data
libudev: udev_device_new_from_syspath: device 0x1975410 has devpath '/devices/LNXSYSTM:00/device:00/PNP0C0C:00/input/input0/event0'
libudev: udev_device_read_db: device 0x1975410 filled with db file data
libudev: udev_device_new_from_syspath: device 0x1975410 has devpath '/devices/LNXSYSTM:00/LNXPWRBN:00/input/input1/event1'
libudev: udev_device_read_db: device 0x1975410 filled with db file data
libudev: udev_device_new_from_syspath: device 0x1975410 has devpath '/devices/pci0000:00/0000:00:13.0/usb5/5-1/5-1:1.2/0003:046D:C52B.0003/input/input2/event2'
libudev: udev_device_read_db: device 0x1975410 filled with db file data
libudev: udev_device_new_from_syspath: device 0x1975410 has devpath '/devices/pci0000:00/0000:00:12.0/usb4/4-5/4-5:1.2/0003:046D:C52B.0007/input/input3/event3'
libudev: udev_device_read_db: device 0x1975410 filled with db file data
libudev: udev_device_new_from_syspath: device 0x1975410 has devpath '/devices/pci0000:00/0000:00:14.2/sound/card0/input4/event4'
libudev: udev_device_read_db: device 0x1975410 filled with db file data
libudev: udev_device_new_from_syspath: device 0x1975410 has devpath '/devices/pci0000:00/0000:00:14.2/sound/card0/input5/event5'
libudev: udev_device_read_db: device 0x1975410 filled with db file data
libudev: udev_device_new_from_syspath: device 0x1975410 has devpath '/devices/pci0000:00/0000:00:14.2/sound/card0/input6/event6'
libudev: udev_device_read_db: device 0x1975410 filled with db file data
libudev: udev_device_new_from_syspath: device 0x1975410 has devpath '/devices/pci0000:00/0000:00:14.2/sound/card0/input7/event7'
libudev: udev_device_read_db: device 0x1975410 filled with db file data
libudev: udev_device_new_from_syspath: device 0x1975410 has devpath '/devices/pci0000:00/0000:00:14.2/sound/card0/input8/event8'
libudev: udev_device_read_db: device 0x1975410 filled with db file data
libudev: udev_device_new_from_syspath: device 0x1975410 has devpath '/devices/pci0000:00/0000:00:14.2/sound/card0/input9/event9'
libudev: udev_device_read_db: device 0x1975410 filled with db file data
libudev: udev_device_new_from_syspath: device 0x1975410 has devpath '/devices/LNXSYSTM:00/device:00/PNP0C0C:00/input/input0'
libudev: udev_device_new_from_syspath: device 0x1975410 has devpath '/devices/LNXSYSTM:00/LNXPWRBN:00/input/input1'
libudev: udev_device_new_from_syspath: device 0x1975410 has devpath '/devices/pci0000:00/0000:00:13.0/usb5/5-1/5-1:1.2/0003:046D:C52B.0003/input/input2'
libudev: udev_device_new_from_syspath: device 0x1975410 has devpath '/devices/pci0000:00/0000:00:12.0/usb4/4-5/4-5:1.2/0003:046D:C52B.0007/input/input3'
libudev: udev_device_new_from_syspath: device 0x1975410 has devpath '/devices/pci0000:00/0000:00:14.2/sound/card0/input4'
libudev: udev_device_new_from_syspath: device 0x1975410 has devpath '/devices/pci0000:00/0000:00:14.2/sound/card0/input5'
libudev: udev_device_new_from_syspath: device 0x1975410 has devpath '/devices/pci0000:00/0000:00:14.2/sound/card0/input6'
libudev: udev_device_new_from_syspath: device 0x1975410 has devpath '/devices/pci0000:00/0000:00:14.2/sound/card0/input7'
libudev: udev_device_new_from_syspath: device 0x1975410 has devpath '/devices/pci0000:00/0000:00:14.2/sound/card0/input8'
libudev: udev_device_new_from_syspath: device 0x1975410 has devpath '/devices/pci0000:00/0000:00:14.2/sound/card0/input9'
libudev: udev_device_new_from_syspath: device 0x1975410 has devpath '/devices/pci0000:00/0000:00:12.0/usb4/4-5/4-5:1.2/0003:046D:C52B.0007/input/input3/mouse0'
libudev: udev_device_read_db: device 0x1975410 filled with db file data
libudev: udev_device_new_from_syspath: device 0x1975410 has devpath '/devices/pci0000:00/0000:00:14.2/sound/card0/input10'
libudev: udev_device_new_from_syspath: device 0x1975410 has devpath '/devices/pci0000:00/0000:00:14.2/sound/card0/input11'
libudev: udev_device_new_from_syspath: device 0x1975410 has devpath '/devices/pci0000:00/0000:00:02.0/0000:01:00.1/sound/card3/input12'
libudev: udev_device_new_from_syspath: device 0x1975410 has devpath '/devices/pci0000:00/0000:00:02.0/0000:01:00.1/sound/card3/input13'
libudev: udev_device_new_from_syspath: device 0x1975410 has devpath '/devices/pci0000:00/0000:00:12.2/usb1/1-3/1-3.2/1-3.2:1.0/input/input14'
libudev: udev_device_new_from_syspath: device 0x1975410 has devpath '/devices/pci0000:00/0000:00:14.4/0000:05:06.0/rc/rc0/input15'
/sys/devices/pci0000:00/0000:00:12.2/usb1/1-3/1-3.2/1-3.2:1.0/input/input14/event14
/sys/devices/pci0000:00/0000:00:12.2/usb1/1-3/1-3.2/1-3.2:1.0/input/input14/js0
[lexa2@lx2linux Temp]$
[lexa2@lx2linux Temp]$ LD_PRELOAD=~/.local/share/Steam/ubuntu12_32/steam-runtime-debug_2013-09-05/amd64/lib/x86_64-linux-gnu/libudev.so.0.13.0 UDEV_LOG=6 ./udevtest
libudev: udev_device_new_from_syspath: device 0x8508b0 has devpath '/devices/pci0000:00/0000:00:12.2/usb1/1-3/1-3.2/1-3.2:1.0/input/input14/js0'
libudev: udev_device_read_db: no db file to read /dev/.udev/data/c13:0: No such file or directory
libudev: udev_device_new_from_syspath: device 0x8508b0 has devpath '/devices/virtual/input/mice'
libudev: udev_device_read_db: no db file to read /dev/.udev/data/c13:63: No such file or directory
libudev: udev_device_new_from_syspath: device 0x8508b0 has devpath '/devices/pci0000:00/0000:00:14.2/sound/card0/input10/event10'
libudev: udev_device_read_db: no db file to read /dev/.udev/data/c13:74: No such file or directory
libudev: udev_device_new_from_syspath: device 0x8508b0 has devpath '/devices/pci0000:00/0000:00:14.2/sound/card0/input11/event11'
libudev: udev_device_read_db: no db file to read /dev/.udev/data/c13:75: No such file or directory
libudev: udev_device_new_from_syspath: device 0x8508b0 has devpath '/devices/pci0000:00/0000:00:02.0/0000:01:00.1/sound/card3/input12/event12'
libudev: udev_device_read_db: no db file to read /dev/.udev/data/c13:76: No such file or directory
libudev: udev_device_new_from_syspath: device 0x8508b0 has devpath '/devices/pci0000:00/0000:00:02.0/0000:01:00.1/sound/card3/input13/event13'
libudev: udev_device_read_db: no db file to read /dev/.udev/data/c13:77: No such file or directory
libudev: udev_device_new_from_syspath: device 0x8508b0 has devpath '/devices/pci0000:00/0000:00:12.2/usb1/1-3/1-3.2/1-3.2:1.0/input/input14/event14'
libudev: udev_device_read_db: no db file to read /dev/.udev/data/c13:78: No such file or directory
libudev: udev_device_new_from_syspath: device 0x8508b0 has devpath '/devices/pci0000:00/0000:00:14.4/0000:05:06.0/rc/rc0/input15/event15'
libudev: udev_device_read_db: no db file to read /dev/.udev/data/c13:79: No such file or directory
libudev: udev_device_new_from_syspath: device 0x8508b0 has devpath '/devices/LNXSYSTM:00/device:00/PNP0C0C:00/input/input0/event0'
libudev: udev_device_read_db: no db file to read /dev/.udev/data/c13:64: No such file or directory
libudev: udev_device_new_from_syspath: device 0x8508b0 has devpath '/devices/LNXSYSTM:00/LNXPWRBN:00/input/input1/event1'
libudev: udev_device_read_db: no db file to read /dev/.udev/data/c13:65: No such file or directory
libudev: udev_device_new_from_syspath: device 0x8508b0 has devpath '/devices/pci0000:00/0000:00:13.0/usb5/5-1/5-1:1.2/0003:046D:C52B.0003/input/input2/event2'
libudev: udev_device_read_db: no db file to read /dev/.udev/data/c13:66: No such file or directory
libudev: udev_device_new_from_syspath: device 0x8508b0 has devpath '/devices/pci0000:00/0000:00:12.0/usb4/4-5/4-5:1.2/0003:046D:C52B.0007/input/input3/event3'
libudev: udev_device_read_db: no db file to read /dev/.udev/data/c13:67: No such file or directory
libudev: udev_device_new_from_syspath: device 0x8508b0 has devpath '/devices/pci0000:00/0000:00:14.2/sound/card0/input4/event4'
libudev: udev_device_read_db: no db file to read /dev/.udev/data/c13:68: No such file or directory
libudev: udev_device_new_from_syspath: device 0x8508b0 has devpath '/devices/pci0000:00/0000:00:14.2/sound/card0/input5/event5'
libudev: udev_device_read_db: no db file to read /dev/.udev/data/c13:69: No such file or directory
libudev: udev_device_new_from_syspath: device 0x8508b0 has devpath '/devices/pci0000:00/0000:00:14.2/sound/card0/input6/event6'
libudev: udev_device_read_db: no db file to read /dev/.udev/data/c13:70: No such file or directory
libudev: udev_device_new_from_syspath: device 0x8508b0 has devpath '/devices/pci0000:00/0000:00:14.2/sound/card0/input7/event7'
libudev: udev_device_read_db: no db file to read /dev/.udev/data/c13:71: No such file or directory
libudev: udev_device_new_from_syspath: device 0x8508b0 has devpath '/devices/pci0000:00/0000:00:14.2/sound/card0/input8/event8'
libudev: udev_device_read_db: no db file to read /dev/.udev/data/c13:72: No such file or directory
libudev: udev_device_new_from_syspath: device 0x8508b0 has devpath '/devices/pci0000:00/0000:00:14.2/sound/card0/input9/event9'
libudev: udev_device_read_db: no db file to read /dev/.udev/data/c13:73: No such file or directory
libudev: udev_device_new_from_syspath: device 0x8508b0 has devpath '/devices/LNXSYSTM:00/device:00/PNP0C0C:00/input/input0'
libudev: udev_device_read_db: no db file to read /dev/.udev/data/+input:input0: No such file or directory
libudev: udev_device_new_from_syspath: device 0x8508b0 has devpath '/devices/LNXSYSTM:00/LNXPWRBN:00/input/input1'
libudev: udev_device_read_db: no db file to read /dev/.udev/data/+input:input1: No such file or directory
libudev: udev_device_new_from_syspath: device 0x8508b0 has devpath '/devices/pci0000:00/0000:00:13.0/usb5/5-1/5-1:1.2/0003:046D:C52B.0003/input/input2'
libudev: udev_device_read_db: no db file to read /dev/.udev/data/+input:input2: No such file or directory
libudev: udev_device_new_from_syspath: device 0x8508b0 has devpath '/devices/pci0000:00/0000:00:12.0/usb4/4-5/4-5:1.2/0003:046D:C52B.0007/input/input3'
libudev: udev_device_read_db: no db file to read /dev/.udev/data/+input:input3: No such file or directory
libudev: udev_device_new_from_syspath: device 0x8508b0 has devpath '/devices/pci0000:00/0000:00:14.2/sound/card0/input4'
libudev: udev_device_read_db: no db file to read /dev/.udev/data/+input:input4: No such file or directory
libudev: udev_device_new_from_syspath: device 0x8508b0 has devpath '/devices/pci0000:00/0000:00:14.2/sound/card0/input5'
libudev: udev_device_read_db: no db file to read /dev/.udev/data/+input:input5: No such file or directory
libudev: udev_device_new_from_syspath: device 0x8508b0 has devpath '/devices/pci0000:00/0000:00:14.2/sound/card0/input6'
libudev: udev_device_read_db: no db file to read /dev/.udev/data/+input:input6: No such file or directory
libudev: udev_device_new_from_syspath: device 0x8508b0 has devpath '/devices/pci0000:00/0000:00:14.2/sound/card0/input7'
libudev: udev_device_read_db: no db file to read /dev/.udev/data/+input:input7: No such file or directory
libudev: udev_device_new_from_syspath: device 0x8508b0 has devpath '/devices/pci0000:00/0000:00:14.2/sound/card0/input8'
libudev: udev_device_read_db: no db file to read /dev/.udev/data/+input:input8: No such file or directory
libudev: udev_device_new_from_syspath: device 0x8508b0 has devpath '/devices/pci0000:00/0000:00:14.2/sound/card0/input9'
libudev: udev_device_read_db: no db file to read /dev/.udev/data/+input:input9: No such file or directory
libudev: udev_device_new_from_syspath: device 0x8508b0 has devpath '/devices/pci0000:00/0000:00:12.0/usb4/4-5/4-5:1.2/0003:046D:C52B.0007/input/input3/mouse0'
libudev: udev_device_read_db: no db file to read /dev/.udev/data/c13:32: No such file or directory
libudev: udev_device_new_from_syspath: device 0x8508b0 has devpath '/devices/pci0000:00/0000:00:14.2/sound/card0/input10'
libudev: udev_device_read_db: no db file to read /dev/.udev/data/+input:input10: No such file or directory
libudev: udev_device_new_from_syspath: device 0x8508b0 has devpath '/devices/pci0000:00/0000:00:14.2/sound/card0/input11'
libudev: udev_device_read_db: no db file to read /dev/.udev/data/+input:input11: No such file or directory
libudev: udev_device_new_from_syspath: device 0x8508b0 has devpath '/devices/pci0000:00/0000:00:02.0/0000:01:00.1/sound/card3/input12'
libudev: udev_device_read_db: no db file to read /dev/.udev/data/+input:input12: No such file or directory
libudev: udev_device_new_from_syspath: device 0x8508b0 has devpath '/devices/pci0000:00/0000:00:02.0/0000:01:00.1/sound/card3/input13'
libudev: udev_device_read_db: no db file to read /dev/.udev/data/+input:input13: No such file or directory
libudev: udev_device_new_from_syspath: device 0x8508b0 has devpath '/devices/pci0000:00/0000:00:12.2/usb1/1-3/1-3.2/1-3.2:1.0/input/input14'
libudev: udev_device_read_db: no db file to read /dev/.udev/data/+input:input14: No such file or directory
libudev: udev_device_new_from_syspath: device 0x8508b0 has devpath '/devices/pci0000:00/0000:00:14.4/0000:05:06.0/rc/rc0/input15'
libudev: udev_device_read_db: no db file to read /dev/.udev/data/+input:input15: No such file or directory

Problem is in lines like "no db file to read /dev/.udev/data/c13:78" - udev on my system uses another naming convention for properties files in database and libudev from sream-runtime simply cannot found required database files and behaves like if there are no extra properties assosiated with device files except what could be read from sysfs.

One could use SDL_JOYSTICK_DEVICE environment variable as a workaround for this case. Gamepad hotplug won't work for this case and it is a bit tricky for "ordinary user" to determine which device file to supply in SDL_JOYSTICK_DEVICE due to input devices names usually not being persistent. Latter problem could be workaround using helper tool like this:

#include <stdio.h>
#include <libudev.h>
#include <sys/time.h>
#include <sys/types.h>

static struct udev *udev = NULL;

int
main(void)
{
    struct udev_enumerate *enumerate = NULL;
    struct udev_list_entry *devs = NULL;
    struct udev_list_entry *item = NULL;

    udev = udev_new();
    if (udev == NULL) {
        printf("udev_new() failed\n");
        return -1;
    }

    enumerate = udev_enumerate_new(udev);
    if (enumerate == NULL) {
        printf("udev_enumerate_new() failed\n");
        return -2;
    }

    udev_enumerate_add_match_subsystem(enumerate, "input");
    udev_enumerate_add_match_property(enumerate, "ID_INPUT_JOYSTICK", "1");
    udev_enumerate_scan_devices(enumerate);
    devs = udev_enumerate_get_list_entry(enumerate);
    for (item = devs; item; item = udev_list_entry_get_next(item)) {
        const char *path = udev_list_entry_get_name(item);
        struct udev_device *dev = udev_device_new_from_syspath(udev, path);
        printf("%s:", udev_device_get_devnode(dev));
        udev_device_unref(dev);
    }

    udev_enumerate_unref(enumerate);
    printf("\n");

    return 0;
}

One should place this code into file named say "udevjoysticks.c" and use it like this (assuming he/she had added a udev rule mentioned earlier into his/her udev ruleset):

[lexa2@lx2linux Temp]$ gcc -O2 ./udevjoysticks.c -o./udevjoysticks -ludev
[lexa2@lx2linux Temp]$ strip ./udevjoysticks
[lexa2@lx2linux Temp]$ ./udevjoysticks
/dev/input/event14:/dev/input/js0:
[lexa2@lx2linux Temp]$ sudo cp -a ./udevjoysticks /usr/local/bin/udevjoysticks
[lexa2@lx2linux Temp]$ SDL_JOYSTICK_DEVICE=$(udevjoysticks) steam
Sslouken 2013-09-28 github

Nice research, thanks!

Is it possible to patch libudev in a way that would be compatible with both systems?
You can run a debug version of the Steam Linux Runtime by launching Steam like this: STEAM_RUNTIME=debug steam
You can then go to /tmp/source and modify and rebuild the libraries to you heart's content, remembering to copy them back into Steam's debug runtime directory in ~/.steam/steam/ubuntu12_32.

Llexa2 2013-09-29 github

Yep, obviously it is possible to patch it with fallback udevdb files naming scheme. But the problem IMO is more generic. What we have here is an incompatibility between udev-147 and udev-175. Libudev is expected to match system udev version as it relies on internal interfaces and assumptions (like file naming conventions or DB encoding scheme) to operate properly. We could fix this exact incompatibility by introducing fallback path but what about more recent udev versions? For example, in udev-176 database is required to be under /run/udev instead of /dev/.udev. It would be a maintenance nightmare to patch steam-runtime so it supports each and every udev out there in the wild. If only there were a more or less standardized generic interface for fetching data from hardware database. Unfortunately it is not the case since the moment HAL had became deprecated :-(.

IMO a more viable approach is to introduce another environment variable in SDL2 that could force it into using fallback joystick detection path and not relying on libudev. Something like "export SDL_JOYSTICK_USE_UDEV=0".

As for libudev, it should be in theory possible not to ship it as all with steam-runtime and use system lib instead. Looking at http://upstream-tracker.org/versions/libudev.html it could be noted that ABI was stable since version 147 - it is exactly the version that is shipped in RHEL6 and derivatives.

From libudev changelog (http://upstream-tracker.org/changelogs/libudev/181/changelog.html) two major milestones could be spotted:

  1. udev 148 introduced ID_INPUT_XXX and deprecated ID_CLASS for input devices. If SDL2 wants to be a_bit_more_compatible with RHEL6 it should try to enumerate devices having ID_INPUT_JOYSTICK=1 and then fallback to ID_CLASS="joystick" in case no devices had been found and lastly maybe fallback to direct /dev/input/event?? probing if still no joysticks detected.

  2. udev 167 is a moment when database format had changed. Steam should either ship two libudev.so versions (say 166 and 175) and detect at startup which to use depending on the system libudev version, or should not ship libudev at all and rely on libudev ABI to remain more or less stable. And obviously linux steam binaries (both client and games) are expected to be linked with libudev 147 - a oldest version for which ABI seems to be stable.

P.S. Executing "STEAM_RUNTIME=debug" steam does not force steam into using libs only from debug runtime. At line 640 of ~/.local/share/Steam/steam.sh library search path is prepended with $STEAMROOT/$PLATFORM. As $PLATFORM dir contains non-debug versions of libSDL2-2.0.so.0 one would end up with non-debug lib linked in by ldd despite using "STEAM_RUNTIME=debug". I've been forced into creating a copy of steam.sh and editing it up at line 640 swapping platform and steam runtime references in library search path.

Llexa2 2013-09-29 github

A quick fix and reminder not to post when too sleepy: second "udev milestone" version is 165 instead of 167.
I've done a quick check and it seems that steamclient.so uses some functionality which had been introduced in libudev165 and steam refuses to start up with an assertion:

/home/buildbot/buildslave_steam/steam_rel_client_ubuntu12_linux/build/src/steamUI/../common/steam/client_api.cpp (294) : Assertion Failed: ClientAPI_InitGlobalInstance: InternalAPI_Init_Internal failed, most likely because you are missing a 32-bit dependency of steamclient.so (the Steam client is a 32-bit app).

In case I try to use libudev.so.0.9.3 or earlier. Then again it starts up OK with libudev.so.0.10.0+.

Llexa2 2013-09-29 github

Implemented a drop-in workaround solution (more like a "dirty hack") for people on RHEL6/CentOS6 using linux version of Steam client with help of steam-debian wrapper and/or having their glibc updated to 2.15+.

Save the contents of the section below as a "/lib/udev/sdl2_joystick_compat"

#!/bin/bash

for i in /dev/.udev/db/input:event* ; do
    [ ! -f $i ] && continue
    z=$(cat $i | grep 'S:char' | sed -e 's,S:char/,,')
    mkdir -p /dev/.udev/data 2>/dev/null >/dev/null
    ln -sf $i /dev/.udev/data/c${z}
done

Make it executable:

# sudo chmod a+x /lib/udev/sdl2_joystick_compat

Place the following into "/etc/udev/rules.d/99-sdl2-joystick-compat.rules":

SUBSYSTEM=="input", ENV{ID_CLASS}=="joystick", ENV{ID_INPUT_JOYSTICK}="1", RUN+="/lib/udev/sdl2_joystick_compat"

With these hacks in place SDL2 (and steam as a consequence) seems to be able to find joysticks that had been connected to the workstation at the moment of the program start up. Hotplug doesn't work (as expected) but it is a minor problem which can't be easily fixed AFAICS.

WARNING: Do not use this hack in case you have udev 165+ installed as it will break your udev database. Breakage is not fatal and would be auto-fixed as soon as you remove the hack and reboot your system.
NOTE: I'm not sure if this would work correctly with udev starting from 148 and up to 164 as ID_CLASS match used in rule file is deprecated starting from udev 148. In case of a trouble one could try using the following rule file instead:

SUBSYSTEM=="input", ENV{ID_INPUT_JOYSTICK}=="1", RUN+="/lib/udev/sdl2_joystick_compat"
Ggabomdq 2013-11-12 github

I'm not a Valve employee but I've been working on the udev code for a while, just found this ticket while googling for a separate issue which needed the user to force ENV{ID_INPUT_JOYSTICK}="1" :)

Anyway, how about we add a hint to SDL (SDL_PATH_UDEV or whatever) that lets you set the libudev.so path, would that work? If you think so, feel free to file a ticket at SDL's Bugzilla.

Llexa2 2013-11-14 github

Having SDL dlopening system libudev and using exports from there instead of exports provided by steam runtime shipped version of libudev might help. We could hit a problem having two libs dynamically linked into the address space of the same process and having the same-named symbols exported but I think it is something that SDL could took care of. I would consider posting a new feature-request into SDL's Bugzilla in a near future (hope I would find some spare time to do it). Thanks for sharing your idea, it's really brilliant.

Mmklinik 2014-07-14 github

Running debian testing, I had a similar problem: some games recognized my gamepad, some didn't. Big picture mode told me: "no gamepads". Turns out that it was a permissions problem. Udev creates two devices for a gamepad: jsX and eventX where X is some number. The js device node had world-read permissions while the event one had very restricted permissions. Steam tries to use event, which fails. I wrote a udev rule that sets the permission of the event device file to world-readable, now it works like a snap.

My solution is derived from this discussion: http://steamcommunity.com/app/221410/discussions/0/864959809809029907/

Here is my udev rule:
$ cat /etc/udev/rules.d/99-joystick.rules
SUBSYSTEMS=="usb", ATTRS{idVendor}=="0583", ATTRS{idProduct}=="205f", MODE="0666", OWNER="mkl"

Hope this helps,
Markus

Fforesto 2014-07-31 github

Alexey, thank you so much for the deep investigation and proposed solutions! I spent far too much time trying to figure out why Steam was failing to see my gamepad on Ubuntu 14.04 (trusty), and your detailed explanation helped immensely.

As a temporary workaround, I added some code to the bash script that I use to launch steam. It scans the files in /dev/input for the ID_INPUT_JOYSTICK=1 property and puts those that match into the SDL_JOYSTICK_DEVICE environment variable. I'll have to fix the permissions on those /dev/input files as well, since udev doesn't seem to be doing it properly. With all that in place, I can use my gamepad while I wait for this bug to be fixed.

# Finds joystick devices so we can coerce Steam's old SDL library into using them
function enum_joysticks {
  local joyprop=ID_INPUT_JOYSTICK=1
  for f in /dev/input/*; do
    if [ ! -c $f ]; then
      continue
    elif udevadm info --query=property --name=$f | grep --quiet $joyprop; then
      echo $f
    fi
  done
}

# Uses the first arg as a separator to join the remaining args
function join {
  local IFS="$1"
  shift
  echo "$*"
}

env SDL_JOYSTICK_DEVICE=$(join : $(enum_joysticks)) steam $*
Fforesto 2014-07-31 github

@gabomdq, @lexa2:
Would the SDL_DYNAMIC_API environment variable introduced in SDL 2.0.2 be useful here?
https://plus.google.com/+RyanGordon/posts/TB8UfnDYu4U
http://www.phoronix.com/scan.php?page=news_item&px=MTU2MzQ

Is Steam using a version of libsdl that supports that feature?

Kkisak-valve maintainer 2017-04-11 github

Hello, is this still an issue since the 2017-01-19 steam client update?

Ttokenrove 2017-04-13 github

This seems to still be a problem for me with a client that claims to be from March 22nd.

LLastique 2017-06-13 github

I have the same problem on Kubuntu 17.04 with Dualshock 4 (PS4 controller) connected via Bluetooth. Setting rw permissions on /dev/input/event* file and/or setting SDL_JOYSTICK_DEVICE env variable does not help. The event device has ID_INPUT_JOYSTICK=1 property.

LLastique 2017-06-15 github

I have some progress. I created my controller config with the controllermap program from SDL2 sources and set it in /etc/environment:

# PlayStation 4 Wireless controller through Bluetooth
SDL_GAMECONTROLLERCONFIG="050000004c050000c405000000810000,Wireless Controller,platform:Linux,x:b3,a:b0,b:b1,y:b2,back:b8,guide:b10,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4,"

After that the controller started working in games, but the Steam client still says "No controllers detected" in the controller settings.

BTW, the controller works out of the box in GOG games.

RRuedii 2018-12-17 github

I have the same issue with my Wii gamepads hooked up through a USB Bluetooth adapter and the XWiiMote stack.

They work on Non-Steam games but Steam can't detect them and thus can't use them.

The DevFS directory format changed a while back, and the legacy links from /dev/js? to /dev/input/js? were recently removed. This may be the issue with finding all generic input devices.

The places that Steam should look for controllers under normal expected behavior:

  1. Match by USB or PCI device ID
  2. Match by USB device type number
  3. Any additional devices that match by special supported Steam Usermode drivers.
  4. /dev/input/js*
  5. /dev/js*
  6. /dev/input/hid* if detected to have attributes of a gaming input device.
  7. /dev/hid* if
  8. XOrg Misc. HID devices with analog sticks and/or button pads excluding keyboards and keypads that are alphanumeric or numeric in nature.

Duplicate devices should be identified and the user should be given a choice of which driver to use.

RRuedii 2018-12-22 github

As a note, it seems to have particular issues with bluetooth devices.

Maybe listing bluetooth HID devices might be good as well to look for specific devices.
However, a fallback of /dev/input/js* and /dev/input/event* should catch these.

Yyajo 2019-12-29 github

I'm having this same problem. I find it strange because for instance when I use Gnome Games I can detect and configure the gamepad just fine.

When I boot steam from the terminal, among all the output, there's always this:

Local Device Found
  type: 044f d007
  path: sdl://0
  serial_number:  - 0
  Manufacturer: 
  Product:      Thrustmaster T Mini Wireless
  Release:      100
  Interface:    -1

So, it seems like SDL found my gamepad. However, it doesn't work on Big Picture Mode or games (only tested in Overcooked).

I followed https://steamcommunity.com/app/221410/discussions/0/558748653738497361/ to emulate it as an Xbox gamepad (adapted to my T-mini gamepad), and this way it works both in BPM and in Overcooked.