Skip to content

Latest commit

 

History

History
63 lines (42 loc) · 3.31 KB

README.adoc

File metadata and controls

63 lines (42 loc) · 3.31 KB

What’s this?

Here we implement virtual devices using the low level uhid

Why can’t we use udev?

To answer this question we need to dive deeper into how the DualSense controller works, bear with me..

The PS4 and PS5 controllers also include a Gyroscope, Accelerometer and a Touchpad. The DualSense controller also includes a microphone and a speaker. The open source driver hid-playstation exposes these features as 3 separate input devices:

/dev/input/event20:	Sony Interactive Entertainment Wireless Controller
/dev/input/event21:	Sony Interactive Entertainment Wireless Controller Motion Sensors
/dev/input/event22:	Sony Interactive Entertainment Wireless Controller Touchpad

Ideally we should be able to use udev to create these devices independently, unfortunately the issue is in linking these 3 devices together.

First off, SDL2 assumes that every /dev/input/event* device might be a joypad, so it opens them all to check if they are based on some heuristics. Normally, the motion sensor device that you create with udev will be opened by SDL2 and it will be recognized as a joypad. To get around this you can hardcode the device name to end with one of the SDL_ShouldIgnoreGamepad hardcoded strings. This will get around the first hurdle and actually recognize the udev created motion sensor as an actual sensor.

The main issue seems to be in linking these 3 devices together: the way SDL2 does this is to match the uniq identifier (EVIOCGUNIQ in this method) between what is recognised as sensor and what is recognised as joypad. Unfortunately, there’s no way to set the uniq for an uinput device; there’s a proposal to add this to the Linux kernel but as of March 2024 this has still not being merged. So what happens in practice is that SDL ends up discarding that sensor and just using the joypad instead.

How UHID solves this?

UHID allows us to completely replicate the DualSense controller at a lower level. The device that we’ll create via UHID will be picked up by hid-playstation just like a USB connected DualSense controller would be, which in turn will create the /dev/input/event devices and downstream applications will see the 3 devices as they should be.

What are the requirements to use UHID?

You need additional permission in order to access /dev/uhid (normally exposed as root only).

First we’ll add our user to the input group:

sudo usermod -a -G input $USER

Then we add an udev rule to allow access to /dev/uhid:

echo 'KERNEL=="uhid", GROUP="input", MODE="0660"' | sudo tee /etc/udev/rules.d/99-uhid.rules

Finally, we have to make sure that the uhid kernel module is loaded at boot:

echo "uhid" | sudo tee /etc/modules-load.d/uhid.conf