Re: [PATCH v2] HID: playstation: Center initial joystick axes to prevent spurious events

From: Guenter Roeck

Date: Tue Feb 24 2026 - 18:35:10 EST


On 2/24/26 14:44, Siarhei Vishniakou wrote:
вт, 24 февр. 2026 г. в 13:10, Guenter Roeck <linux@xxxxxxxxxxxx>:

On Tue, Nov 11, 2025 at 03:45:19PM -0800, Siarhei Vishniakou wrote:
When a new PlayStation gamepad (DualShock 4 or DualSense) is initialized,
the input subsystem sets the default value for its absolute axes (e.g.,
ABS_X, ABS_Y) to 0.

However, the hardware's actual neutral/resting state for these joysticks
is 128 (0x80). This creates a mismatch.

When the first HID report arrives from the device, the driver sees the
resting value of 128. The kernel compares this to its initial state of 0
and incorrectly interprets this as a delta (0 -> 128). Consequently, it
generates EV_ABS events for this initial, non-existent movement.

This behavior can fail userspace 'sanity check' tests (e.g., in
Android CTS) that correctly assert no motion events should be generated
from a device that is already at rest.

This patch fixes the issue by explicitly setting the initial value of the
main joystick axes (e.g., ABS_X, ABS_Y, ABS_RX, ABS_RY) to 128 (0x80)
in the common ps_gamepad_create() function.

This aligns the kernel's initial state with the hardware's expected
neutral state, ensuring that the first report (at 128) produces no
delta and thus, no spurious event.

Signed-off-by: Siarhei Vishniakou <svv@xxxxxxxxxx>
Reviewed-by: Benjamin Tissoires <bentiss@xxxxxxxxxx>
---
drivers/hid/hid-playstation.c | 5 +++++
1 file changed, 5 insertions(+)

diff --git a/drivers/hid/hid-playstation.c b/drivers/hid/hid-playstation.c
index 1468fb11e39d..a145b5ea4405 100644
--- a/drivers/hid/hid-playstation.c
+++ b/drivers/hid/hid-playstation.c
@@ -718,11 +718,16 @@ static struct input_dev *ps_gamepad_create(struct hid_device *hdev,
if (IS_ERR(gamepad))
return ERR_CAST(gamepad);

+ /* Set initial resting state for joysticks to 128 (center) */
input_set_abs_params(gamepad, ABS_X, 0, 255, 0, 0);
+ gamepad->absinfo[ABS_X].value = 128;

input_set_abs_params() can fail to allocate absinfo. If that happens,
this will crash. AI suggests setting the value with input_abs_set_val()
to ensure that the value is checked before dereferencing.

Guenter

input_set_abs_params(gamepad, ABS_Y, 0, 255, 0, 0);
+ gamepad->absinfo[ABS_Y].value = 128;
input_set_abs_params(gamepad, ABS_Z, 0, 255, 0, 0);
input_set_abs_params(gamepad, ABS_RX, 0, 255, 0, 0);
+ gamepad->absinfo[ABS_RX].value = 128;
input_set_abs_params(gamepad, ABS_RY, 0, 255, 0, 0);
+ gamepad->absinfo[ABS_RY].value = 128;
input_set_abs_params(gamepad, ABS_RZ, 0, 255, 0, 0);

input_set_abs_params(gamepad, ABS_HAT0X, -1, 1, 0, 0);
--
2.51.2.1041.gc1ab5b90ca-goo

The function `input_set_abs_params` is ill-formed. If this call can
fail, then it should return some kind of error result instead of void.
In addition, the function name doesn't suggest that it's going to be
doing any allocations.
So the (short-term) fix should be something like this:

/* Set initial resting state for joysticks to 128 (center) */
input_set_abs_params(gamepad, ABS_X, 0, 255, 0, 0);
+ if (gamepad->absinfo == NULL) {
+ // input_set_abs_params allocates "absinfo" struct, which could fail.
+ return ERR_CAST(gamepad);
+ }


That function is called about 870+ times.

A better long-term option would be to change the signature of
input_set_abs_params to return a bool, or to add an explicit
allocation step (looking at code search, there aren't too many places
using this API today, but this might break 3-rd party stuff).

Curious to hear maintainers' opinions on this.

The same would apply to the following macro.

static inline void input_abs_set_##_suffix(struct input_dev *dev, \
unsigned int axis, int val) \
{ \
input_alloc_absinfo(dev); \
if (dev->absinfo) \
dev->absinfo[axis]._item = val; \
}

which is called some 170 times with no error check.

Overall, input_abs_set_val() and input_alloc_absinfo() are widely used
in the kernel. Changing that would be monumental. While I agree that the
current code is less than perfect, I think the immediate fix should be
to avoid the crash and use the same mechanism that is used by all other
drivers.

Of course, I am not the maintainer, so that is just my personal opinion.

Thanks,
Guenter