[PATCH] HID: tmff: Use 64-bit arithmetic for force feedback scaling

From: Linmao Li

Date: Fri Jul 10 2026 - 06:28:15 EST


The logical minimum and maximum values come from the HID report
descriptor and cover the full signed 32-bit range. Subtracting them in
an int can overflow before the force feedback value is scaled. The
subsequent multiplication can overflow as well, producing an incorrect
value despite the final range checks.

Use 64-bit intermediates for both scaling helpers, as done by commit
48d1677779ad ("HID: pidff: Fix integer overflow in pidff_rescale") for
the same arithmetic in the PID driver. This keeps the arithmetic
defined for the complete descriptor range before the result is clamped.

Fixes: dc76c912145f ("Input: use new FF interface in the HID force feedback drivers")
Fixes: b27c9590ca0f ("HID: add support for Thrustmaster FGT Force Feedback wheel")
Signed-off-by: Linmao Li <lilinmao@xxxxxxxxxx>
---
drivers/hid/hid-tmff.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/hid/hid-tmff.c b/drivers/hid/hid-tmff.c
index 423f395d01ac..319e7b670384 100644
--- a/drivers/hid/hid-tmff.c
+++ b/drivers/hid/hid-tmff.c
@@ -17,6 +17,7 @@

#include <linux/hid.h>
#include <linux/input.h>
+#include <linux/math64.h>
#include <linux/slab.h>
#include <linux/module.h>

@@ -47,9 +48,9 @@ struct tmff_device {
/* Changes values from 0 to 0xffff into values from minimum to maximum */
static inline int tmff_scale_u16(unsigned int in, int minimum, int maximum)
{
- int ret;
+ s64 ret;

- ret = (in * (maximum - minimum) / 0xffff) + minimum;
+ ret = div_s64((s64)in * ((s64)maximum - minimum), 0xffff) + minimum;
if (ret < minimum)
return minimum;
if (ret > maximum)
@@ -60,9 +61,9 @@ static inline int tmff_scale_u16(unsigned int in, int minimum, int maximum)
/* Changes values from -0x80 to 0x7f into values from minimum to maximum */
static inline int tmff_scale_s8(int in, int minimum, int maximum)
{
- int ret;
+ s64 ret;

- ret = (((in + 0x80) * (maximum - minimum)) / 0xff) + minimum;
+ ret = div_s64((s64)(in + 0x80) * ((s64)maximum - minimum), 0xff) + minimum;
if (ret < minimum)
return minimum;
if (ret > maximum)
--
2.25.1