diff options
author | Sascha Hlusiak <saschahlusiak@arcor.de> | 2012-10-06 16:18:24 +0200 |
---|---|---|
committer | Sascha Hlusiak <saschahlusiak@arcor.de> | 2013-01-16 10:50:40 +0100 |
commit | 342057bf38e2da46609ed2fa0d3f5fb46c8ed215 (patch) | |
tree | cf170f000b6b7c7785618d4c5fcc499485d12885 | |
parent | 053405f711512959e95d0a882d69b6cba6405e7d (diff) |
backend_evdev: fix scaling overflow for high resolution axes
The module scales all axis values from the kernel to the range of
-32768 .. 32768, for compatibility with the old joystick kernel module.
The current implementation had an integer overflow, if the axis had a high
resolution of > 16384, like the popular XBox 360 controller.
This commitmakes the scaling use float instead to fix erratic behaviour
on high resolution joysticks. The joystick backend was not affected.
Fixes bug: https://bugs.freedesktop.org/show_bug.cgi?id=42399
-rw-r--r-- | src/backend_evdev.c | 26 |
1 files changed, 24 insertions, 2 deletions
diff --git a/src/backend_evdev.c b/src/backend_evdev.c index d3c12c5..ca0b2e0 100644 --- a/src/backend_evdev.c +++ b/src/backend_evdev.c @@ -277,8 +277,30 @@ jstkReadData_evdev(JoystickDevPtr joystick, struct jstk_evdev_axis_data *axis; axis = &data->axis[iev.code]; if ((axis->number >= 0) && (axis->number < MAXAXES)) { - value = (iev.value - axis->min) * 65535 - / (axis->max - axis->min) - 32768; + /* NOTE: controllers report totally different ranges: + * - 0..256, with a center of 127 (Logitech Dual Action axes) + * - 0..256 with a center of 0 (XBox left/right triggers) + * - -32768..32768 with a center of 0 (XBox axes) + * + * These ranges will ALL be scaled to -32768..32768, with + * the center value to be assumed 0. This is for compatibility + * with the legacy joystick module, which reports values in + * the same range. + * + * The value is also important for the deadzone, which can be + * configured by the user and is in -32768..32768 range. + * + * TODO: how to respect center value, so that that XBox triggers + * and logitech axes report idle, when not moved? + * TODO: report all values as -1.0f..1.0f, but this would possibly + * break config file semantics. + */ + + float v = (float) iev.value; + v = (v - (float)axis->min) * 65535.0f + / (axis->max - axis->min) - 32768.0f; + value = (int) v; + if (abs(value) < joystick->axis[axis->number].deadzone) { /* We only want one event when in deadzone */ if (joystick->axis[axis->number].value != 0) { |