* [PATCH 0/3] input: force feedback for trigger rumble motors
@ 2026-07-30 9:53 Guillaume Casal
2026-07-30 9:53 ` [PATCH 1/3] input: uapi: Add trigger_left and trigger_right to ff_rumble_effect struct Guillaume Casal
` (3 more replies)
0 siblings, 4 replies; 13+ messages in thread
From: Guillaume Casal @ 2026-07-30 9:53 UTC (permalink / raw)
To: dmitry.torokhov; +Cc: linux-input, linux-kernel, dbdaniel42
Some gamepads carry rumble motors behind their triggers, in addition to
the usual two in the grips: Xbox controllers call them impulse triggers,
and handhelds such as the ASUS ROG Xbox Ally X have them too. The force
feedback API cannot reach those motors, because struct ff_rumble_effect
only carries a strong and a weak magnitude.
The first two patches are Daniel Bomar's, posted in April 2022 and never
merged:
https://lore.kernel.org/lkml/20220410220449.5071-1-dbdaniel42@gmail.com/
They add trigger_left and trigger_right to struct ff_rumble_effect and
carry them through ff-memless. I have rebased them onto v7.2-rc5 with no
functional change and kept his authorship.
The third patch is new and addresses what I believe was the main gap in
that series: there was no way for userspace to discover whether a device
has trigger motors at all. It adds an FF_TRIGGER_RUMBLE capability bit
that drivers advertise and applications test in the EVIOCGBIT(EV_FF)
bitmap.
On ABI: struct ff_rumble_effect lives in a union sized by the larger
struct ff_periodic_effect, so the two new members add no size. On an
x86_64 build, struct ff_effect stays at 48 bytes and the union at 32,
of which the extended rumble struct uses 8.
Testing. I ran this on an ASUS ROG Xbox Ally X (USB 0b05:1b4c) under
SteamOS, kernel 6.16.12, where the patches apply unchanged. A memless
test device advertising the capability shows bit 0x62 in its
EVIOCGBIT(EV_FF) bitmap, and the four magnitudes arrive at the driver
independently:
triggers only : strong= 0 weak= 0 trigger_left=65535 trigger_right=65535
grips only : strong=65535 weak=65535 trigger_left= 0 trigger_right= 0
left trigger : strong= 0 weak= 0 trigger_left=65535 trigger_right= 0
right trigger : strong= 0 weak= 0 trigger_left= 0 trigger_right=65535
Wired into that handheld's HID driver, this drives the four actuators
separately on real hardware: the triggers buzz while the grips stay
silent, confirmed both by feel and by capturing the USB traffic. That
driver is not in mainline, so its patch is not part of this series; I
will send it to its maintainers separately.
To be explicit about what was and was not tested: on v7.2-rc5 the series
applies cleanly, drivers/input/ff-memless.o builds, and checkpatch.pl
reports no warnings, but I have not booted that kernel. The runtime
testing described above was done on 6.16.12, where the affected code is
identical.
Daniel Bomar (2):
input: uapi: Add trigger_left and trigger_right to ff_rumble_effect struct
input: ff-memless: Add trigger left/right in ml_combine_effects
Guillaume Casal (1):
input: Add FF_TRIGGER_RUMBLE capability bit
drivers/input/ff-memless.c | 8 +++++++-
include/uapi/linux/input.h | 5 +++++
2 files changed, 12 insertions(+), 1 deletion(-)
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 1/3] input: uapi: Add trigger_left and trigger_right to ff_rumble_effect struct
2026-07-30 9:53 [PATCH 0/3] input: force feedback for trigger rumble motors Guillaume Casal
@ 2026-07-30 9:53 ` Guillaume Casal
2026-07-30 10:04 ` sashiko-bot
2026-07-30 9:53 ` [PATCH 2/3] input: ff-memless: Add trigger left/right in ml_combine_effects Guillaume Casal
` (2 subsequent siblings)
3 siblings, 1 reply; 13+ messages in thread
From: Guillaume Casal @ 2026-07-30 9:53 UTC (permalink / raw)
To: dmitry.torokhov; +Cc: linux-input, linux-kernel, dbdaniel42
From: Daniel Bomar <dbdaniel42@gmail.com>
This adds two variables to control the trigger motors to the struct that
is passed in from userspace. This is ABI compatible because it does not
change the total size of the union that contains this struct: the union
is sized by struct ff_periodic_effect, which is larger.
Originally posted in 2022 and never merged:
https://lore.kernel.org/lkml/20220410220449.5071-1-dbdaniel42@gmail.com/
Rebased onto v7.2-rc5 with no functional change; the kernel-doc entries for
the two new members are the only addition.
Signed-off-by: Daniel Bomar <dbdaniel42@gmail.com>
Signed-off-by: Guillaume Casal <guillaume.casal.42@gmail.com>
---
diff --git a/include/uapi/linux/input.h b/include/uapi/linux/input.h
--- a/include/uapi/linux/input.h
+++ b/include/uapi/linux/input.h
@@ -420,6 +420,8 @@
* struct ff_rumble_effect - defines parameters of a periodic force-feedback effect
* @strong_magnitude: magnitude of the heavy motor
* @weak_magnitude: magnitude of the light one
+ * @trigger_left: magnitude of the motor behind the left trigger
+ * @trigger_right: magnitude of the motor behind the right trigger
*
* Some rumble pads have two motors of different weight. Strong_magnitude
* represents the magnitude of the vibration generated by the heavy one.
@@ -427,6 +429,8 @@
struct ff_rumble_effect {
__u16 strong_magnitude;
__u16 weak_magnitude;
+ __u16 trigger_left;
+ __u16 trigger_right;
};
/**
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 2/3] input: ff-memless: Add trigger left/right in ml_combine_effects
2026-07-30 9:53 [PATCH 0/3] input: force feedback for trigger rumble motors Guillaume Casal
2026-07-30 9:53 ` [PATCH 1/3] input: uapi: Add trigger_left and trigger_right to ff_rumble_effect struct Guillaume Casal
@ 2026-07-30 9:53 ` Guillaume Casal
2026-07-30 10:24 ` sashiko-bot
2026-07-30 9:53 ` [PATCH 3/3] input: Add FF_TRIGGER_RUMBLE capability bit Guillaume Casal
2026-07-30 13:40 ` [PATCH v2 0/4] input: force feedback for trigger rumble motors Guillaume Casal
3 siblings, 1 reply; 13+ messages in thread
From: Guillaume Casal @ 2026-07-30 9:53 UTC (permalink / raw)
To: dmitry.torokhov; +Cc: linux-input, linux-kernel, dbdaniel42
From: Daniel Bomar <dbdaniel42@gmail.com>
Combine the new trigger magnitudes alongside the existing strong and weak
magnitudes, so that drivers using input_ff_create_memless() receive them
the same way.
Originally posted in 2022 and never merged:
https://lore.kernel.org/lkml/20220410220449.5071-1-dbdaniel42@gmail.com/
Rebased onto v7.2-rc5 with no functional change.
Signed-off-by: Daniel Bomar <dbdaniel42@gmail.com>
Signed-off-by: Guillaume Casal <guillaume.casal.42@gmail.com>
---
diff --git a/drivers/input/ff-memless.c b/drivers/input/ff-memless.c
--- a/drivers/input/ff-memless.c
+++ b/drivers/input/ff-memless.c
@@ -243,7 +243,7 @@
int gain)
{
struct ff_effect *new = state->effect;
- unsigned int strong, weak, i;
+ unsigned int strong, weak, trigger_left, trigger_right, i;
int x, y;
s16 level;
@@ -269,6 +269,8 @@
case FF_RUMBLE:
strong = (u32)new->u.rumble.strong_magnitude * gain / 0xffff;
weak = (u32)new->u.rumble.weak_magnitude * gain / 0xffff;
+ trigger_left = (u32)new->u.rumble.trigger_left * gain / 0xffff;
+ trigger_right = (u32)new->u.rumble.trigger_right * gain / 0xffff;
if (effect->u.rumble.strong_magnitude + strong)
effect->direction = ml_calculate_direction(
@@ -287,6 +289,10 @@
0xffffU);
effect->u.rumble.weak_magnitude =
min(weak + effect->u.rumble.weak_magnitude, 0xffffU);
+ effect->u.rumble.trigger_left =
+ min(trigger_left + effect->u.rumble.trigger_left, 0xffffU);
+ effect->u.rumble.trigger_right =
+ min(trigger_right + effect->u.rumble.trigger_right, 0xffffU);
break;
case FF_PERIODIC:
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 3/3] input: Add FF_TRIGGER_RUMBLE capability bit
2026-07-30 9:53 [PATCH 0/3] input: force feedback for trigger rumble motors Guillaume Casal
2026-07-30 9:53 ` [PATCH 1/3] input: uapi: Add trigger_left and trigger_right to ff_rumble_effect struct Guillaume Casal
2026-07-30 9:53 ` [PATCH 2/3] input: ff-memless: Add trigger left/right in ml_combine_effects Guillaume Casal
@ 2026-07-30 9:53 ` Guillaume Casal
2026-07-30 10:39 ` sashiko-bot
2026-07-30 13:40 ` [PATCH v2 0/4] input: force feedback for trigger rumble motors Guillaume Casal
3 siblings, 1 reply; 13+ messages in thread
From: Guillaume Casal @ 2026-07-30 9:53 UTC (permalink / raw)
To: dmitry.torokhov; +Cc: linux-input, linux-kernel, dbdaniel42
The preceding patches let userspace ask for rumble in the motors located
under the triggers, but give it no way to find out whether the device has
such motors at all. Without that, an application can only set the new
magnitudes and hope, and it cannot tell a device that ignores them from
one that has no trigger motors.
Add FF_TRIGGER_RUMBLE as a capability bit. Drivers that fill in the
trigger magnitudes advertise it with
input_set_capability(dev, EV_FF, FF_TRIGGER_RUMBLE);
and userspace tests for it in the EVIOCGBIT(EV_FF) bitmap, exactly as it
already tests for FF_RUMBLE.
It is deliberately not an effect type. The magnitudes keep travelling
inside struct ff_rumble_effect and FF_RUMBLE remains the transport, so
FF_EFFECT_MIN and FF_EFFECT_MAX are untouched. Placing it at 0x62, above
FF_AUTOCENTER, keeps it out of the effect id space whose upper bound
FF_MAX_EFFECTS already documents. Unlike its neighbours FF_GAIN and
FF_AUTOCENTER it is read-only: it reports what the hardware has rather
than something userspace sets, and it is never used as an effect id.
Signed-off-by: Guillaume Casal <guillaume.casal.42@gmail.com>
---
diff --git a/include/uapi/linux/input.h b/include/uapi/linux/input.h
--- a/include/uapi/linux/input.h
+++ b/include/uapi/linux/input.h
@@ -528,6 +528,7 @@
#define FF_GAIN 0x60
#define FF_AUTOCENTER 0x61
+#define FF_TRIGGER_RUMBLE 0x62
/*
* ff->playback(effect_id = FF_GAIN) is the first effect_id to
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 1/3] input: uapi: Add trigger_left and trigger_right to ff_rumble_effect struct
2026-07-30 9:53 ` [PATCH 1/3] input: uapi: Add trigger_left and trigger_right to ff_rumble_effect struct Guillaume Casal
@ 2026-07-30 10:04 ` sashiko-bot
0 siblings, 0 replies; 13+ messages in thread
From: sashiko-bot @ 2026-07-30 10:04 UTC (permalink / raw)
To: Guillaume Casal; +Cc: dmitry.torokhov, linux-input
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
New issues:
- [High] Adding `trigger_left` and `trigger_right` to `struct ff_rumble_effect` within a union breaks backward compatibility and causes random device actuation for legacy userspace applications.
Pre-existing issues:
- [High] 4 bytes of uninitialized kernel stack memory are leaked to userspace via the `uinput` subsystem when a 32-bit compat application sends an `EVIOCSFF` ioctl.
--
--- Patch [1]: [PATCH 1/3] input: uapi: Add trigger_left and trigger_right to ff_rumble_effect struct ---
commit 47b93f39a2f9b455e85b8381fa40a96ca5aaac36
Author: Daniel Bomar <dbdaniel42@gmail.com>
input: uapi: Add trigger_left and trigger_right to ff_rumble_effect struct
This adds two variables to control the trigger motors to the struct that
is passed in from userspace. It reuses existing union padding to maintain
the total size of struct ff_effect.
Link: https://lore.kernel.org/lkml/20220410220449.5071-1-dbdaniel42@gmail.com/
> diff --git a/include/uapi/linux/input.h b/include/uapi/linux/input.h
> index 6aa703fcfcfb7..3d62603a387b9 100644
> --- a/include/uapi/linux/input.h
> +++ b/include/uapi/linux/input.h
[ ... ]
> @@ -427,6 +429,8 @@ struct ff_periodic_effect {
> struct ff_rumble_effect {
> __u16 strong_magnitude;
> __u16 weak_magnitude;
> + __u16 trigger_left;
> + __u16 trigger_right;
> };
[Severity: High]
Does this break backward compatibility for legacy userspace applications?
Because struct ff_rumble_effect resides within a union inside struct ff_effect,
extending its size from 4 to 8 bytes does not change the overall size of
struct ff_effect, and the EVIOCSFF ioctl number remains identical.
Legacy userspace applications typically allocate struct ff_effect on the stack
without zero-initializing the entire union padding. When calling EVIOCSFF for
a rumble effect, they leave uninitialized stack memory in the trailing bytes
that now correspond to trigger_left and trigger_right.
Could an updated driver read these uninitialized fields and actuate the trigger
motors based on random stack garbage?
[Severity: High]
This isn't a bug introduced by this patch, but does the input subsystem leak
uninitialized kernel stack memory to userspace during 32-bit compat ioctls?
In drivers/input/evdev.c:evdev_do_ioctl(), an uninitialized 48-byte effect
variable is declared on the stack:
struct ff_effect effect;
When a 32-bit compat application calls EVIOCSFF, input_ff_effect_from_user() in
drivers/input/input-compat.c copies only 44 bytes from userspace:
if (copy_from_user(compat_effect, buffer,
sizeof(struct ff_effect_compat)))
return -EFAULT;
This leaves 4 bytes of the effect structure untouched, containing uninitialized
kernel stack data.
If this effect is uploaded to a virtual uinput device, uinput_dev_upload_effect()
stores a pointer to this stack variable. When a 64-bit uinput daemon process
calls the UI_BEGIN_FF_UPLOAD ioctl in
drivers/input/misc/uinput.c:uinput_ioctl_handler():
retval = uinput_ff_upload_to_user(p, &ff_up);
it copies the entire 48-byte struct ff_effect back to userspace, reliably
disclosing 4 bytes of uninitialized kernel stack memory per ioctl call. Could
this be exploited to read kernel memory layout?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260730095317.767418-1-guillaume.casal.42@gmail.com?part=1
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/3] input: ff-memless: Add trigger left/right in ml_combine_effects
2026-07-30 9:53 ` [PATCH 2/3] input: ff-memless: Add trigger left/right in ml_combine_effects Guillaume Casal
@ 2026-07-30 10:24 ` sashiko-bot
0 siblings, 0 replies; 13+ messages in thread
From: sashiko-bot @ 2026-07-30 10:24 UTC (permalink / raw)
To: Guillaume Casal; +Cc: dmitry.torokhov, linux-input
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Critical] Extending `struct ff_rumble_effect` breaks backward compatibility for legacy userspace applications by interpreting uninitialized union padding as valid rumble magnitudes.
--
--- Patch [2]: [PATCH 2/3] input: ff-memless: Add trigger left/right in ml_combine_effects ---
commit 3748260413928654275c7c17fc4ca45fccc0a9ee
Author: Daniel Bomar <dbdaniel42@gmail.com>
input: ff-memless: Add trigger left/right in ml_combine_effects
Combine the new trigger magnitudes alongside the existing strong and weak
magnitudes, so that drivers using input_ff_create_memless() receive them
the same way.
> diff --git a/drivers/input/ff-memless.c b/drivers/input/ff-memless.c
> index d1fefd1dfc0de..f6e7f5e93c687 100644
> --- a/drivers/input/ff-memless.c
> +++ b/drivers/input/ff-memless.c
[ ... ]
> @@ -269,6 +269,8 @@ static void ml_combine_effects(struct ff_effect *effect,
> case FF_RUMBLE:
> strong = (u32)new->u.rumble.strong_magnitude * gain / 0xffff;
> weak = (u32)new->u.rumble.weak_magnitude * gain / 0xffff;
> + trigger_left = (u32)new->u.rumble.trigger_left * gain / 0xffff;
> + trigger_right = (u32)new->u.rumble.trigger_right * gain / 0xffff;
[Severity: Critical]
Does interpreting these new fields break backward compatibility for legacy
userspace applications?
Because struct ff_rumble_effect is part of a union dominated by larger
structs in struct ff_effect, extending its size did not change the total size
of struct ff_effect.
Legacy applications allocating struct ff_effect on the stack, setting
type = FF_RUMBLE, and initializing only strong_magnitude and weak_magnitude
could unknowingly pass uninitialized bytes to the kernel.
Since this code actively scales and applies trigger_left and trigger_right,
wouldn't those uninitialized bytes from the stack result in random trigger
vibrations?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260730095317.767418-1-guillaume.casal.42@gmail.com?part=2
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 3/3] input: Add FF_TRIGGER_RUMBLE capability bit
2026-07-30 9:53 ` [PATCH 3/3] input: Add FF_TRIGGER_RUMBLE capability bit Guillaume Casal
@ 2026-07-30 10:39 ` sashiko-bot
0 siblings, 0 replies; 13+ messages in thread
From: sashiko-bot @ 2026-07-30 10:39 UTC (permalink / raw)
To: Guillaume Casal; +Cc: dmitry.torokhov, linux-input
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] Extending `struct ff_rumble_effect` within the `ff_effect` union breaks backward compatibility for older userspace applications that use `EVIOCSFF` by exposing uninitialized memory as trigger magnitudes.
- [Low] Missing `FF_TRIGGER_RUMBLE` string representation in the `force` array in `hid-debug.c`.
- [Low] `FF_TRIGGER_RUMBLE` is not documented in the Force Feedback API documentation.
--
--- Patch [3]: [PATCH 3/3] input: Add FF_TRIGGER_RUMBLE capability bit ---
commit 454627a6a6ad091c91ae3a0477831268ea8fe178
Author: Guillaume Casal <guillaume.casal.42@gmail.com>
input: Add FF_TRIGGER_RUMBLE capability bit
This commit adds the FF_TRIGGER_RUMBLE capability bit to allow userspace to
discover if a device has motors under the triggers. The capability is added
as a read-only bit at 0x62 to avoid conflicting with the effect id space.
> diff --git a/include/uapi/linux/input.h b/include/uapi/linux/input.h
> index 3d62603a387b9..677e9505a4aa3 100644
> --- a/include/uapi/linux/input.h
> +++ b/include/uapi/linux/input.h
> @@ -528,6 +528,7 @@ struct ff_effect {
>
> #define FF_GAIN 0x60
> #define FF_AUTOCENTER 0x61
> +#define FF_TRIGGER_RUMBLE 0x62
[Severity: High]
Does extending struct ff_rumble_effect (as mentioned in the commit message)
cause a regression for older userspace applications using EVIOCSFF?
Legacy applications frequently allocate struct ff_effect on the stack,
initialize only known fields like strong_magnitude and weak_magnitude, and
pass the struct to the EVIOCSFF ioctl.
In drivers/input/evdev.c:evdev_do_ioctl():
case EVIOC_MASK_SIZE(EVIOCSFF):
if (input_ff_effect_from_user(p, size, &effect))
return -EFAULT;
This copies the entire union size from userspace. If uninitialized stack
garbage is copied, it could be interpreted as trigger_left and trigger_right.
Then in drivers/input/ff-memless.c:ml_combine_effects():
trigger_left = (u32)new->u.rumble.trigger_left * gain / 0xffff;
trigger_right = (u32)new->u.rumble.trigger_right * gain / 0xffff;
These uninitialized fields are actively read and processed into the final
effect playback state. Could this result in random, unintended vibration of
the trigger motors?
[Severity: Low]
Is the FF_TRIGGER_RUMBLE string representation missing in the force array?
In drivers/hid/hid-debug.c:force:
static const char *force[FF_CNT] = {
[FF_RUMBLE] = "FF_RUMBLE",
Without adding [FF_TRIGGER_RUMBLE] = "FF_TRIGGER_RUMBLE" here,
names[EV_FF][0x62] evaluates to NULL. This causes hid_resolv_event() to fall
back to printing the raw hex value ('0062') instead of 'FF_TRIGGER_RUMBLE'
in debugfs.
[Severity: Low]
Is FF_TRIGGER_RUMBLE missing from the Force Feedback API documentation?
Documentation/input/ff.rst:Querying device capabilities lists supported
EV_FF capability bits:
- FF_GAIN gain is adjustable
- FF_AUTOCENTER autocenter is adjustable
Since this commit introduces a new capability, should it be documented here
so userspace developers know how to discover trigger rumble support?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260730095317.767418-1-guillaume.casal.42@gmail.com?part=3
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v2 0/4] input: force feedback for trigger rumble motors
2026-07-30 9:53 [PATCH 0/3] input: force feedback for trigger rumble motors Guillaume Casal
` (2 preceding siblings ...)
2026-07-30 9:53 ` [PATCH 3/3] input: Add FF_TRIGGER_RUMBLE capability bit Guillaume Casal
@ 2026-07-30 13:40 ` Guillaume Casal
2026-07-30 13:40 ` [PATCH v2 1/4] input: Add FF_TRIGGER_RUMBLE effect type Guillaume Casal
` (3 more replies)
3 siblings, 4 replies; 13+ messages in thread
From: Guillaume Casal @ 2026-07-30 13:40 UTC (permalink / raw)
To: dmitry.torokhov; +Cc: linux-input, linux-kernel, dbdaniel42
Some gamepads carry rumble motors behind their triggers, in addition to
the usual two in the grips: Xbox controllers call them impulse triggers,
and handhelds such as the ASUS ROG Xbox Ally X have them too. The force
feedback API cannot reach those motors.
v1: https://lore.kernel.org/linux-input/20260730095317.767418-1-guillaume.casal.42@gmail.com/
Changes since v1
================
v1 followed the 2022 series by Daniel Bomar and added trigger_left and
trigger_right to struct ff_rumble_effect. That was wrong, and I am
grateful the problem was pointed out on the list before it went any
further.
EVIOCSFF copies the whole struct ff_effect from userspace. An
application that sets only strong_magnitude and weak_magnitude, and does
not clear the rest of the union, passes uninitialised stack content in
the bytes that v1 gave meaning to. ff-memless would then scale that
content and hand it to the driver, so a program that works today would
start buzzing the triggers at random. Keeping the size of the union
unchanged makes the layout compatible, not the meaning. This is likely
why the 2022 series never went anywhere.
v2 therefore uses a distinct effect type, FF_TRIGGER_RUMBLE, with its own
struct ff_trigger_rumble_effect, following what was done for FF_HAPTIC.
No existing application emits this type, so no uninitialised byte can be
mistaken for a magnitude. The capability bit of v1 is dropped: userspace
discovers the type in the EVIOCGBIT(EV_FF) bitmap, as it does for
FF_RUMBLE.
Two smaller points raised on v1 are fixed here as well: the missing entry
in the force[] array of hid-debug.c, and the missing line in
Documentation/input/ff.rst.
Design notes
============
ml_get_combo_effect() groups playing effects by type, so a trigger rumble
effect forms its own combo and reaches the driver in its own
play_effect() call, without disturbing FF_RUMBLE. An effect that has
finished still contributes its type with zero magnitudes, so the stop
path needs no change.
Testing
=======
checkpatch.pl reports no warnings on any of the four patches.
I booted v7.2-rc5 with this series applied under QEMU, with a small
memless driver compiled in that advertises both types and logs the
magnitudes it is handed. Userspace side, a static init issues the
EVIOCSFF ioctls. Output, kernel lines interleaved with userspace ones:
capabilities advertised : FF_RUMBLE yes, FF_TRIGGER_RUMBLE yes
triggers only -> FF_TRIGGER_RUMBLE left=65535 right=65535
grips only -> FF_RUMBLE strong=65535 weak=65535
left trigger only -> FF_TRIGGER_RUMBLE left=65535 right= 0
right trigger only -> FF_TRIGGER_RUMBLE left= 0 right=65535
Each effect is followed by a call with zero magnitudes when it expires,
so the existing stop path needs no change.
The last case is the one that matters for the concern raised on v1. The
test fills the whole struct ff_effect with 0xAA, sets only type,
replay.length and the two rumble magnitudes, and uploads it, which is
what a careless application does today:
old-style app, dirty union
-> FF_RUMBLE strong=32768 weak=32768
and no FF_TRIGGER_RUMBLE call at all
The dirty bytes cannot be mistaken for trigger magnitudes, because they
never carry that meaning for an FF_RUMBLE effect. With v1 they would have
been scaled and sent to the hardware.
The same was then run against real hardware. The vendor kernel of my
handheld cannot be rebuilt, its sources are not published, so I booted
the patched kernel in a VM on the same machine and handed it the gamepad
by USB passthrough. The driver bound it as usual and the device came up
advertising both types:
peripheral: /dev/input/event8 (ASUS ROG Ally X Gamepad)
capabilities advertised : FF_RUMBLE yes, FF_TRIGGER_RUMBLE yes
Capturing the physical bus from the host with usbmon while the VM drove
the pad gives the reports the firmware actually received:
triggers: L=100 R=100 grips: L= 0 R= 0 triggers only
triggers: L= 0 R= 0 grips: L=100 R=100 grips only
triggers: L=100 R= 0 grips: L= 0 R= 0 left trigger only
triggers: L= 0 R=100 grips: L= 0 R= 0 right trigger only
triggers: L= 0 R= 0 grips: L= 50 R= 50 old-style app, dirty union
The four actuators are driven independently, and the careless
application gets its 50% in the grips with nothing in the triggers,
which is the whole point of the change in shape since v1.
The driver patch that fills those two magnitudes is not part of this
series: that driver is not in mainline, and I will send it to its
maintainers once the API here settles.
Guillaume Casal (4):
input: Add FF_TRIGGER_RUMBLE effect type
input: ff-memless: Handle FF_TRIGGER_RUMBLE
HID: debug: Add FF_TRIGGER_RUMBLE name
Documentation: input: Document FF_TRIGGER_RUMBLE
Documentation/input/ff.rst | 1 +
drivers/hid/hid-debug.c | 1 +
drivers/input/ff-memless.c | 9 +++++++++
include/uapi/linux/input.h | 17 ++++++++++++++++-
4 files changed, 27 insertions(+), 1 deletion(-)
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v2 1/4] input: Add FF_TRIGGER_RUMBLE effect type
2026-07-30 13:40 ` [PATCH v2 0/4] input: force feedback for trigger rumble motors Guillaume Casal
@ 2026-07-30 13:40 ` Guillaume Casal
2026-07-30 13:53 ` sashiko-bot
2026-07-30 13:40 ` [PATCH v2 2/4] input: ff-memless: Handle FF_TRIGGER_RUMBLE Guillaume Casal
` (2 subsequent siblings)
3 siblings, 1 reply; 13+ messages in thread
From: Guillaume Casal @ 2026-07-30 13:40 UTC (permalink / raw)
To: dmitry.torokhov; +Cc: linux-input, linux-kernel, dbdaniel42
Some gamepads carry rumble motors behind their triggers, in addition to
the ones in the grips that FF_RUMBLE drives: Xbox controllers call them
impulse triggers, and handhelds such as the ASUS ROG Xbox Ally X have
them too. The force feedback API cannot reach those motors.
Add FF_TRIGGER_RUMBLE as a new effect type carrying its own
struct ff_trigger_rumble_effect, and move FF_EFFECT_MIN down to it, in
the same way FF_HAPTIC was added.
v1 took the approach of the 2022 series and added two members to
struct ff_rumble_effect instead:
https://lore.kernel.org/linux-input/20260730095317.767418-1-guillaume.casal.42@gmail.com/
That is not safe. EVIOCSFF copies the whole struct ff_effect from
userspace, and an application that leaves the tail of the union
uninitialised, which is common when only strong_magnitude and
weak_magnitude are set, would have had that stack content interpreted as
trigger magnitudes. Working programs would start buzzing their triggers
at random. Keeping the size of the union unchanged makes the ABI
compatible in layout, not in meaning.
A distinct effect type has no such problem: no existing application ever
emits it, so no uninitialised byte can be mistaken for a magnitude. It
also removes the need for a separate capability bit, since userspace
discovers the type in the EVIOCGBIT(EV_FF) bitmap exactly as it does for
FF_RUMBLE.
Based on an earlier attempt by Daniel Bomar:
https://lore.kernel.org/lkml/20220410220449.5071-1-dbdaniel42@gmail.com/
Signed-off-by: Guillaume Casal <guillaume.casal.42@gmail.com>
---
diff --git a/include/uapi/linux/input.h b/include/uapi/linux/input.h
--- a/include/uapi/linux/input.h
+++ b/include/uapi/linux/input.h
@@ -438,6 +438,20 @@
* @repeat_count: number of times to retrigger effect
* @retrigger_period: time before effect is retriggered (in ms)
*/
+/**
+ * struct ff_trigger_rumble_effect - parameters of a trigger rumble effect
+ * @left_magnitude: magnitude of the motor behind the left trigger
+ * @right_magnitude: magnitude of the motor behind the right trigger
+ *
+ * Some gamepads carry rumble motors behind their triggers, in addition to
+ * the ones in the grips that FF_RUMBLE drives. Xbox controllers call them
+ * impulse triggers.
+ */
+struct ff_trigger_rumble_effect {
+ __u16 left_magnitude;
+ __u16 right_magnitude;
+};
+
struct ff_haptic_effect {
__u16 hid_usage;
__u16 vendor_id;
@@ -483,6 +497,7 @@
struct ff_periodic_effect periodic;
struct ff_condition_effect condition[2]; /* One for each axis */
struct ff_rumble_effect rumble;
+ struct ff_trigger_rumble_effect trigger_rumble;
struct ff_haptic_effect haptic;
} u;
};
@@ -491,6 +506,7 @@
* Force feedback effect types
*/
+#define FF_TRIGGER_RUMBLE 0x4e
#define FF_HAPTIC 0x4f
#define FF_RUMBLE 0x50
#define FF_PERIODIC 0x51
@@ -501,7 +517,7 @@
#define FF_INERTIA 0x56
#define FF_RAMP 0x57
-#define FF_EFFECT_MIN FF_HAPTIC
+#define FF_EFFECT_MIN FF_TRIGGER_RUMBLE
#define FF_EFFECT_MAX FF_RAMP
/*
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v2 2/4] input: ff-memless: Handle FF_TRIGGER_RUMBLE
2026-07-30 13:40 ` [PATCH v2 0/4] input: force feedback for trigger rumble motors Guillaume Casal
2026-07-30 13:40 ` [PATCH v2 1/4] input: Add FF_TRIGGER_RUMBLE effect type Guillaume Casal
@ 2026-07-30 13:40 ` Guillaume Casal
2026-07-30 13:40 ` [PATCH v2 3/4] HID: debug: Add FF_TRIGGER_RUMBLE name Guillaume Casal
2026-07-30 13:40 ` [PATCH v2 4/4] Documentation: input: Document FF_TRIGGER_RUMBLE Guillaume Casal
3 siblings, 0 replies; 13+ messages in thread
From: Guillaume Casal @ 2026-07-30 13:40 UTC (permalink / raw)
To: dmitry.torokhov; +Cc: linux-input, linux-kernel, dbdaniel42
Combine trigger rumble effects the way the other types are combined, so
that drivers using input_ff_create_memless() receive them.
Because ml_get_combo_effect() groups playing effects by type, a trigger
rumble effect forms its own combo and reaches the driver in its own
play_effect() call, leaving FF_RUMBLE untouched. An effect that has
finished still contributes its type to the combo with zero magnitudes,
so the existing stop path works unchanged.
Signed-off-by: Guillaume Casal <guillaume.casal.42@gmail.com>
---
diff --git a/drivers/input/ff-memless.c b/drivers/input/ff-memless.c
--- a/drivers/input/ff-memless.c
+++ b/drivers/input/ff-memless.c
@@ -289,6 +289,15 @@
min(weak + effect->u.rumble.weak_magnitude, 0xffffU);
break;
+ case FF_TRIGGER_RUMBLE:
+ effect->u.trigger_rumble.left_magnitude =
+ min((u32)new->u.trigger_rumble.left_magnitude * gain / 0xffff +
+ effect->u.trigger_rumble.left_magnitude, 0xffffU);
+ effect->u.trigger_rumble.right_magnitude =
+ min((u32)new->u.trigger_rumble.right_magnitude * gain / 0xffff +
+ effect->u.trigger_rumble.right_magnitude, 0xffffU);
+ break;
+
case FF_PERIODIC:
i = apply_envelope(state, abs(new->u.periodic.magnitude),
&new->u.periodic.envelope);
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v2 3/4] HID: debug: Add FF_TRIGGER_RUMBLE name
2026-07-30 13:40 ` [PATCH v2 0/4] input: force feedback for trigger rumble motors Guillaume Casal
2026-07-30 13:40 ` [PATCH v2 1/4] input: Add FF_TRIGGER_RUMBLE effect type Guillaume Casal
2026-07-30 13:40 ` [PATCH v2 2/4] input: ff-memless: Handle FF_TRIGGER_RUMBLE Guillaume Casal
@ 2026-07-30 13:40 ` Guillaume Casal
2026-07-30 13:40 ` [PATCH v2 4/4] Documentation: input: Document FF_TRIGGER_RUMBLE Guillaume Casal
3 siblings, 0 replies; 13+ messages in thread
From: Guillaume Casal @ 2026-07-30 13:40 UTC (permalink / raw)
To: dmitry.torokhov; +Cc: linux-input, linux-kernel, dbdaniel42
Without an entry in the force[] array, hid_resolv_event() prints the raw
hex code instead of the name in debugfs.
Signed-off-by: Guillaume Casal <guillaume.casal.42@gmail.com>
---
diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c
--- a/drivers/hid/hid-debug.c
+++ b/drivers/hid/hid-debug.c
@@ -3583,6 +3583,7 @@
};
static const char *force[FF_CNT] = {
+ [FF_TRIGGER_RUMBLE] = "FF_TRIGGER_RUMBLE",
[FF_RUMBLE] = "FF_RUMBLE",
[FF_PERIODIC] = "FF_PERIODIC",
[FF_CONSTANT] = "FF_CONSTANT",
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v2 4/4] Documentation: input: Document FF_TRIGGER_RUMBLE
2026-07-30 13:40 ` [PATCH v2 0/4] input: force feedback for trigger rumble motors Guillaume Casal
` (2 preceding siblings ...)
2026-07-30 13:40 ` [PATCH v2 3/4] HID: debug: Add FF_TRIGGER_RUMBLE name Guillaume Casal
@ 2026-07-30 13:40 ` Guillaume Casal
3 siblings, 0 replies; 13+ messages in thread
From: Guillaume Casal @ 2026-07-30 13:40 UTC (permalink / raw)
To: dmitry.torokhov; +Cc: linux-input, linux-kernel, dbdaniel42
List the new effect type alongside the others so that userspace
developers can find it when querying device capabilities.
Signed-off-by: Guillaume Casal <guillaume.casal.42@gmail.com>
---
diff --git a/Documentation/input/ff.rst b/Documentation/input/ff.rst
--- a/Documentation/input/ff.rst
+++ b/Documentation/input/ff.rst
@@ -85,6 +85,7 @@
- FF_FRICTION can simulate friction
- FF_DAMPER can simulate damper effects
- FF_RUMBLE rumble effects
+- FF_TRIGGER_RUMBLE rumble effects in the triggers
- FF_INERTIA can simulate inertia
- FF_GAIN gain is adjustable
- FF_AUTOCENTER autocenter is adjustable
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v2 1/4] input: Add FF_TRIGGER_RUMBLE effect type
2026-07-30 13:40 ` [PATCH v2 1/4] input: Add FF_TRIGGER_RUMBLE effect type Guillaume Casal
@ 2026-07-30 13:53 ` sashiko-bot
0 siblings, 0 replies; 13+ messages in thread
From: sashiko-bot @ 2026-07-30 13:53 UTC (permalink / raw)
To: Guillaume Casal; +Cc: dmitry.torokhov, linux-input
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] Kernel stack memory leak via `evdev` compat IOCTL and `uinput`.
--
--- Patch [1]: [PATCH v2 1/4] input: Add FF_TRIGGER_RUMBLE effect type ---
commit 2bed919a335670e21f97b67d6c9c64308176a631
Author: Guillaume Casal <guillaume.casal.42@gmail.com>
Subject: input: Add FF_TRIGGER_RUMBLE effect type
This commit adds a new FF_TRIGGER_RUMBLE force feedback effect type to support
impulse triggers found on modern gamepads. It introduces the
ff_trigger_rumble_effect structure and adds it to the ff_effect union. This
avoids ABI compatibility issues that could arise from reusing existing structs
with uninitialized tail bytes.
> diff --git a/include/uapi/linux/input.h b/include/uapi/linux/input.h
> index 6aa703fcfcfb7..1d172489f8bc5 100644
> --- a/include/uapi/linux/input.h
> +++ b/include/uapi/linux/input.h
[ ... ]
> @@ -483,6 +497,7 @@ struct ff_effect {
> struct ff_periodic_effect periodic;
> struct ff_condition_effect condition[2]; /* One for each axis */
> struct ff_rumble_effect rumble;
> + struct ff_trigger_rumble_effect trigger_rumble;
> struct ff_haptic_effect haptic;
> } u;
> };
[Severity: High]
This is a pre-existing issue, but could the handling of EVIOCSFF via compat
ioctl lead to a kernel stack memory leak when used with uinput?
When a 32-bit userspace client calls the EVIOCSFF ioctl on an evdev device
backed by a uinput device, evdev_do_ioctl() allocates a 48-byte
struct ff_effect on the kernel stack without initialization:
drivers/input/evdev.c:evdev_do_ioctl() {
struct ff_effect effect;
...
case EVIOC_MASK_SIZE(EVIOCSFF):
if (input_ff_effect_from_user(p, size, &effect))
return -EFAULT;
error = input_ff_upload(dev, &effect, file);
...
}
For compat applications, input_ff_effect_from_user() only copies 44 bytes
(sizeof(struct ff_effect_compat)), leaving the last 4 bytes of the effect
struct uninitialized:
drivers/input/input-compat.c:input_ff_effect_from_user() {
compat_effect = (struct ff_effect_compat *)effect;
if (copy_from_user(compat_effect, buffer,
sizeof(struct ff_effect_compat)))
...
}
If a 64-bit userspace daemon retrieves the force-feedback effect using the
UI_BEGIN_FF_UPLOAD ioctl, uinput_ioctl_handler() copies the full 48-byte
structure back to userspace:
drivers/input/misc/uinput.c:uinput_ioctl_handler() {
ff_up.effect = *req->u.upload.effect;
...
retval = uinput_ff_upload_to_user(p, &ff_up);
...
}
Does this sequence allow the 64-bit uinput daemon to read 4 bytes of
uninitialized kernel stack data?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260730134004.1118476-1-guillaume.casal.42@gmail.com?part=1
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2026-07-30 13:53 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-30 9:53 [PATCH 0/3] input: force feedback for trigger rumble motors Guillaume Casal
2026-07-30 9:53 ` [PATCH 1/3] input: uapi: Add trigger_left and trigger_right to ff_rumble_effect struct Guillaume Casal
2026-07-30 10:04 ` sashiko-bot
2026-07-30 9:53 ` [PATCH 2/3] input: ff-memless: Add trigger left/right in ml_combine_effects Guillaume Casal
2026-07-30 10:24 ` sashiko-bot
2026-07-30 9:53 ` [PATCH 3/3] input: Add FF_TRIGGER_RUMBLE capability bit Guillaume Casal
2026-07-30 10:39 ` sashiko-bot
2026-07-30 13:40 ` [PATCH v2 0/4] input: force feedback for trigger rumble motors Guillaume Casal
2026-07-30 13:40 ` [PATCH v2 1/4] input: Add FF_TRIGGER_RUMBLE effect type Guillaume Casal
2026-07-30 13:53 ` sashiko-bot
2026-07-30 13:40 ` [PATCH v2 2/4] input: ff-memless: Handle FF_TRIGGER_RUMBLE Guillaume Casal
2026-07-30 13:40 ` [PATCH v2 3/4] HID: debug: Add FF_TRIGGER_RUMBLE name Guillaume Casal
2026-07-30 13:40 ` [PATCH v2 4/4] Documentation: input: Document FF_TRIGGER_RUMBLE Guillaume Casal
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.