atar-axis / xpadneo

Advanced Linux Driver for Xbox One Wireless Controller (shipped with Xbox One S)
https://atar-axis.github.io/xpadneo/
GNU General Public License v3.0
1.87k stars 110 forks source link

Prevent axis fixup and get xbox elite 2 layout in steam #458

Open martindmtrv opened 4 months ago

martindmtrv commented 4 months ago

I've been experimenting with another controller mocking xbox elite 2 so I can get paddles working with steam input.

I noticed this:

https://github.com/atar-axis/xpadneo/blob/bce97bd057ce6fcc30bc53a9deb6c0728d31dd1d/hid-xpadneo/src/hid-xpadneo.c#L1149

As I understand, we are setting the vendor and product code to one that is unused by SDL so we don't get unexpected remaps from other layers.

I did some digging and found that the reason the remaps happen is due to the fact that for some controllers (like the xbox elite 2 controller) SDL actually reads directly from hidraw.

This was a breaking change when it was introduced, but it can be disabled entirely with an environment variable

https://forum.endeavouros.com/t/sdl2-breakage-changes/10551

By setting SDL_JOYSTICK_HIDAPI=0 in /etc/environment we prevent SDL from reading hidraw, and it will get the mapping we set here, even if we mock a xbox elite 2 controller.

I don't know if there are other layers that also would interfere and would also need this kind of workaround. By setting this env variable and using a kernel module I am working on for vader 3 pro I am able to get xbox elite 2 layout in steam and remap the paddles

kakra commented 4 months ago

SDL2 with HID API disabled in latest versions currently properly detects the paddles of xpadneo. So, if we mock Vader 3 into the driver, it should work for it the same way. But it has a completely different HID descriptor, so we'd need to modify the descriptor to match the button bit positions of xpadneo, and patch the raw HID packets to expose the expected format.

@ahungry instead modified the evdev description which I cannot accept into the driver currently. Otherwise, I'm open for integrating Vader 3 into xpadneo. Actually, I'm looking into accepting some Switch-compatible controllers into xpadneo (which are currently only supported via XINPUT mode) because we have access to more buttons and functions in that mode.

As I understand, we are setting the vendor and product code to one that is unused by SDL so we don't get unexpected remaps from other layers.

Yes, exactly. I had to do that multiple times because people kept submitted controllerdb mappings of the new ID to SDL2 although no mapping was needed - like it would be needed for SDL to even support a controller. Now, we seem to use the same ID the virtual Steam controller is using via Steam Input: that VID/PID is hard-coded in wine to handle it differently from native controllers and it works.

And because I had to do it multiple times, I am so picky about accepting changes into the kernel which mess with the evdev mapping. We have no more options left to avoid wrong mappings from other layers.

In latest SDL2, it looks like all the bogus Xbox controllerdb mappings have been removed, instead a new heuristic was introduced that detects proper mappings from different drivers correctly - that is, as long as hidraw is not used. In hidraw, SDL2 assumes a specific HID report format without even looking if the expected format matches the HID descriptor. So SDL_JOYSTICK_HIDAPI=0 is still needed, or you remove permissions from the hidraw device (which our udev rules do but it can be overwritten by OpenRGB and the likes).

Usually, running SDL2 without HID API should be completely fine except you need functions not provided by the kernel API, i.e. dedicated trigger rumble is not yet supported. xpadneo synthesizes that currently, it's not native trigger rumble. But if you use such functions and need HID API, you should only use native kernel drivers.

https://forum.endeavouros.com/t/sdl2-breakage-changes/10551

This quote is actually from our documentation. ;-) But it has since been removed because we deployed the udev rules for revoking hidraw permissions. It's still in the older releases.

I finally removed it with upcoming SDL2 paddle support:

kakra commented 4 months ago

I'll add information about SDL_JOYSTICK_HIDAPI=0 so it can be more easily discovered.