summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>2025-02-01 12:38:47 +0100
committerJiri Kosina <jkosina@suse.com>2025-02-03 15:16:56 +0100
commitf538183e997a9fb6087e94e71e372de967b9e56a (patch)
treed3d748749149b5ff086841a4f4314750ef541197
parent8876fc1884f5b39550c8387ff3176396c988541d (diff)
HID: pidff: Clamp PERIODIC effect period to device's logical range
This ensures the effect can actually be played on the connected force feedback device. Adds clamping functions used instead of rescaling, as we don't want to change the characteristics of the periodic effects. Fixes edge cases found on Moza Racing and some other hardware where the effects would not play if the period is outside the defined logical range. Changes in v6: - Use in-kernel clamp macro instead of a custom solution Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com> Reviewed-by: Michał Kopeć <michal@nozomi.space> Reviewed-by: Paul Dino Jones <paul@spacefreak18.xyz> Tested-by: Paul Dino Jones <paul@spacefreak18.xyz> Tested-by: Cristóferson Bueno <cbueno81@gmail.com> Tested-by: Pablo Cisneros <patchkez@protonmail.com> Signed-off-by: Jiri Kosina <jkosina@suse.com>
-rw-r--r--drivers/hid/usbhid/hid-pidff.c19
1 files changed, 16 insertions, 3 deletions
diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
index a01c1b2ab2f4..488e6a6a14a6 100644
--- a/drivers/hid/usbhid/hid-pidff.c
+++ b/drivers/hid/usbhid/hid-pidff.c
@@ -15,10 +15,9 @@
#include <linux/input.h>
#include <linux/slab.h>
#include <linux/usb.h>
-
#include <linux/hid.h>
+#include <linux/minmax.h>
-#include "usbhid.h"
#define PID_EFFECTS_MAX 64
#define PID_INFINITE 0xffff
@@ -188,6 +187,16 @@ struct pidff_device {
};
/*
+ * Clamp value for a given field
+ */
+static s32 pidff_clamp(s32 i, struct hid_field *field)
+{
+ s32 clamped = clamp(i, field->logical_minimum, field->logical_maximum);
+ pr_debug("clamped from %d to %d", i, clamped);
+ return clamped;
+}
+
+/*
* Scale an unsigned value with range 0..max for the given field
*/
static int pidff_rescale(int i, int max, struct hid_field *field)
@@ -361,7 +370,11 @@ static void pidff_set_periodic_report(struct pidff_device *pidff,
pidff_set_signed(&pidff->set_periodic[PID_OFFSET],
effect->u.periodic.offset);
pidff_set(&pidff->set_periodic[PID_PHASE], effect->u.periodic.phase);
- pidff->set_periodic[PID_PERIOD].value[0] = effect->u.periodic.period;
+
+ /* Clamp period to ensure the device can play the effect */
+ pidff->set_periodic[PID_PERIOD].value[0] =
+ pidff_clamp(effect->u.periodic.period,
+ pidff->set_periodic[PID_PERIOD].field);
hid_hw_request(pidff->hid, pidff->reports[PID_SET_PERIODIC],
HID_REQ_SET_REPORT);