From 465ce84d2997e5af6630b88d88b63509d5a88031 Mon Sep 17 00:00:00 2001 From: Kai Krakow Date: Sat, 8 Aug 2026 12:27:06 +0200 Subject: avoid signed overflow when scaling gain + FF_GAIN and the driver gain both use the full 16-bit range. Their product can exceed INT_MAX. Signed overflow is undefined and happens for common settings such as 75 percent times 75 percent. Use a u32 intermediate for the scaling operation. + Pass the configured gain directly when initializing or updating the hardware. This also removes two redundant multiply-divide expressions which could overflow before cancelling out. --- src/hid-tmff2.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/hid-tmff2.c b/src/hid-tmff2.c index 9cf07b9..02e70f1 100644 --- a/src/hid-tmff2.c +++ b/src/hid-tmff2.c @@ -48,6 +48,11 @@ module_param(gain, ushort, 0); MODULE_PARM_DESC(gain, "Level of gain (0-65535)"); +static u16 tmff2_scale_gain(u16 value) +{ + return (u32)value * gain / GAIN_MAX; +} + static spinlock_t lock; static struct tmff2_device_entry *tmff2_from_hdev(struct hid_device *hdev) @@ -244,7 +249,7 @@ static ssize_t gain_store(struct device *dev, gain = value; if (tmff2->set_gain) /* if we can, update gain immediately */ - tmff2->set_gain(tmff2->data, (GAIN_MAX * gain) / GAIN_MAX); + tmff2->set_gain(tmff2->data, gain); return count; } @@ -268,7 +273,7 @@ static void tmff2_set_gain(struct input_dev *dev, uint16_t value) return; } - if (tmff2->set_gain(tmff2->data, (value * gain) / GAIN_MAX)) + if (tmff2->set_gain(tmff2->data, tmff2_scale_gain(value))) hid_warn(tmff2->hdev, "unable to set gain\n"); } @@ -644,7 +649,7 @@ static int tmff2_wheel_init(struct tmff2_device_entry *tmff2) /* set defaults wherever possible */ if (tmff2->set_gain) { ff->set_gain = tmff2_set_gain; - tmff2->set_gain(tmff2->data, (GAIN_MAX * gain) / GAIN_MAX); + tmff2->set_gain(tmff2->data, gain); } if (tmff2->set_autocenter) -- cgit v1.3