Uinput controller

What exactly are the criteria for an evdev device to be recognised as a controller by SDL2?

The following code creates a device that shows up with evtest but not with sdl2-jstest, gamepad-tool, or (the end goal) Steam:

import libevdev
import time
from libevdev import InputEvent
from libevdev import InputAbsInfo

a = InputAbsInfo()
d = libevdev.Device()
d.enable(libevdev.EV_ABS.ABS_X, a)
d.enable(libevdev.EV_ABS.ABS_Y, a)
d.name = 'python test device'
d.enable(libevdev.EV_KEY.KEY_1)
uinput = d.create_uinput_device()

print('new device at {}'.format(uinput.devnode))

while True:
    events = [
        InputEvent(libevdev.EV_KEY.KEY_1, 1),
        InputEvent(libevdev.EV_KEY.KEY_1, 0),
        InputEvent(libevdev.EV_SYN.SYN_REPORT, 0),
    ]
    uinput.send_events(events)
    time.sleep(1)

The function IsJoystick in src/joystick/linux/SDL_joystick.c may be crucial. I can see that that wants key events enabled, plus ABS_X and ABS_Y, but I can’t quite work out what else it’s checking.

(My goal is to get SDL2 working with a web-based mobile controller I’ve developed. I’m currently using xboxdrv as a bridge, but I’m pretty sure that shouldn’t be necessary.)

You need to set the class of the device to “joystick”. SDL checks that in joystick_udev_callback(): https://hg.libsdl.org/SDL/file/e4ed298b49ff/src/joystick/linux/SDL_sysjoystick.c#l229

Thanks! Adding a udev rule to set ENV{ID_INPUT_JOYSTICK}="1" did the trick.

Now, ideally, I just need to find some clean way to set the class programmatically for the devices I create.