Menu

emulate joystick with uinput?

2020-09-11
2020-09-12
  • Justin R. Miller

    I'm trying to create a virtual joystick on Linux using the uinput kernel module and the Python bindings for libuinput.

    I've succeeded, in a few lines of code, of making a joystick that is seen by all of the major joystick calibration and testing tools (qjoypad, jcal, jstest-gtk, etc.).

    The same joystick, if it exists before PC-BASIC is started, is unable to trigger strig() events. As a test, I've made a BASIC program which responds to button presses on strig()'s 0, 2, 4, and 6 button values. I can use a real joystick as either /dev/input/js0 or js1 and it works fine, but the virtual joystick doesn't work in either slot.

    I'm using the SDL2 interface and have dug into that library's code a bit and can't figure out why this won't work. Does anyone have any pointers as to what I could do, or alternatively, how I could trigger BASIC strig() by other non-hardware means?

     
    • Justin R. Miller

      On Sep 11, 2020, at 1:45 PM, Justin R. Miller incanus@users.sourceforge.net wrote:

      I'm using the SDL2 interface and have dug into that library's code a bit and can't figure out why this won't work. Does anyone have any pointers as to what I could do, or alternatively, how I could trigger BASIC strig() by other non-hardware means?

      I just tested out the (deprecated) Pygame interface and that does work properly for both USB and virtual joysticks. So it does seem to be an SDL2 issue. Any pointers gladly taken, and my question still stands as to a suggestion for another approach to strig() use.

      JM

       
  • Rob Hagemans

    Rob Hagemans - 2020-09-12

    It seems indeed there's something about SDL2's handling of virtual joysticks relative to SDL1.2 (on which this version of Pygame is based).

    Could you share your Python code perhaps? I can have a look if I can reproduce the issue.

     

    Last edit: Rob Hagemans 2020-09-12
  • Rob Hagemans

    Rob Hagemans - 2020-09-12

    Here's some discussion of changes in Linux joystick handling between SDL1.2 and SDL2: https://forums.libsdl.org/viewtopic.php?p=40841

    Seems SDL1.2 used /dev/input/js* but this has been changed to dev/input/event* which creates issues for some users.

    Another thing to do is capture the debug logs with --debug --logfile=my_logfile.txt and see if SDL2 makes any noises about the joysticks.

     
    • Justin R. Miller

      On Sep 11, 2020, at 10:25 PM, Rob Hagemans robhagemans@users.sourceforge.net wrote:

      Here's some discussion of changes in Linux joystick handling between SDL1.2 and SDL2: https://forums.libsdl.org/viewtopic.php?p=40841

      Seems SDL1.2 used /dev/input/js but this has been changed to dev/input/event which creates issues for some users.

      Another thing to do is capture the debug logs with --debug --logfile=my_logfile.txt and see if SDL2 makes any noises about the joysticks.

      Correct, the virtual joystick works in Pygame i.e. SDL 1.2.

      I was able to figure this out. It turns out that you can use udev on Linux to set an environment variable for certain classes of input devices to ensure that SDL2 sees them as actual joysticks. These three posts fit together to create a solution:

      https://discourse.libsdl.org/t/uinput-controller/27972
      https://github.com/dvdhrm/xwiimote/issues/51#issuecomment-137929076
      https://github.com/denilsonsa/udev-joystick-blacklist/blob/master/51-these-are-not-joysticks-rm.rules

      Using a rule like the following solves the problem for my setup and makes virtual and non-virtual joysticks work (the latter of which this environment variable doesn’t hurt):

      SUBSYSTEM=="input", KERNEL=="js[0-9]*", ENV{ID_INPUT_JOYSTICK}="1"

      Then, Python code such as this (external to PC-BASIC, and somehow long-running) will create a virtual joystick with two buttons that will properly trigger STRIG():

      import uinput

      d = uinput.Device([uinput.BTN_A, uinput.BTN_B])

      d.emit_click(uinput.BTN_A)

      Whether this device exists and/or a physical joystick is plugged in before PC-BASIC starts will determine which is the first and which is the second joystick (i.e. STRIG()’s 0/2 or 4/6 arguments).

      Thanks for the reply and hope this is useful to someone else out there.

      JM

       
Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.