Advertisement

Virtual controller (Linux)

Started by April 28, 2020 06:17 PM
8 comments, last by Bregma 4 years, 7 months ago

(Unsure if this is the right forum, but none of them seem ideal, and you guys seem as likely to know about this stuff as anyone)

So my friend and I have been working on a local co-op game designed for a large number of players, with a bespoke web-based gamepad, to be used from a smartphone. Having built a simple mock-up gamepad, I thought I'd take a slight detour into trying to use it as a general-purpose controller (even in its current form, it could be great for simple ‘party’ games that can be played with just a few buttons).

So I have the phone sending data to a Linux desktop server, which sends events with uinput for each button press. Easy enough. But it seems that I'll need to do more than this to have existing games actually recognise the virtual device. After a few hours of research, I can't see that there is any kind of universal approach to do this.

So how does Steam, for example, determine that a particular device should be treated as a gamepad? I need to find a way to convince Steam (and third-party games) to see my virtual device as if it were an ordinary physical controller.

There are APIs for that built into the Unix core and some are driver level in the Linux Kernel. Windows for example offers two options, XInput as Microsoft's own gaming solution and Rawinput/ HID that uses drive rlevel code and the USB standard to detect devices. Anyways, as there isn't any XInput I'm aware of on Linux, your best bet would also be to utilize the HID capability of the Kernel.

Every USB plugable device, like a Gamepad, makes use of the USB standard and so offers certain IDs (Usage Pages) that identify the device type (1 and 2 are for Keyboard and Mouse, 4 is a Gamepad)

Advertisement

For Windows, I used the XInput API , no problems even for a novice programmer. What do you need the API for in Linux?

None

Just to reiterate, I'm trying to create a virtual input device that will be recognised as a controller by most games. I've made some minor changes to the OP to clarify this.

I've had some success on Linux by using xboxdrv to remap the evdev events. But this is a bit of an ugly solution. I may want to reimplement the relevant parts of xboxdrv instead.

@Shaarigan What APIs are you referring to? There's the xpad driver, but it's unclear to me right now whether that can be harnessed. I would really hope that what I want is possible without using something as low-level as raw HID input, which seems like it's designed for physical devices.

@ozonsphere What functions did you use to achieve this? The documentation for XInput seems to be aimed at consumers, rather than producers, of input events.

Advertisement

I think on Linux UHID is what you want to feed input into the kernel from user space.

https://www.kernel.org/doc/Documentation/hid/uhid.txt

george.fst said:
I would really hope that what I want is possible without using something as low-level as raw HID input

I guess to have most games recognize your virtual controller, you don't have any choice except going straight to the bottom of everything and work on a kernel basis. As I said, you don't have much choice in your input API wether on Linux nor Windows.

Input comes from the deep dark of the OS, either via OS messages which don't support HID devices or you have to utilize the USB driver/ a library abstracting this for you, to do that.

Now if you want to have input also generated from your mobile App, this is getting even more tricky because you have to feed the input into those channels used by the games you are targeting and this is unfortunately either OS messages for mouse and keyboard and/or HID/driver-level code for exotic devices like gamepads, joysticks and steering-wheels. You can't force an application to receive input via another channel except you change the code

You're using the Linux uinput API for button/valuator input, and that's definitely the right thing to do.

Pretty much everything interesting to do with a GUI on a Linux system is going to rely on the display server for input and output. That means any game is going to be an X11 or Wayland client to get input. Input for the X11 or Wayland servers is performed through libinput, which also provides an interface to the udev system. Between the two systems you can get all the identifying and meta information you need.

Unfortunately, that sometimes means you need to know more about the device than you can get from the device data. Like, for example, button 5 on a typical mouse is the side-click on the scrollwheel.

If you're at the level where uinput makes sense, playing with libinput and udev should give you the remaining pieces of the puzzle.

Stephen M. Webb
Professional Free Software Developer

This topic is closed to new replies.

Advertisement