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
2.01k stars 113 forks source link

Changing the sensitivity curve of controller sticks #129

Open moll opened 5 years ago

moll commented 5 years ago

Hey,

First, thanks for the high quality driver!

Ever since I started playing Rocket League, I've been longing to tweak the sensitivity curve on the controller sticks. The default, linear, is a tad too sensitive for my thumbs and makes it hard to do tiny adjustments. What method of going about this would you, @atar-axis, suggest? Should I go the kernel module route and add a config parameter to Xpadneo? Should I write a loadable library to intercept controller access of a game and transform stick values there? While I can code, I'm not yet familiar how game pads are handled to know which option would be simpler to implement and more convenient to later use per game. Any hints or starting points you could suggest would be appreciated.

Thanks in advance!

PS. I know Steam specifically has a layer to adjust sensitivities, but so far that seems to break my X Box Controller entirely in-game, not to mention the rather poor usability and lag of their configuration UI. I'd prefer a more general solution, too, that one could use with non-Steam games.

atar-axis commented 5 years ago

Hum, I think I would start with a config parameter - just look at those which are already there :)

atar-axis commented 5 years ago

Any news here?

kakra commented 4 years ago

This is difficult to implement: I was thinking about using a gamma adjustment for this but apparently it is not allowed to use floating point math in the kernel and I found no easy way to do this with integer math or with lookup tables that are not huge. We should defer that until after v0.8 landed because that is planned to have a feature to change axis shifting, and a curve adjustment would be somewhat interfering with that code.

moll commented 4 years ago

Hey again! Unfortunately I never did manage to properly implement this, and have since stopped playing Rocket League due to them dropping Linux support. I did, however, do a little proof of concept with a simple square curve (that is, x^2 where x is the stick's value from -1 to 1) by using integer math.

Somewhere around the line 1111 I threw in the following.

value -= 32768;

if (usg_code == ABS_X || usg_code == ABS_Y) {
    value = (value < 0 ? -1 : 1) * (value * value) / 32768;
}

I actually found this particular curve to be insufficient for what I was after. I then started to think it'd probably require a lot of playtesting and having it hardcoded makes it rather inconvenient to change. Tweaking the entire formula at runtime, however, would require a formula parser in the driver and what-not, at which point it seemed too complicated.

Maybe the better solution long term would be to write a hookable DLL in a higher language and use that in user-space instead of shoving it in the Xpadneo. Having a formula parser in a system driver seems a tad overkill. Then again, IP filtering has an entire VM in the kernel (BPF), so perhaps BPF could be one way to utilize existing kernel code to provide custom transformations.

moll commented 4 years ago

My small patch above was made to v0.6. I now see v0.7 is out and changes a lot of the internals.

kakra commented 3 years ago

Moving this to the v0.11 feature plan as this depends on how Xbox Elite 2 controllers implement hardware profile support.