]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 6.13
authorSasha Levin <sashal@kernel.org>
Wed, 16 Apr 2025 16:38:29 +0000 (12:38 -0400)
committerSasha Levin <sashal@kernel.org>
Wed, 16 Apr 2025 16:38:29 +0000 (12:38 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
22 files changed:
queue-6.13/hid-hid-universal-pidff-add-asetek-wheelbases-suppor.patch [new file with mode: 0644]
queue-6.13/hid-pidff-clamp-effect-playback-loop_count-value.patch [new file with mode: 0644]
queue-6.13/hid-pidff-clamp-periodic-effect-period-to-device-s-l.patch [new file with mode: 0644]
queue-6.13/hid-pidff-comment-and-code-style-update.patch [new file with mode: 0644]
queue-6.13/hid-pidff-completely-rework-and-fix-pidff_reset-func.patch [new file with mode: 0644]
queue-6.13/hid-pidff-compute-infinite-value-instead-of-using-ha.patch [new file with mode: 0644]
queue-6.13/hid-pidff-define-values-used-in-pidff_find_special_f.patch [new file with mode: 0644]
queue-6.13/hid-pidff-factor-out-code-for-setting-gain.patch [new file with mode: 0644]
queue-6.13/hid-pidff-factor-out-pool-report-fetch-and-remove-ex.patch [new file with mode: 0644]
queue-6.13/hid-pidff-fix-90-degrees-direction-name-north-east.patch [new file with mode: 0644]
queue-6.13/hid-pidff-fix-set_device_control.patch [new file with mode: 0644]
queue-6.13/hid-pidff-make-sure-to-fetch-pool-before-checking-si.patch [new file with mode: 0644]
queue-6.13/hid-pidff-move-all-hid-pidff-definitions-to-a-dedica.patch [new file with mode: 0644]
queue-6.13/hid-pidff-remove-redundant-call-to-pidff_find_specia.patch [new file with mode: 0644]
queue-6.13/hid-pidff-rename-two-functions-to-align-them-with-na.patch [new file with mode: 0644]
queue-6.13/hid-pidff-rescale-time-values-to-match-field-units.patch [new file with mode: 0644]
queue-6.13/hid-pidff-simplify-pidff_rescale_signed.patch [new file with mode: 0644]
queue-6.13/hid-pidff-simplify-pidff_upload_effect-function.patch [new file with mode: 0644]
queue-6.13/hid-pidff-stop-all-effects-before-enabling-actuators.patch [new file with mode: 0644]
queue-6.13/hid-pidff-support-device-error-response-from-pid_blo.patch [new file with mode: 0644]
queue-6.13/hid-pidff-use-macros-instead-of-hardcoded-min-max-va.patch [new file with mode: 0644]
queue-6.13/series

diff --git a/queue-6.13/hid-hid-universal-pidff-add-asetek-wheelbases-suppor.patch b/queue-6.13/hid-hid-universal-pidff-add-asetek-wheelbases-suppor.patch
new file mode 100644 (file)
index 0000000..951bcc2
--- /dev/null
@@ -0,0 +1,92 @@
+From 0a0b38afee0e82901b62c98c5510aca5d79b2d0c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 11 Feb 2025 15:35:09 +0100
+Subject: HID: hid-universal-pidff: Add Asetek wheelbases support
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+
+[ Upstream commit c385f61108d403633e8cfbdae15b35ccf7cee686 ]
+
+Adds Asetek vendor id and product ids for:
+- Invicta
+- Forte
+- La Prima
+- Tony Kanaan
+
+v2:
+- Misc spelling fix in driver loaded info
+
+v3:
+- Chanage Oleg's name order
+
+Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/hid-ids.h             |  6 ++++++
+ drivers/hid/hid-universal-pidff.c | 10 +++++++---
+ 2 files changed, 13 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
+index e1e002df64de2..db88831633466 100644
+--- a/drivers/hid/hid-ids.h
++++ b/drivers/hid/hid-ids.h
+@@ -190,6 +190,12 @@
+ #define USB_DEVICE_ID_APPLE_TOUCHBAR_BACKLIGHT 0x8102
+ #define USB_DEVICE_ID_APPLE_TOUCHBAR_DISPLAY 0x8302
++#define USB_VENDOR_ID_ASETEK                  0x2433
++#define USB_DEVICE_ID_ASETEK_INVICTA          0xf300
++#define USB_DEVICE_ID_ASETEK_FORTE            0xf301
++#define USB_DEVICE_ID_ASETEK_LA_PRIMA         0xf303
++#define USB_DEVICE_ID_ASETEK_TONY_KANAAN      0xf306
++
+ #define USB_VENDOR_ID_ASUS            0x0486
+ #define USB_DEVICE_ID_ASUS_T91MT      0x0185
+ #define USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO  0x0186
+diff --git a/drivers/hid/hid-universal-pidff.c b/drivers/hid/hid-universal-pidff.c
+index 1b713b741d192..5b89ec7b5c26c 100644
+--- a/drivers/hid/hid-universal-pidff.c
++++ b/drivers/hid/hid-universal-pidff.c
+@@ -4,7 +4,7 @@
+  * hid-pidff wrapper for PID-enabled devices
+  * Handles device reports, quirks and extends usable button range
+  *
+- * Copyright (c) 2024, 2025 Makarenko Oleg
++ * Copyright (c) 2024, 2025 Oleg Makarenko
+  * Copyright (c) 2024, 2025 Tomasz Pakuła
+  */
+@@ -104,7 +104,7 @@ static int universal_pidff_probe(struct hid_device *hdev,
+               goto err;
+       }
+-      hid_info(hdev, "Universal pidff driver loaded sucesfully!");
++      hid_info(hdev, "Universal pidff driver loaded sucessfully!");
+       return 0;
+ err:
+@@ -179,6 +179,10 @@ static const struct hid_device_id universal_pidff_devices[] = {
+               .driver_data = HID_PIDFF_QUIRK_PERIODIC_SINE_ONLY },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_LITE_STAR_GT987_FF),
+               .driver_data = HID_PIDFF_QUIRK_PERIODIC_SINE_ONLY },
++      { HID_USB_DEVICE(USB_VENDOR_ID_ASETEK, USB_DEVICE_ID_ASETEK_INVICTA) },
++      { HID_USB_DEVICE(USB_VENDOR_ID_ASETEK, USB_DEVICE_ID_ASETEK_FORTE) },
++      { HID_USB_DEVICE(USB_VENDOR_ID_ASETEK, USB_DEVICE_ID_ASETEK_LA_PRIMA) },
++      { HID_USB_DEVICE(USB_VENDOR_ID_ASETEK, USB_DEVICE_ID_ASETEK_TONY_KANAAN) },
+       { }
+ };
+ MODULE_DEVICE_TABLE(hid, universal_pidff_devices);
+@@ -194,5 +198,5 @@ module_hid_driver(universal_pidff);
+ MODULE_DESCRIPTION("Universal driver for USB PID Force Feedback devices");
+ MODULE_LICENSE("GPL");
+-MODULE_AUTHOR("Makarenko Oleg <oleg@makarenk.ooo>");
++MODULE_AUTHOR("Oleg Makarenko <oleg@makarenk.ooo>");
+ MODULE_AUTHOR("Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>");
+-- 
+2.39.5
+
diff --git a/queue-6.13/hid-pidff-clamp-effect-playback-loop_count-value.patch b/queue-6.13/hid-pidff-clamp-effect-playback-loop_count-value.patch
new file mode 100644 (file)
index 0000000..3dcab87
--- /dev/null
@@ -0,0 +1,42 @@
+From 18c55e3e5b2c33a02da7b212a4c2976409f8e90c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Feb 2025 23:30:01 +0100
+Subject: HID: pidff: Clamp effect playback LOOP_COUNT value
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+
+[ Upstream commit 0c6673e3d17b258b8c5c7331d28bf6c49f25ed30 ]
+
+Ensures the loop count will never exceed the logical_maximum.
+
+Fixes implementation errors happening when applications use the max
+value of int32/DWORD as the effect iterations. This could be observed
+when running software both native and in wine.
+
+Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/usbhid/hid-pidff.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
+index ffecc712be003..74b033a4ac1b8 100644
+--- a/drivers/hid/usbhid/hid-pidff.c
++++ b/drivers/hid/usbhid/hid-pidff.c
+@@ -690,7 +690,8 @@ static void pidff_playback_pid(struct pidff_device *pidff, int pid_id, int n)
+       } else {
+               pidff->effect_operation_status->value[0] =
+                       pidff->operation_id[PID_EFFECT_START];
+-              pidff->effect_operation[PID_LOOP_COUNT].value[0] = n;
++              pidff->effect_operation[PID_LOOP_COUNT].value[0] =
++                      pidff_clamp(n, pidff->effect_operation[PID_LOOP_COUNT].field);
+       }
+       hid_hw_request(pidff->hid, pidff->reports[PID_EFFECT_OPERATION],
+-- 
+2.39.5
+
diff --git a/queue-6.13/hid-pidff-clamp-periodic-effect-period-to-device-s-l.patch b/queue-6.13/hid-pidff-clamp-periodic-effect-period-to-device-s-l.patch
new file mode 100644 (file)
index 0000000..22c0238
--- /dev/null
@@ -0,0 +1,84 @@
+From 302108835bbf1426dc34238367aa6867b9364e7f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 1 Feb 2025 12:38:47 +0100
+Subject: HID: pidff: Clamp PERIODIC effect period to device's logical range
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+
+[ Upstream commit f538183e997a9fb6087e94e71e372de967b9e56a ]
+
+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>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/usbhid/hid-pidff.c | 19 ++++++++++++++++---
+ 1 file changed, 16 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
+index 25dbed076f530..6b55345ce75ac 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
+@@ -192,6 +191,16 @@ struct pidff_device {
+       u32 quirks;
+ };
++/*
++ * 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
+  */
+@@ -372,7 +381,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);
+-- 
+2.39.5
+
diff --git a/queue-6.13/hid-pidff-comment-and-code-style-update.patch b/queue-6.13/hid-pidff-comment-and-code-style-update.patch
new file mode 100644 (file)
index 0000000..564d90d
--- /dev/null
@@ -0,0 +1,193 @@
+From 18fb9bbc8cd16f86addce464172b451415e2fa2e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 11 Feb 2025 15:35:10 +0100
+Subject: HID: pidff: Comment and code style update
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+
+[ Upstream commit e19675c2477491401b236ed939ad5a43ddc339af ]
+
+Update comments to fully conform to the Linux comment styling.
+Define Linux infinite effect duration (0) as FF_INFINITE
+
+Chanage Oleg's name order
+
+Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/usbhid/hid-pidff.c | 57 +++++++++++++++-------------------
+ 1 file changed, 25 insertions(+), 32 deletions(-)
+
+diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
+index 503f643b59cad..e2508a4d754d3 100644
+--- a/drivers/hid/usbhid/hid-pidff.c
++++ b/drivers/hid/usbhid/hid-pidff.c
+@@ -3,13 +3,9 @@
+  *  Force feedback driver for USB HID PID compliant devices
+  *
+  *  Copyright (c) 2005, 2006 Anssi Hannula <anssi.hannula@gmail.com>
++ *  Upgraded 2025 by Oleg Makarenko and Tomasz Pakuła
+  */
+-/*
+- */
+-
+-/* #define DEBUG */
+-
+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+ #include "hid-pidff.h"
+@@ -25,9 +21,9 @@
+ /* Linux Force Feedback API uses miliseconds as time unit */
+ #define FF_TIME_EXPONENT      -3
++#define FF_INFINITE           0
+ /* Report usage table used to put reports into an array */
+-
+ #define PID_SET_EFFECT                0
+ #define PID_EFFECT_OPERATION  1
+ #define PID_DEVICE_GAIN               2
+@@ -48,12 +44,12 @@ static const u8 pidff_reports[] = {
+       0x21, 0x77, 0x7d, 0x7f, 0x89, 0x90, 0x96, 0xab,
+       0x5a, 0x5f, 0x6e, 0x73, 0x74
+ };
+-
+-/* device_control is really 0x95, but 0x96 specified as it is the usage of
+-the only field in that report */
++/*
++ * device_control is really 0x95, but 0x96 specified
++ * as it is the usage of the only field in that report.
++ */
+ /* PID special fields */
+-
+ #define PID_EFFECT_TYPE                       0x25
+ #define PID_DIRECTION                 0x57
+ #define PID_EFFECT_OPERATION_ARRAY    0x78
+@@ -61,7 +57,6 @@ the only field in that report */
+ #define PID_DEVICE_CONTROL_ARRAY      0x96
+ /* Value usage tables used to put fields and values into arrays */
+-
+ #define PID_EFFECT_BLOCK_INDEX        0
+ #define PID_DURATION          1
+@@ -119,7 +114,6 @@ static const u8 pidff_device_gain[] = { 0x7e };
+ static const u8 pidff_pool[] = { 0x80, 0x83, 0xa9 };
+ /* Special field key tables used to put special field keys into arrays */
+-
+ #define PID_ENABLE_ACTUATORS  0
+ #define PID_DISABLE_ACTUATORS 1
+ #define PID_STOP_ALL_EFFECTS  2
+@@ -176,8 +170,10 @@ struct pidff_device {
+       struct pidff_usage effect_operation[sizeof(pidff_effect_operation)];
+       struct pidff_usage block_free[sizeof(pidff_block_free)];
+-      /* Special field is a field that is not composed of
+-         usage<->value pairs that pidff_usage values are */
++      /*
++       * Special field is a field that is not composed of
++       * usage<->value pairs that pidff_usage values are
++       */
+       /* Special field in create_new_effect */
+       struct hid_field *create_new_effect_type;
+@@ -222,7 +218,7 @@ static s32 pidff_clamp(s32 i, struct hid_field *field)
+ static int pidff_rescale(int i, int max, struct hid_field *field)
+ {
+       return i * (field->logical_maximum - field->logical_minimum) / max +
+-          field->logical_minimum;
++              field->logical_minimum;
+ }
+ /*
+@@ -282,9 +278,8 @@ static void pidff_set_time(struct pidff_usage *usage, u16 time)
+ static void pidff_set_duration(struct pidff_usage *usage, u16 duration)
+ {
+-      /* Convert infinite length from Linux API (0)
+-         to PID standard (NULL) if needed */
+-      if (duration == 0)
++      /* Infinite value conversion from Linux API -> PID */
++      if (duration == FF_INFINITE)
+               duration = PID_INFINITE;
+       if (duration == PID_INFINITE) {
+@@ -302,16 +297,16 @@ static void pidff_set_envelope_report(struct pidff_device *pidff,
+                                     struct ff_envelope *envelope)
+ {
+       pidff->set_envelope[PID_EFFECT_BLOCK_INDEX].value[0] =
+-          pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0];
++              pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0];
+       pidff->set_envelope[PID_ATTACK_LEVEL].value[0] =
+-          pidff_rescale(envelope->attack_level >
+-                        S16_MAX ? S16_MAX : envelope->attack_level, S16_MAX,
+-                        pidff->set_envelope[PID_ATTACK_LEVEL].field);
++              pidff_rescale(envelope->attack_level >
++                      S16_MAX ? S16_MAX : envelope->attack_level, S16_MAX,
++                      pidff->set_envelope[PID_ATTACK_LEVEL].field);
+       pidff->set_envelope[PID_FADE_LEVEL].value[0] =
+-          pidff_rescale(envelope->fade_level >
+-                        S16_MAX ? S16_MAX : envelope->fade_level, S16_MAX,
+-                        pidff->set_envelope[PID_FADE_LEVEL].field);
++              pidff_rescale(envelope->fade_level >
++                      S16_MAX ? S16_MAX : envelope->fade_level, S16_MAX,
++                      pidff->set_envelope[PID_FADE_LEVEL].field);
+       pidff_set_time(&pidff->set_envelope[PID_ATTACK_TIME],
+                       envelope->attack_length);
+@@ -702,9 +697,7 @@ static void pidff_playback_pid(struct pidff_device *pidff, int pid_id, int n)
+ static int pidff_playback(struct input_dev *dev, int effect_id, int value)
+ {
+       struct pidff_device *pidff = dev->ff->private;
+-
+       pidff_playback_pid(pidff, pidff->pid_id[effect_id], value);
+-
+       return 0;
+ }
+@@ -732,8 +725,11 @@ static int pidff_erase_effect(struct input_dev *dev, int effect_id)
+       hid_dbg(pidff->hid, "starting to erase %d/%d\n",
+               effect_id, pidff->pid_id[effect_id]);
+-      /* Wait for the queue to clear. We do not want a full fifo to
+-         prevent the effect removal. */
++
++      /*
++       * Wait for the queue to clear. We do not want
++       * a full fifo to prevent the effect removal.
++       */
+       hid_hw_wait(pidff->hid);
+       pidff_playback_pid(pidff, pid_id, 0);
+       pidff_erase_pid(pidff, pid_id);
+@@ -1239,7 +1235,6 @@ static int pidff_find_effects(struct pidff_device *pidff,
+               set_bit(FF_FRICTION, dev->ffbit);
+       return 0;
+-
+ }
+ #define PIDFF_FIND_FIELDS(name, report, strict) \
+@@ -1370,12 +1365,10 @@ static int pidff_check_autocenter(struct pidff_device *pidff,
+               hid_notice(pidff->hid,
+                          "device has unknown autocenter control method\n");
+       }
+-
+       pidff_erase_pid(pidff,
+                       pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]);
+       return 0;
+-
+ }
+ /*
+-- 
+2.39.5
+
diff --git a/queue-6.13/hid-pidff-completely-rework-and-fix-pidff_reset-func.patch b/queue-6.13/hid-pidff-completely-rework-and-fix-pidff_reset-func.patch
new file mode 100644 (file)
index 0000000..61a616a
--- /dev/null
@@ -0,0 +1,259 @@
+From c3a3eb88636b587ca89edfa209e5d19c7ec6b14b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 1 Feb 2025 12:38:57 +0100
+Subject: HID: pidff: Completely rework and fix pidff_reset function
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+
+[ Upstream commit cb3fd788e3fa5358602a49809c4eb4911539c9d0 ]
+
+Previously, it was assumed that DEVICE_CONTROL usage is always an array
+but a lot of devices implements it as a bitmask variable. This led to
+the pidff_reset function not working and causing errors in such cases.
+
+Selectors can come in three types. One selection of a set, N selections
+and Any selection in form of bitmask as from USB Hid Usage Tables v1.5,
+subsection 3.4.2.1
+
+Added pidff_send_device_control which handles usage flag check which
+decides whether DEVICE_CONTROL should be handled as "One selection of a
+set" or "Any selection of a set".
+
+Reset was triggered once, on device initialization. Now, it's triggered
+every time when uploading an effect to an empty device (no currently
+stored effects), tracked by pidff->effect_count variable.
+
+Co-developed-by: Makarenko Oleg <oleg@makarenk.ooo>
+Signed-off-by: Makarenko Oleg <oleg@makarenk.ooo>
+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>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/usbhid/hid-pidff.c | 138 +++++++++++++++++++++------------
+ 1 file changed, 89 insertions(+), 49 deletions(-)
+
+diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
+index 635596a57c75d..99b5d3deb40d0 100644
+--- a/drivers/hid/usbhid/hid-pidff.c
++++ b/drivers/hid/usbhid/hid-pidff.c
+@@ -109,9 +109,10 @@ static const u8 pidff_pool[] = { 0x80, 0x83, 0xa9 };
+ /* Special field key tables used to put special field keys into arrays */
+ #define PID_ENABLE_ACTUATORS  0
+-#define PID_STOP_ALL_EFFECTS  1
+-#define PID_RESET             2
+-static const u8 pidff_device_control[] = { 0x97, 0x99, 0x9a };
++#define PID_DISABLE_ACTUATORS 1
++#define PID_STOP_ALL_EFFECTS  2
++#define PID_RESET             3
++static const u8 pidff_device_control[] = { 0x97, 0x98, 0x99, 0x9a };
+ #define PID_CONSTANT  0
+ #define PID_RAMP      1
+@@ -190,6 +191,7 @@ struct pidff_device {
+       int pid_id[PID_EFFECTS_MAX];
+       u32 quirks;
++      u8 effect_count;
+ };
+ /*
+@@ -490,9 +492,83 @@ static int pidff_needs_set_ramp(struct ff_effect *effect, struct ff_effect *old)
+              effect->u.ramp.end_level != old->u.ramp.end_level;
+ }
++/*
++ * Clear device control report
++ */
++static void pidff_send_device_control(struct pidff_device *pidff, int field)
++{
++      int i, tmp;
++      int field_index = pidff->control_id[field];
++
++      /* Detect if the field is a bitmask variable or an array */
++      if (pidff->device_control->flags & HID_MAIN_ITEM_VARIABLE) {
++              hid_dbg(pidff->hid, "DEVICE_CONTROL is a bitmask\n");
++              /* Clear current bitmask */
++              for(i = 0; i < sizeof(pidff_device_control); i++) {
++                      tmp = pidff->control_id[i];
++                      pidff->device_control->value[tmp] = 0;
++              }
++              pidff->device_control->value[field_index - 1] = 1;
++      } else {
++              hid_dbg(pidff->hid, "DEVICE_CONTROL is an array\n");
++              pidff->device_control->value[0] = field_index;
++      }
++
++      hid_hw_request(pidff->hid, pidff->reports[PID_DEVICE_CONTROL], HID_REQ_SET_REPORT);
++      hid_hw_wait(pidff->hid);
++}
++
++/*
++ * Modify actuators state
++ */
++static void pidff_modify_actuators_state(struct pidff_device *pidff, bool enable)
++{
++      hid_dbg(pidff->hid, "%s actuators\n", enable ? "Enable" : "Disable");
++      pidff_send_device_control(pidff,
++              enable ? PID_ENABLE_ACTUATORS : PID_DISABLE_ACTUATORS);
++}
++
++/*
++ * Reset the device, stop all effects, enable actuators
++ * Refetch pool report
++ */
++static void pidff_reset(struct pidff_device *pidff)
++{
++      int i = 0;
++
++      /* We reset twice as sometimes hid_wait_io isn't waiting long enough */
++      pidff_send_device_control(pidff, PID_RESET);
++      pidff_send_device_control(pidff, PID_RESET);
++      pidff->effect_count = 0;
++
++      pidff_send_device_control(pidff, PID_STOP_ALL_EFFECTS);
++      pidff_modify_actuators_state(pidff, 1);
++
++      /* pool report is sometimes messed up, refetch it */
++      hid_hw_request(pidff->hid, pidff->reports[PID_POOL], HID_REQ_GET_REPORT);
++      hid_hw_wait(pidff->hid);
++
++      if (pidff->pool[PID_SIMULTANEOUS_MAX].value) {
++              while (pidff->pool[PID_SIMULTANEOUS_MAX].value[0] < 2) {
++                      if (i++ > 20) {
++                              hid_warn(pidff->hid,
++                                       "device reports %d simultaneous effects\n",
++                                       pidff->pool[PID_SIMULTANEOUS_MAX].value[0]);
++                              break;
++                      }
++                      hid_dbg(pidff->hid, "pid_pool requested again\n");
++                      hid_hw_request(pidff->hid, pidff->reports[PID_POOL],
++                                        HID_REQ_GET_REPORT);
++                      hid_hw_wait(pidff->hid);
++              }
++      }
++}
++
+ /*
+  * Send a request for effect upload to the device
+  *
++ * Reset and enable actuators if no effects were present on the device
++ *
+  * Returns 0 if device reported success, -ENOSPC if the device reported memory
+  * is full. Upon unknown response the function will retry for 60 times, if
+  * still unsuccessful -EIO is returned.
+@@ -501,6 +577,9 @@ static int pidff_request_effect_upload(struct pidff_device *pidff, int efnum)
+ {
+       int j;
++      if (!pidff->effect_count)
++              pidff_reset(pidff);
++
+       pidff->create_new_effect_type->value[0] = efnum;
+       hid_hw_request(pidff->hid, pidff->reports[PID_CREATE_NEW_EFFECT],
+                       HID_REQ_SET_REPORT);
+@@ -520,6 +599,8 @@ static int pidff_request_effect_upload(struct pidff_device *pidff, int efnum)
+                       hid_dbg(pidff->hid, "device reported free memory: %d bytes\n",
+                                pidff->block_load[PID_RAM_POOL_AVAILABLE].value ?
+                                pidff->block_load[PID_RAM_POOL_AVAILABLE].value[0] : -1);
++
++                      pidff->effect_count++;
+                       return 0;
+               }
+               if (pidff->block_load_status->value[0] ==
+@@ -568,12 +649,16 @@ static int pidff_playback(struct input_dev *dev, int effect_id, int value)
+ /*
+  * Erase effect with PID id
++ * Decrease the device effect counter
+  */
+ static void pidff_erase_pid(struct pidff_device *pidff, int pid_id)
+ {
+       pidff->block_free[PID_EFFECT_BLOCK_INDEX].value[0] = pid_id;
+       hid_hw_request(pidff->hid, pidff->reports[PID_BLOCK_FREE],
+                       HID_REQ_SET_REPORT);
++
++      if (pidff->effect_count > 0)
++              pidff->effect_count--;
+ }
+ /*
+@@ -1221,50 +1306,6 @@ static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev)
+       return 0;
+ }
+-/*
+- * Reset the device
+- */
+-static void pidff_reset(struct pidff_device *pidff)
+-{
+-      struct hid_device *hid = pidff->hid;
+-      int i = 0;
+-
+-      pidff->device_control->value[0] = pidff->control_id[PID_RESET];
+-      /* We reset twice as sometimes hid_wait_io isn't waiting long enough */
+-      hid_hw_request(hid, pidff->reports[PID_DEVICE_CONTROL], HID_REQ_SET_REPORT);
+-      hid_hw_wait(hid);
+-      hid_hw_request(hid, pidff->reports[PID_DEVICE_CONTROL], HID_REQ_SET_REPORT);
+-      hid_hw_wait(hid);
+-
+-      pidff->device_control->value[0] = pidff->control_id[PID_STOP_ALL_EFFECTS];
+-      hid_hw_request(hid, pidff->reports[PID_DEVICE_CONTROL], HID_REQ_SET_REPORT);
+-      hid_hw_wait(hid);
+-
+-      pidff->device_control->value[0] =
+-              pidff->control_id[PID_ENABLE_ACTUATORS];
+-      hid_hw_request(hid, pidff->reports[PID_DEVICE_CONTROL], HID_REQ_SET_REPORT);
+-      hid_hw_wait(hid);
+-
+-      /* pool report is sometimes messed up, refetch it */
+-      hid_hw_request(hid, pidff->reports[PID_POOL], HID_REQ_GET_REPORT);
+-      hid_hw_wait(hid);
+-
+-      if (pidff->pool[PID_SIMULTANEOUS_MAX].value) {
+-              while (pidff->pool[PID_SIMULTANEOUS_MAX].value[0] < 2) {
+-                      if (i++ > 20) {
+-                              hid_warn(pidff->hid,
+-                                       "device reports %d simultaneous effects\n",
+-                                       pidff->pool[PID_SIMULTANEOUS_MAX].value[0]);
+-                              break;
+-                      }
+-                      hid_dbg(pidff->hid, "pid_pool requested again\n");
+-                      hid_hw_request(hid, pidff->reports[PID_POOL],
+-                                        HID_REQ_GET_REPORT);
+-                      hid_hw_wait(hid);
+-              }
+-      }
+-}
+-
+ /*
+  * Test if autocenter modification is using the supported method
+  */
+@@ -1330,6 +1371,7 @@ int hid_pidff_init_with_quirks(struct hid_device *hid, __u32 initial_quirks)
+       pidff->hid = hid;
+       pidff->quirks = initial_quirks;
++      pidff->effect_count = 0;
+       hid_device_io_start(hid);
+@@ -1346,8 +1388,6 @@ int hid_pidff_init_with_quirks(struct hid_device *hid, __u32 initial_quirks)
+       if (error)
+               goto fail;
+-      pidff_reset(pidff);
+-
+       if (test_bit(FF_GAIN, dev->ffbit)) {
+               pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], 0xffff);
+               hid_hw_request(hid, pidff->reports[PID_DEVICE_GAIN],
+-- 
+2.39.5
+
diff --git a/queue-6.13/hid-pidff-compute-infinite-value-instead-of-using-ha.patch b/queue-6.13/hid-pidff-compute-infinite-value-instead-of-using-ha.patch
new file mode 100644 (file)
index 0000000..8849343
--- /dev/null
@@ -0,0 +1,45 @@
+From 7cd7fbc41bfea5e4f94a4e0a233bc46c0f66e151 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Feb 2025 23:30:02 +0100
+Subject: HID: pidff: Compute INFINITE value instead of using hardcoded 0xffff
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+
+[ Upstream commit 1a575044d516972a1d036d54c0180b9085e21dc6 ]
+
+As per USB PID standard:
+INFINITE - Referrers to the maximum value of a range. i.e. if in an 8
+bit unsigned field the value of 255 would indicate INFINITE.
+
+Detecting 0xffff (U16_MAX) is still important as we MIGHT get this value
+as infinite from some native software as 0 was never actually defined
+in Linux' FF api as the infinite value. I'm working on it though.
+
+Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/usbhid/hid-pidff.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
+index 74b033a4ac1b8..a614438e43bd8 100644
+--- a/drivers/hid/usbhid/hid-pidff.c
++++ b/drivers/hid/usbhid/hid-pidff.c
+@@ -283,8 +283,9 @@ static void pidff_set_duration(struct pidff_usage *usage, u16 duration)
+       if (duration == FF_INFINITE)
+               duration = PID_INFINITE;
++      /* PID defines INFINITE as the max possible value for duration field */
+       if (duration == PID_INFINITE) {
+-              usage->value[0] = PID_INFINITE;
++              usage->value[0] = (1U << usage->field->report_size) - 1;
+               return;
+       }
+-- 
+2.39.5
+
diff --git a/queue-6.13/hid-pidff-define-values-used-in-pidff_find_special_f.patch b/queue-6.13/hid-pidff-define-values-used-in-pidff_find_special_f.patch
new file mode 100644 (file)
index 0000000..e285697
--- /dev/null
@@ -0,0 +1,79 @@
+From 2ff0ff4d3df8e2b26d32cd4ee5761c22f0369f26 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 1 Feb 2025 12:38:59 +0100
+Subject: HID: pidff: Define values used in pidff_find_special_fields
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+
+[ Upstream commit 1c12f136891cf4d2d4e6aa202d671a9d2171a716 ]
+
+Makes it clear where did these values came from
+
+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>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/usbhid/hid-pidff.c | 21 +++++++++++++++------
+ 1 file changed, 15 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
+index 42c951a1d65bf..bd913d57e4d75 100644
+--- a/drivers/hid/usbhid/hid-pidff.c
++++ b/drivers/hid/usbhid/hid-pidff.c
+@@ -48,6 +48,14 @@ static const u8 pidff_reports[] = {
+ /* device_control is really 0x95, but 0x96 specified as it is the usage of
+ the only field in that report */
++/* PID special fields */
++
++#define PID_EFFECT_TYPE                       0x25
++#define PID_DIRECTION                 0x57
++#define PID_EFFECT_OPERATION_ARRAY    0x78
++#define PID_BLOCK_LOAD_STATUS         0x8b
++#define PID_DEVICE_CONTROL_ARRAY      0x96
++
+ /* Value usage tables used to put fields and values into arrays */
+ #define PID_EFFECT_BLOCK_INDEX        0
+@@ -1056,23 +1064,24 @@ static int pidff_find_special_fields(struct pidff_device *pidff)
+       pidff->create_new_effect_type =
+               pidff_find_special_field(pidff->reports[PID_CREATE_NEW_EFFECT],
+-                                       0x25, 1);
++                                       PID_EFFECT_TYPE, 1);
+       pidff->set_effect_type =
+               pidff_find_special_field(pidff->reports[PID_SET_EFFECT],
+-                                       0x25, 1);
++                                       PID_EFFECT_TYPE, 1);
+       pidff->effect_direction =
+               pidff_find_special_field(pidff->reports[PID_SET_EFFECT],
+-                                       0x57, 0);
++                                       PID_DIRECTION, 0);
+       pidff->device_control =
+               pidff_find_special_field(pidff->reports[PID_DEVICE_CONTROL],
+-                      0x96, !(pidff->quirks & HID_PIDFF_QUIRK_PERMISSIVE_CONTROL));
++                      PID_DEVICE_CONTROL_ARRAY,
++                      !(pidff->quirks & HID_PIDFF_QUIRK_PERMISSIVE_CONTROL));
+       pidff->block_load_status =
+               pidff_find_special_field(pidff->reports[PID_BLOCK_LOAD],
+-                                       0x8b, 1);
++                                       PID_BLOCK_LOAD_STATUS, 1);
+       pidff->effect_operation_status =
+               pidff_find_special_field(pidff->reports[PID_EFFECT_OPERATION],
+-                                       0x78, 1);
++                                       PID_EFFECT_OPERATION_ARRAY, 1);
+       hid_dbg(pidff->hid, "search done\n");
+-- 
+2.39.5
+
diff --git a/queue-6.13/hid-pidff-factor-out-code-for-setting-gain.patch b/queue-6.13/hid-pidff-factor-out-code-for-setting-gain.patch
new file mode 100644 (file)
index 0000000..8420164
--- /dev/null
@@ -0,0 +1,83 @@
+From 159ce5f3d0e9462a48955532fbf2352cd6fa377e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 1 Feb 2025 12:39:01 +0100
+Subject: HID: pidff: Factor out code for setting gain
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+
+[ Upstream commit f7ebf0b11b9e04bf59c438ad14f0115b12aa2f44 ]
+
+Makes it possible to easily set gain from inside hid-pidff.c
+
+Changes in v7:
+- Check if device gain field exists before setting device gain
+
+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>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/usbhid/hid-pidff.c | 26 +++++++++++++++-----------
+ 1 file changed, 15 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
+index 180b2cf66e4c7..ac6f940abd901 100644
+--- a/drivers/hid/usbhid/hid-pidff.c
++++ b/drivers/hid/usbhid/hid-pidff.c
+@@ -539,6 +539,19 @@ static int pidff_needs_set_ramp(struct ff_effect *effect, struct ff_effect *old)
+              effect->u.ramp.end_level != old->u.ramp.end_level;
+ }
++/*
++ * Set device gain
++ */
++static void pidff_set_gain_report(struct pidff_device *pidff, u16 gain)
++{
++      if (!pidff->device_gain[PID_DEVICE_GAIN_FIELD].field)
++              return;
++
++      pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], gain);
++      hid_hw_request(pidff->hid, pidff->reports[PID_DEVICE_GAIN],
++                      HID_REQ_SET_REPORT);
++}
++
+ /*
+  * Clear device control report
+  */
+@@ -865,11 +878,7 @@ static int pidff_upload_effect(struct input_dev *dev, struct ff_effect *effect,
+  */
+ static void pidff_set_gain(struct input_dev *dev, u16 gain)
+ {
+-      struct pidff_device *pidff = dev->ff->private;
+-
+-      pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], gain);
+-      hid_hw_request(pidff->hid, pidff->reports[PID_DEVICE_GAIN],
+-                      HID_REQ_SET_REPORT);
++      pidff_set_gain_report(dev->ff->private, gain);
+ }
+ static void pidff_autocenter(struct pidff_device *pidff, u16 magnitude)
+@@ -1414,12 +1423,7 @@ int hid_pidff_init_with_quirks(struct hid_device *hid, __u32 initial_quirks)
+       if (error)
+               goto fail;
+-      if (test_bit(FF_GAIN, dev->ffbit)) {
+-              pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], 0xffff);
+-              hid_hw_request(hid, pidff->reports[PID_DEVICE_GAIN],
+-                                   HID_REQ_SET_REPORT);
+-      }
+-
++      pidff_set_gain_report(pidff, 0xffff);
+       error = pidff_check_autocenter(pidff, dev);
+       if (error)
+               goto fail;
+-- 
+2.39.5
+
diff --git a/queue-6.13/hid-pidff-factor-out-pool-report-fetch-and-remove-ex.patch b/queue-6.13/hid-pidff-factor-out-pool-report-fetch-and-remove-ex.patch
new file mode 100644 (file)
index 0000000..ee8069e
--- /dev/null
@@ -0,0 +1,117 @@
+From 56cfa0759e801c5bcad99a3849bd2b1524b5a90b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 1 Feb 2025 12:39:06 +0100
+Subject: HID: pidff: Factor out pool report fetch and remove excess
+ declaration
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+
+[ Upstream commit 5d98079b2d0186e1f586301a9c00144a669416a8 ]
+
+We only want to refetch the pool report during device init. Reset
+function is now called when uploading effects to an empty device so
+extract pool fetch to separate function and call it from init before
+autocenter check (autocenter check triggered reset during init).
+
+Remove a superfluous pointer declaration and assigment as well.
+
+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>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/usbhid/hid-pidff.c | 45 ++++++++++++++++++----------------
+ 1 file changed, 24 insertions(+), 21 deletions(-)
+
+diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
+index b21e844f5f3a3..f23381b6e3447 100644
+--- a/drivers/hid/usbhid/hid-pidff.c
++++ b/drivers/hid/usbhid/hid-pidff.c
+@@ -591,12 +591,9 @@ static void pidff_modify_actuators_state(struct pidff_device *pidff, bool enable
+ /*
+  * Reset the device, stop all effects, enable actuators
+- * Refetch pool report
+  */
+ static void pidff_reset(struct pidff_device *pidff)
+ {
+-      int i = 0;
+-
+       /* We reset twice as sometimes hid_wait_io isn't waiting long enough */
+       pidff_send_device_control(pidff, PID_RESET);
+       pidff_send_device_control(pidff, PID_RESET);
+@@ -604,23 +601,29 @@ static void pidff_reset(struct pidff_device *pidff)
+       pidff_send_device_control(pidff, PID_STOP_ALL_EFFECTS);
+       pidff_modify_actuators_state(pidff, 1);
++}
+-      /* pool report is sometimes messed up, refetch it */
+-      hid_hw_request(pidff->hid, pidff->reports[PID_POOL], HID_REQ_GET_REPORT);
+-      hid_hw_wait(pidff->hid);
++/*
++ * Refetch pool report
++ */
++static void pidff_fetch_pool(struct pidff_device *pidff)
++{
++      if (!pidff->pool[PID_SIMULTANEOUS_MAX].value)
++              return;
+-      if (pidff->pool[PID_SIMULTANEOUS_MAX].value) {
+-              while (pidff->pool[PID_SIMULTANEOUS_MAX].value[0] < 2) {
+-                      if (i++ > 20) {
+-                              hid_warn(pidff->hid,
+-                                       "device reports %d simultaneous effects\n",
+-                                       pidff->pool[PID_SIMULTANEOUS_MAX].value[0]);
+-                              break;
+-                      }
+-                      hid_dbg(pidff->hid, "pid_pool requested again\n");
+-                      hid_hw_request(pidff->hid, pidff->reports[PID_POOL],
+-                                        HID_REQ_GET_REPORT);
+-                      hid_hw_wait(pidff->hid);
++      int i = 0;
++      while (pidff->pool[PID_SIMULTANEOUS_MAX].value[0] < 2) {
++              hid_dbg(pidff->hid, "pid_pool requested again\n");
++              hid_hw_request(pidff->hid, pidff->reports[PID_POOL],
++                              HID_REQ_GET_REPORT);
++              hid_hw_wait(pidff->hid);
++
++              /* break after 20 tries with SIMULTANEOUS_MAX < 2 */
++              if (i++ > 20) {
++                      hid_warn(pidff->hid,
++                               "device reports %d simultaneous effects\n",
++                               pidff->pool[PID_SIMULTANEOUS_MAX].value[0]);
++                      break;
+               }
+       }
+ }
+@@ -916,9 +919,7 @@ static void pidff_autocenter(struct pidff_device *pidff, u16 magnitude)
+  */
+ static void pidff_set_autocenter(struct input_dev *dev, u16 magnitude)
+ {
+-      struct pidff_device *pidff = dev->ff->private;
+-
+-      pidff_autocenter(pidff, magnitude);
++      pidff_autocenter(dev->ff->private, magnitude);
+ }
+ /*
+@@ -1424,6 +1425,8 @@ int hid_pidff_init_with_quirks(struct hid_device *hid, u32 initial_quirks)
+       if (error)
+               goto fail;
++      /* pool report is sometimes messed up, refetch it */
++      pidff_fetch_pool(pidff);
+       pidff_set_gain_report(pidff, U16_MAX);
+       error = pidff_check_autocenter(pidff, dev);
+       if (error)
+-- 
+2.39.5
+
diff --git a/queue-6.13/hid-pidff-fix-90-degrees-direction-name-north-east.patch b/queue-6.13/hid-pidff-fix-90-degrees-direction-name-north-east.patch
new file mode 100644 (file)
index 0000000..9bbfb71
--- /dev/null
@@ -0,0 +1,34 @@
+From 67be8f2859efa7abf3df4b1d446e02f05b6e9837 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Feb 2025 23:30:03 +0100
+Subject: HID: pidff: Fix 90 degrees direction name North -> East
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+
+[ Upstream commit f98ecedbeca34a8df1460c3a03cce32639c99a9d ]
+
+Signed-off-by: Jiri Kosina <jkosina@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/usbhid/hid-pidff.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
+index a614438e43bd8..6eb7934c8f53b 100644
+--- a/drivers/hid/usbhid/hid-pidff.c
++++ b/drivers/hid/usbhid/hid-pidff.c
+@@ -145,7 +145,7 @@ static const u8 pidff_block_load_status[] = { 0x8c, 0x8d, 0x8e};
+ #define PID_EFFECT_STOP               1
+ static const u8 pidff_effect_operation_status[] = { 0x79, 0x7b };
+-/* Polar direction 90 degrees (North) */
++/* Polar direction 90 degrees (East) */
+ #define PIDFF_FIXED_WHEEL_DIRECTION   0x4000
+ struct pidff_usage {
+-- 
+2.39.5
+
diff --git a/queue-6.13/hid-pidff-fix-set_device_control.patch b/queue-6.13/hid-pidff-fix-set_device_control.patch
new file mode 100644 (file)
index 0000000..b87fc4d
--- /dev/null
@@ -0,0 +1,79 @@
+From 7f7e1dc79ab8a02d52eac5a493699b30de646ea3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Feb 2025 23:30:04 +0100
+Subject: HID: pidff: Fix set_device_control()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+
+[ Upstream commit e2fa0bdf08a70623f24ed52f2037a330999d9800 ]
+
+As the search for Device Control report is permissive, make sure the
+desired field was actually found, before trying to set it.
+
+Fix bitmask clearing as it was erronously using index instead of
+index - 1 (HID arrays index is 1-based).
+
+Add last two missing Device Control usages to the defined array.
+PID_PAUSE and PID_CONTINUE.
+
+Signed-off-by: Jiri Kosina <jkosina@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/usbhid/hid-pidff.c | 20 +++++++++++++++-----
+ 1 file changed, 15 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
+index 6eb7934c8f53b..8dfd2c554a276 100644
+--- a/drivers/hid/usbhid/hid-pidff.c
++++ b/drivers/hid/usbhid/hid-pidff.c
+@@ -118,7 +118,9 @@ static const u8 pidff_pool[] = { 0x80, 0x83, 0xa9 };
+ #define PID_DISABLE_ACTUATORS 1
+ #define PID_STOP_ALL_EFFECTS  2
+ #define PID_RESET             3
+-static const u8 pidff_device_control[] = { 0x97, 0x98, 0x99, 0x9a };
++#define PID_PAUSE             4
++#define PID_CONTINUE          5
++static const u8 pidff_device_control[] = { 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c };
+ #define PID_CONSTANT  0
+ #define PID_RAMP      1
+@@ -551,21 +553,29 @@ static void pidff_set_gain_report(struct pidff_device *pidff, u16 gain)
+ }
+ /*
+- * Clear device control report
++ * Send device control report to the device
+  */
+ static void pidff_set_device_control(struct pidff_device *pidff, int field)
+ {
+-      int i, tmp;
++      int i, index;
+       int field_index = pidff->control_id[field];
++      if (field_index < 1)
++              return;
++
+       /* Detect if the field is a bitmask variable or an array */
+       if (pidff->device_control->flags & HID_MAIN_ITEM_VARIABLE) {
+               hid_dbg(pidff->hid, "DEVICE_CONTROL is a bitmask\n");
++
+               /* Clear current bitmask */
+               for(i = 0; i < sizeof(pidff_device_control); i++) {
+-                      tmp = pidff->control_id[i];
+-                      pidff->device_control->value[tmp] = 0;
++                      index = pidff->control_id[i];
++                      if (index < 1)
++                              continue;
++
++                      pidff->device_control->value[index - 1] = 0;
+               }
++
+               pidff->device_control->value[field_index - 1] = 1;
+       } else {
+               hid_dbg(pidff->hid, "DEVICE_CONTROL is an array\n");
+-- 
+2.39.5
+
diff --git a/queue-6.13/hid-pidff-make-sure-to-fetch-pool-before-checking-si.patch b/queue-6.13/hid-pidff-make-sure-to-fetch-pool-before-checking-si.patch
new file mode 100644 (file)
index 0000000..d105176
--- /dev/null
@@ -0,0 +1,76 @@
+From 9f1981ec1eaa69fb1d14e8d6c02bbed402ddd623 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 11 Feb 2025 15:35:08 +0100
+Subject: HID: pidff: Make sure to fetch pool before checking SIMULTANEOUS_MAX
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+
+[ Upstream commit 1f650dcec32d22deb1d6db12300a2b98483099a9 ]
+
+As noted by Anssi some 20 years ago, pool report is sometimes messed up.
+This worked fine on many devices but casued oops on VRS DirectForce PRO.
+
+Here, we're making sure pool report is refetched before trying to access
+any of it's fields. While loop was replaced with a for loop + exit
+conditions were moved aroud to decrease the possibility of creating an
+infinite loop scenario.
+
+Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/usbhid/hid-pidff.c | 29 +++++++++++++----------------
+ 1 file changed, 13 insertions(+), 16 deletions(-)
+
+diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
+index f23381b6e3447..503f643b59cad 100644
+--- a/drivers/hid/usbhid/hid-pidff.c
++++ b/drivers/hid/usbhid/hid-pidff.c
+@@ -604,28 +604,25 @@ static void pidff_reset(struct pidff_device *pidff)
+ }
+ /*
+- * Refetch pool report
++ * Fetch pool report
+  */
+ static void pidff_fetch_pool(struct pidff_device *pidff)
+ {
+-      if (!pidff->pool[PID_SIMULTANEOUS_MAX].value)
+-              return;
++      int i;
++      struct hid_device *hid = pidff->hid;
+-      int i = 0;
+-      while (pidff->pool[PID_SIMULTANEOUS_MAX].value[0] < 2) {
+-              hid_dbg(pidff->hid, "pid_pool requested again\n");
+-              hid_hw_request(pidff->hid, pidff->reports[PID_POOL],
+-                              HID_REQ_GET_REPORT);
+-              hid_hw_wait(pidff->hid);
++      /* Repeat if PID_SIMULTANEOUS_MAX < 2 to make sure it's correct */
++      for(i = 0; i < 20; i++) {
++              hid_hw_request(hid, pidff->reports[PID_POOL], HID_REQ_GET_REPORT);
++              hid_hw_wait(hid);
+-              /* break after 20 tries with SIMULTANEOUS_MAX < 2 */
+-              if (i++ > 20) {
+-                      hid_warn(pidff->hid,
+-                               "device reports %d simultaneous effects\n",
+-                               pidff->pool[PID_SIMULTANEOUS_MAX].value[0]);
+-                      break;
+-              }
++              if (!pidff->pool[PID_SIMULTANEOUS_MAX].value)
++                      return;
++              if (pidff->pool[PID_SIMULTANEOUS_MAX].value[0] >= 2)
++                      return;
+       }
++      hid_warn(hid, "device reports %d simultaneous effects\n",
++               pidff->pool[PID_SIMULTANEOUS_MAX].value[0]);
+ }
+ /*
+-- 
+2.39.5
+
diff --git a/queue-6.13/hid-pidff-move-all-hid-pidff-definitions-to-a-dedica.patch b/queue-6.13/hid-pidff-move-all-hid-pidff-definitions-to-a-dedica.patch
new file mode 100644 (file)
index 0000000..16e39e8
--- /dev/null
@@ -0,0 +1,154 @@
+From 3365a9dc9e2fcb2e5293178b093467e5f4f6225f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 1 Feb 2025 12:39:03 +0100
+Subject: HID: pidff: Move all hid-pidff definitions to a dedicated header
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+
+[ Upstream commit 0d24d4b1da96df9fc5ff36966f40f980ef864d46 ]
+
+Do not clutter hid includes with stuff not needed outside of
+the kernel.
+
+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>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/hid-universal-pidff.c |  3 ++-
+ drivers/hid/usbhid/hid-core.c     |  1 +
+ drivers/hid/usbhid/hid-pidff.c    |  3 ++-
+ drivers/hid/usbhid/hid-pidff.h    | 33 +++++++++++++++++++++++++++++++
+ include/linux/hid.h               | 15 --------------
+ 5 files changed, 38 insertions(+), 17 deletions(-)
+ create mode 100644 drivers/hid/usbhid/hid-pidff.h
+
+diff --git a/drivers/hid/hid-universal-pidff.c b/drivers/hid/hid-universal-pidff.c
+index 7ef5ab9146b1c..1b713b741d192 100644
+--- a/drivers/hid/hid-universal-pidff.c
++++ b/drivers/hid/hid-universal-pidff.c
+@@ -13,6 +13,7 @@
+ #include <linux/module.h>
+ #include <linux/input-event-codes.h>
+ #include "hid-ids.h"
++#include "usbhid/hid-pidff.h"
+ #define JOY_RANGE (BTN_DEAD - BTN_JOYSTICK + 1)
+@@ -89,7 +90,7 @@ static int universal_pidff_probe(struct hid_device *hdev,
+       }
+       /* Check if HID_PID support is enabled */
+-      int (*init_function)(struct hid_device *, __u32);
++      int (*init_function)(struct hid_device *, u32);
+       init_function = hid_pidff_init_with_quirks;
+       if (!init_function) {
+diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
+index a6eb6fe6130d1..44c2351b870fa 100644
+--- a/drivers/hid/usbhid/hid-core.c
++++ b/drivers/hid/usbhid/hid-core.c
+@@ -35,6 +35,7 @@
+ #include <linux/hid-debug.h>
+ #include <linux/hidraw.h>
+ #include "usbhid.h"
++#include "hid-pidff.h"
+ /*
+  * Version Information
+diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
+index ac6f940abd901..a8eaa77e80be3 100644
+--- a/drivers/hid/usbhid/hid-pidff.c
++++ b/drivers/hid/usbhid/hid-pidff.c
+@@ -12,6 +12,7 @@
+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
++#include "hid-pidff.h"
+ #include <linux/input.h>
+ #include <linux/slab.h>
+ #include <linux/usb.h>
+@@ -1383,7 +1384,7 @@ static int pidff_check_autocenter(struct pidff_device *pidff,
+  * Check if the device is PID and initialize it
+  * Set initial quirks
+  */
+-int hid_pidff_init_with_quirks(struct hid_device *hid, __u32 initial_quirks)
++int hid_pidff_init_with_quirks(struct hid_device *hid, u32 initial_quirks)
+ {
+       struct pidff_device *pidff;
+       struct hid_input *hidinput = list_entry(hid->inputs.next,
+diff --git a/drivers/hid/usbhid/hid-pidff.h b/drivers/hid/usbhid/hid-pidff.h
+new file mode 100644
+index 0000000000000..dda571e0a5bd3
+--- /dev/null
++++ b/drivers/hid/usbhid/hid-pidff.h
+@@ -0,0 +1,33 @@
++/* SPDX-License-Identifier: GPL-2.0-or-later */
++#ifndef __HID_PIDFF_H
++#define __HID_PIDFF_H
++
++#include <linux/hid.h>
++
++/* HID PIDFF quirks */
++
++/* Delay field (0xA7) missing. Skip it during set effect report upload */
++#define HID_PIDFF_QUIRK_MISSING_DELAY         BIT(0)
++
++/* Missing Paramter block offset (0x23). Skip it during SET_CONDITION
++   report upload */
++#define HID_PIDFF_QUIRK_MISSING_PBO           BIT(1)
++
++/* Initialise device control field even if logical_minimum != 1 */
++#define HID_PIDFF_QUIRK_PERMISSIVE_CONTROL    BIT(2)
++
++/* Use fixed 0x4000 direction during SET_EFFECT report upload */
++#define HID_PIDFF_QUIRK_FIX_WHEEL_DIRECTION   BIT(3)
++
++/* Force all periodic effects to be uploaded as SINE */
++#define HID_PIDFF_QUIRK_PERIODIC_SINE_ONLY    BIT(4)
++
++#ifdef CONFIG_HID_PID
++int hid_pidff_init(struct hid_device *hid);
++int hid_pidff_init_with_quirks(struct hid_device *hid, u32 initial_quirks);
++#else
++#define hid_pidff_init NULL
++#define hid_pidff_init_with_quirks NULL
++#endif
++
++#endif
+diff --git a/include/linux/hid.h b/include/linux/hid.h
+index e180679ab284c..9ca7e26ac4e92 100644
+--- a/include/linux/hid.h
++++ b/include/linux/hid.h
+@@ -1222,21 +1222,6 @@ unsigned long hid_lookup_quirk(const struct hid_device *hdev);
+ int hid_quirks_init(char **quirks_param, __u16 bus, int count);
+ void hid_quirks_exit(__u16 bus);
+-#ifdef CONFIG_HID_PID
+-int hid_pidff_init(struct hid_device *hid);
+-int hid_pidff_init_with_quirks(struct hid_device *hid, __u32 initial_quirks);
+-#else
+-#define hid_pidff_init NULL
+-#define hid_pidff_init_with_quirks NULL
+-#endif
+-
+-/* HID PIDFF quirks */
+-#define HID_PIDFF_QUIRK_MISSING_DELAY         BIT(0)
+-#define HID_PIDFF_QUIRK_MISSING_PBO           BIT(1)
+-#define HID_PIDFF_QUIRK_PERMISSIVE_CONTROL    BIT(2)
+-#define HID_PIDFF_QUIRK_FIX_WHEEL_DIRECTION   BIT(3)
+-#define HID_PIDFF_QUIRK_PERIODIC_SINE_ONLY    BIT(4)
+-
+ #define dbg_hid(fmt, ...) pr_debug("%s: " fmt, __FILE__, ##__VA_ARGS__)
+ #define hid_err(hid, fmt, ...)                                \
+-- 
+2.39.5
+
diff --git a/queue-6.13/hid-pidff-remove-redundant-call-to-pidff_find_specia.patch b/queue-6.13/hid-pidff-remove-redundant-call-to-pidff_find_specia.patch
new file mode 100644 (file)
index 0000000..47266ed
--- /dev/null
@@ -0,0 +1,39 @@
+From 8b7b49c3973926eb82d92dd75ce5fabb4aeb81d4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 11 Feb 2025 15:35:12 +0100
+Subject: HID: pidff: Remove redundant call to pidff_find_special_keys
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+
+[ Upstream commit 1bd55e79cbc0ea2d6a65f51e06c891806359c2f2 ]
+
+Probably left out as a mistake after Anssi created the helper macro
+
+Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/usbhid/hid-pidff.c | 4 ----
+ 1 file changed, 4 deletions(-)
+
+diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
+index d5734cbf745d1..6f6c47bd57eaa 100644
+--- a/drivers/hid/usbhid/hid-pidff.c
++++ b/drivers/hid/usbhid/hid-pidff.c
+@@ -1159,10 +1159,6 @@ static int pidff_find_special_fields(struct pidff_device *pidff)
+               return -1;
+       }
+-      pidff_find_special_keys(pidff->control_id, pidff->device_control,
+-                              pidff_device_control,
+-                              sizeof(pidff_device_control));
+-
+       PIDFF_FIND_SPECIAL_KEYS(control_id, device_control, device_control);
+       if (!PIDFF_FIND_SPECIAL_KEYS(type_id, create_new_effect_type,
+-- 
+2.39.5
+
diff --git a/queue-6.13/hid-pidff-rename-two-functions-to-align-them-with-na.patch b/queue-6.13/hid-pidff-rename-two-functions-to-align-them-with-na.patch
new file mode 100644 (file)
index 0000000..2866e63
--- /dev/null
@@ -0,0 +1,68 @@
+From 39fae9c77f9df0a2513dc84357780918ba952cc9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Feb 2025 23:30:00 +0100
+Subject: HID: pidff: Rename two functions to align them with naming convention
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+
+[ Upstream commit bbeface1051142bcb0473fdcc89102ea5b31607d ]
+
+Driver uses "set" everywhere to indicate setting report values and
+requesting HID_REQ_SET_REPORT
+
+Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/usbhid/hid-pidff.c | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
+index 6f6c47bd57eaa..ffecc712be003 100644
+--- a/drivers/hid/usbhid/hid-pidff.c
++++ b/drivers/hid/usbhid/hid-pidff.c
+@@ -552,7 +552,7 @@ static void pidff_set_gain_report(struct pidff_device *pidff, u16 gain)
+ /*
+  * Clear device control report
+  */
+-static void pidff_send_device_control(struct pidff_device *pidff, int field)
++static void pidff_set_device_control(struct pidff_device *pidff, int field)
+ {
+       int i, tmp;
+       int field_index = pidff->control_id[field];
+@@ -578,10 +578,10 @@ static void pidff_send_device_control(struct pidff_device *pidff, int field)
+ /*
+  * Modify actuators state
+  */
+-static void pidff_modify_actuators_state(struct pidff_device *pidff, bool enable)
++static void pidff_set_actuators(struct pidff_device *pidff, bool enable)
+ {
+       hid_dbg(pidff->hid, "%s actuators\n", enable ? "Enable" : "Disable");
+-      pidff_send_device_control(pidff,
++      pidff_set_device_control(pidff,
+               enable ? PID_ENABLE_ACTUATORS : PID_DISABLE_ACTUATORS);
+ }
+@@ -591,12 +591,12 @@ static void pidff_modify_actuators_state(struct pidff_device *pidff, bool enable
+ static void pidff_reset(struct pidff_device *pidff)
+ {
+       /* We reset twice as sometimes hid_wait_io isn't waiting long enough */
+-      pidff_send_device_control(pidff, PID_RESET);
+-      pidff_send_device_control(pidff, PID_RESET);
++      pidff_set_device_control(pidff, PID_RESET);
++      pidff_set_device_control(pidff, PID_RESET);
+       pidff->effect_count = 0;
+-      pidff_send_device_control(pidff, PID_STOP_ALL_EFFECTS);
+-      pidff_modify_actuators_state(pidff, 1);
++      pidff_set_device_control(pidff, PID_STOP_ALL_EFFECTS);
++      pidff_set_actuators(pidff, 1);
+ }
+ /*
+-- 
+2.39.5
+
diff --git a/queue-6.13/hid-pidff-rescale-time-values-to-match-field-units.patch b/queue-6.13/hid-pidff-rescale-time-values-to-match-field-units.patch
new file mode 100644 (file)
index 0000000..d61dfe6
--- /dev/null
@@ -0,0 +1,167 @@
+From 9e39fc1bd5b565a5404006bc53e73915edf33824 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 1 Feb 2025 12:39:00 +0100
+Subject: HID: pidff: Rescale time values to match field units
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+
+[ Upstream commit 8713107221a8ce4021ec5fa12bb50ecc8165cf08 ]
+
+PID devices can use different exponents for time fields, while Linux
+Force Feedback API only supports miliseconds.
+
+Read the exponent of a given time field and scale its value accordingly.
+
+Changes in v7:
+- Rescale all time fields, not only period
+
+changes in v9:
+- Properly assign fade_lenght, not attack_length to PID_FADE_TIME
+
+Co-developed-by: Makarenko Oleg <oleg@makarenk.ooo>
+Signed-off-by: Makarenko Oleg <oleg@makarenk.ooo>
+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>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/usbhid/hid-pidff.c | 69 ++++++++++++++++++++++++++--------
+ 1 file changed, 54 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
+index bd913d57e4d75..180b2cf66e4c7 100644
+--- a/drivers/hid/usbhid/hid-pidff.c
++++ b/drivers/hid/usbhid/hid-pidff.c
+@@ -22,6 +22,9 @@
+ #define       PID_EFFECTS_MAX         64
+ #define       PID_INFINITE            0xffff
++/* Linux Force Feedback API uses miliseconds as time unit */
++#define FF_TIME_EXPONENT      -3
++
+ /* Report usage table used to put reports into an array */
+ #define PID_SET_EFFECT                0
+@@ -231,6 +234,24 @@ static int pidff_rescale_signed(int i, struct hid_field *field)
+           field->logical_minimum / -0x8000;
+ }
++/*
++ * Scale time value from Linux default (ms) to field units
++ */
++static u32 pidff_rescale_time(u16 time, struct hid_field *field)
++{
++      u32 scaled_time = time;
++      int exponent = field->unit_exponent;
++      pr_debug("time field exponent: %d\n", exponent);
++
++      for (;exponent < FF_TIME_EXPONENT; exponent++)
++              scaled_time *= 10;
++      for (;exponent > FF_TIME_EXPONENT; exponent--)
++              scaled_time /= 10;
++
++      pr_debug("time calculated from %d to %d\n", time, scaled_time);
++      return scaled_time;
++}
++
+ static void pidff_set(struct pidff_usage *usage, u16 value)
+ {
+       usage->value[0] = pidff_rescale(value, 0xffff, usage->field);
+@@ -252,6 +273,27 @@ static void pidff_set_signed(struct pidff_usage *usage, s16 value)
+       pr_debug("calculated from %d to %d\n", value, usage->value[0]);
+ }
++static void pidff_set_time(struct pidff_usage *usage, u16 time)
++{
++      u32 modified_time = pidff_rescale_time(time, usage->field);
++      usage->value[0] = pidff_clamp(modified_time, usage->field);
++}
++
++static void pidff_set_duration(struct pidff_usage *usage, u16 duration)
++{
++      /* Convert infinite length from Linux API (0)
++         to PID standard (NULL) if needed */
++      if (duration == 0)
++              duration = PID_INFINITE;
++
++      if (duration == PID_INFINITE) {
++              usage->value[0] = PID_INFINITE;
++              return;
++      }
++
++      pidff_set_time(usage, duration);
++}
++
+ /*
+  * Send envelope report to the device
+  */
+@@ -270,8 +312,10 @@ static void pidff_set_envelope_report(struct pidff_device *pidff,
+                         0x7fff ? 0x7fff : envelope->fade_level, 0x7fff,
+                         pidff->set_envelope[PID_FADE_LEVEL].field);
+-      pidff->set_envelope[PID_ATTACK_TIME].value[0] = envelope->attack_length;
+-      pidff->set_envelope[PID_FADE_TIME].value[0] = envelope->fade_length;
++      pidff_set_time(&pidff->set_envelope[PID_ATTACK_TIME],
++                      envelope->attack_length);
++      pidff_set_time(&pidff->set_envelope[PID_FADE_TIME],
++                      envelope->fade_length);
+       hid_dbg(pidff->hid, "attack %u => %d\n",
+               envelope->attack_level,
+@@ -340,14 +384,12 @@ static void pidff_set_effect_report(struct pidff_device *pidff,
+       pidff->set_effect_type->value[0] =
+               pidff->create_new_effect_type->value[0];
+-      /* Convert infinite length from Linux API (0)
+-         to PID standard (NULL) if needed */
+-      pidff->set_effect[PID_DURATION].value[0] =
+-              effect->replay.length == 0 ? PID_INFINITE : effect->replay.length;
++      pidff_set_duration(&pidff->set_effect[PID_DURATION],
++              effect->replay.length);
+       pidff->set_effect[PID_TRIGGER_BUTTON].value[0] = effect->trigger.button;
+-      pidff->set_effect[PID_TRIGGER_REPEAT_INT].value[0] =
+-              effect->trigger.interval;
++      pidff_set_time(&pidff->set_effect[PID_TRIGGER_REPEAT_INT],
++                      effect->trigger.interval);
+       pidff->set_effect[PID_GAIN].value[0] =
+               pidff->set_effect[PID_GAIN].field->logical_maximum;
+       pidff->set_effect[PID_DIRECTION_ENABLE].value[0] = 1;
+@@ -360,7 +402,8 @@ static void pidff_set_effect_report(struct pidff_device *pidff,
+       /* Omit setting delay field if it's missing */
+       if (!(pidff->quirks & HID_PIDFF_QUIRK_MISSING_DELAY))
+-              pidff->set_effect[PID_START_DELAY].value[0] = effect->replay.delay;
++              pidff_set_time(&pidff->set_effect[PID_START_DELAY],
++                              effect->replay.delay);
+       hid_hw_request(pidff->hid, pidff->reports[PID_SET_EFFECT],
+                       HID_REQ_SET_REPORT);
+@@ -392,15 +435,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);
+-
+-      /* 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);
++      pidff_set_time(&pidff->set_periodic[PID_PERIOD],
++                      effect->u.periodic.period);
+       hid_hw_request(pidff->hid, pidff->reports[PID_SET_PERIODIC],
+                       HID_REQ_SET_REPORT);
+-
+ }
+ /*
+-- 
+2.39.5
+
diff --git a/queue-6.13/hid-pidff-simplify-pidff_rescale_signed.patch b/queue-6.13/hid-pidff-simplify-pidff_rescale_signed.patch
new file mode 100644 (file)
index 0000000..4138021
--- /dev/null
@@ -0,0 +1,47 @@
+From 04f6c98ddccd154c60d887dc27d8faa2820d8996 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 1 Feb 2025 12:39:04 +0100
+Subject: HID: pidff: Simplify pidff_rescale_signed
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+
+[ Upstream commit 4eb9c2ee538b62dc5dcae192297c3a4044b7ade5 ]
+
+This function overrelies on ternary operators and makes it hard to parse
+it mentally. New version makes it very easy to understand.
+
+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>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/usbhid/hid-pidff.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
+index a8eaa77e80be3..8083eb7684e5e 100644
+--- a/drivers/hid/usbhid/hid-pidff.c
++++ b/drivers/hid/usbhid/hid-pidff.c
+@@ -230,9 +230,9 @@ static int pidff_rescale(int i, int max, struct hid_field *field)
+  */
+ static int pidff_rescale_signed(int i, struct hid_field *field)
+ {
+-      return i == 0 ? 0 : i >
+-          0 ? i * field->logical_maximum / 0x7fff : i *
+-          field->logical_minimum / -0x8000;
++      if (i > 0) return i * field->logical_maximum / 0x7fff;
++      if (i < 0) return i * field->logical_minimum / -0x8000;
++      return 0;
+ }
+ /*
+-- 
+2.39.5
+
diff --git a/queue-6.13/hid-pidff-simplify-pidff_upload_effect-function.patch b/queue-6.13/hid-pidff-simplify-pidff_upload_effect-function.patch
new file mode 100644 (file)
index 0000000..16567ff
--- /dev/null
@@ -0,0 +1,100 @@
+From e2159f9fba9c9b937fcfacb7c4a5f5c16d9242ae Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 1 Feb 2025 12:38:58 +0100
+Subject: HID: pidff: Simplify pidff_upload_effect function
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+
+[ Upstream commit e4bdc80ef14272ef56c38d8ca2f365fdf59cd0ba ]
+
+Merge a bit of code that reqeusts conditional effects upload.
+Makes it clear, that effect handling should be identical for
+SPRING, DAMPER, INERTIA and FRICTION.
+
+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>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/usbhid/hid-pidff.c | 54 ++++++++++------------------------
+ 1 file changed, 16 insertions(+), 38 deletions(-)
+
+diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
+index 99b5d3deb40d0..42c951a1d65bf 100644
+--- a/drivers/hid/usbhid/hid-pidff.c
++++ b/drivers/hid/usbhid/hid-pidff.c
+@@ -770,48 +770,26 @@ static int pidff_upload_effect(struct input_dev *dev, struct ff_effect *effect,
+               break;
+       case FF_SPRING:
+-              if (!old) {
+-                      error = pidff_request_effect_upload(pidff,
+-                                      pidff->type_id[PID_SPRING]);
+-                      if (error)
+-                              return error;
+-              }
+-              if (!old || pidff_needs_set_effect(effect, old))
+-                      pidff_set_effect_report(pidff, effect);
+-              if (!old || pidff_needs_set_condition(effect, old))
+-                      pidff_set_condition_report(pidff, effect);
+-              break;
+-
+-      case FF_FRICTION:
+-              if (!old) {
+-                      error = pidff_request_effect_upload(pidff,
+-                                      pidff->type_id[PID_FRICTION]);
+-                      if (error)
+-                              return error;
+-              }
+-              if (!old || pidff_needs_set_effect(effect, old))
+-                      pidff_set_effect_report(pidff, effect);
+-              if (!old || pidff_needs_set_condition(effect, old))
+-                      pidff_set_condition_report(pidff, effect);
+-              break;
+-
+       case FF_DAMPER:
+-              if (!old) {
+-                      error = pidff_request_effect_upload(pidff,
+-                                      pidff->type_id[PID_DAMPER]);
+-                      if (error)
+-                              return error;
+-              }
+-              if (!old || pidff_needs_set_effect(effect, old))
+-                      pidff_set_effect_report(pidff, effect);
+-              if (!old || pidff_needs_set_condition(effect, old))
+-                      pidff_set_condition_report(pidff, effect);
+-              break;
+-
+       case FF_INERTIA:
++      case FF_FRICTION:
+               if (!old) {
++                      switch(effect->type) {
++                      case FF_SPRING:
++                              type_id = PID_SPRING;
++                              break;
++                      case FF_DAMPER:
++                              type_id = PID_DAMPER;
++                              break;
++                      case FF_INERTIA:
++                              type_id = PID_INERTIA;
++                              break;
++                      case FF_FRICTION:
++                              type_id = PID_FRICTION;
++                              break;
++                      }
+                       error = pidff_request_effect_upload(pidff,
+-                                      pidff->type_id[PID_INERTIA]);
++                                      pidff->type_id[type_id]);
+                       if (error)
+                               return error;
+               }
+-- 
+2.39.5
+
diff --git a/queue-6.13/hid-pidff-stop-all-effects-before-enabling-actuators.patch b/queue-6.13/hid-pidff-stop-all-effects-before-enabling-actuators.patch
new file mode 100644 (file)
index 0000000..b84909d
--- /dev/null
@@ -0,0 +1,63 @@
+From 0923ad51b20b53cb105f09473875a7431cc6c137 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 1 Feb 2025 12:38:53 +0100
+Subject: HID: pidff: Stop all effects before enabling actuators
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+
+[ Upstream commit ce52c0c939fcb568d1abe454821d5623de38b424 ]
+
+Some PID compliant devices automatically play effects after boot (i.e.
+autocenter spring) that prevent the rendering of other effects since
+it is done outside the kernel driver.
+
+This makes sure all the effects currently played are stopped after
+resetting the device.
+It brings compatibility to the Brunner CLS-P joystick and others
+
+Reported-by: Jules Noirant <jules.noirant@orange.fr>
+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>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/usbhid/hid-pidff.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
+index 6b55345ce75ac..635596a57c75d 100644
+--- a/drivers/hid/usbhid/hid-pidff.c
++++ b/drivers/hid/usbhid/hid-pidff.c
+@@ -109,8 +109,9 @@ static const u8 pidff_pool[] = { 0x80, 0x83, 0xa9 };
+ /* Special field key tables used to put special field keys into arrays */
+ #define PID_ENABLE_ACTUATORS  0
+-#define PID_RESET             1
+-static const u8 pidff_device_control[] = { 0x97, 0x9a };
++#define PID_STOP_ALL_EFFECTS  1
++#define PID_RESET             2
++static const u8 pidff_device_control[] = { 0x97, 0x99, 0x9a };
+ #define PID_CONSTANT  0
+ #define PID_RAMP      1
+@@ -1235,6 +1236,10 @@ static void pidff_reset(struct pidff_device *pidff)
+       hid_hw_request(hid, pidff->reports[PID_DEVICE_CONTROL], HID_REQ_SET_REPORT);
+       hid_hw_wait(hid);
++      pidff->device_control->value[0] = pidff->control_id[PID_STOP_ALL_EFFECTS];
++      hid_hw_request(hid, pidff->reports[PID_DEVICE_CONTROL], HID_REQ_SET_REPORT);
++      hid_hw_wait(hid);
++
+       pidff->device_control->value[0] =
+               pidff->control_id[PID_ENABLE_ACTUATORS];
+       hid_hw_request(hid, pidff->reports[PID_DEVICE_CONTROL], HID_REQ_SET_REPORT);
+-- 
+2.39.5
+
diff --git a/queue-6.13/hid-pidff-support-device-error-response-from-pid_blo.patch b/queue-6.13/hid-pidff-support-device-error-response-from-pid_blo.patch
new file mode 100644 (file)
index 0000000..f2396c7
--- /dev/null
@@ -0,0 +1,54 @@
+From ba582ecdfdcc0dcd3faeb1504f9d0e913697a105 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 11 Feb 2025 15:35:11 +0100
+Subject: HID: pidff: Support device error response from PID_BLOCK_LOAD
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+
+[ Upstream commit 9d4174dc4a234408d91fd83725e1899766cd1731 ]
+
+If an error happens on the device, the driver will no longer fall
+into the trap of reading this status 60 times before it decides that
+this reply won't change to success/memory full.
+
+Greatly reduces communication overhead during device error situation.
+
+Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/usbhid/hid-pidff.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
+index e2508a4d754d3..d5734cbf745d1 100644
+--- a/drivers/hid/usbhid/hid-pidff.c
++++ b/drivers/hid/usbhid/hid-pidff.c
+@@ -138,7 +138,8 @@ static const u8 pidff_effect_types[] = {
+ #define PID_BLOCK_LOAD_SUCCESS        0
+ #define PID_BLOCK_LOAD_FULL   1
+-static const u8 pidff_block_load_status[] = { 0x8c, 0x8d };
++#define PID_BLOCK_LOAD_ERROR  2
++static const u8 pidff_block_load_status[] = { 0x8c, 0x8d, 0x8e};
+ #define PID_EFFECT_START      0
+ #define PID_EFFECT_STOP               1
+@@ -666,6 +667,11 @@ static int pidff_request_effect_upload(struct pidff_device *pidff, int efnum)
+                               pidff->block_load[PID_RAM_POOL_AVAILABLE].value[0] : -1);
+                       return -ENOSPC;
+               }
++              if (pidff->block_load_status->value[0] ==
++                  pidff->status_id[PID_BLOCK_LOAD_ERROR]) {
++                      hid_dbg(pidff->hid, "device error during effect creation\n");
++                      return -EREMOTEIO;
++              }
+       }
+       hid_err(pidff->hid, "pid_block_load failed 60 times\n");
+       return -EIO;
+-- 
+2.39.5
+
diff --git a/queue-6.13/hid-pidff-use-macros-instead-of-hardcoded-min-max-va.patch b/queue-6.13/hid-pidff-use-macros-instead-of-hardcoded-min-max-va.patch
new file mode 100644 (file)
index 0000000..0eb9012
--- /dev/null
@@ -0,0 +1,122 @@
+From 52f5f2a790f36da96a3b05acd9e02c5f3cbd167c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 1 Feb 2025 12:39:05 +0100
+Subject: HID: pidff: Use macros instead of hardcoded min/max values for shorts
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+
+[ Upstream commit 21755162456902998f8d9897086b8c980c540df5 ]
+
+Makes it obvious these magic values ARE in fact derived from min and
+max values for s16 and u16
+
+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>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/usbhid/hid-pidff.c | 24 ++++++++++++------------
+ 1 file changed, 12 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
+index 8083eb7684e5e..b21e844f5f3a3 100644
+--- a/drivers/hid/usbhid/hid-pidff.c
++++ b/drivers/hid/usbhid/hid-pidff.c
+@@ -21,7 +21,7 @@
+ #define       PID_EFFECTS_MAX         64
+-#define       PID_INFINITE            0xffff
++#define       PID_INFINITE            U16_MAX
+ /* Linux Force Feedback API uses miliseconds as time unit */
+ #define FF_TIME_EXPONENT      -3
+@@ -226,12 +226,12 @@ static int pidff_rescale(int i, int max, struct hid_field *field)
+ }
+ /*
+- * Scale a signed value in range -0x8000..0x7fff for the given field
++ * Scale a signed value in range S16_MIN..S16_MAX for the given field
+  */
+ static int pidff_rescale_signed(int i, struct hid_field *field)
+ {
+-      if (i > 0) return i * field->logical_maximum / 0x7fff;
+-      if (i < 0) return i * field->logical_minimum / -0x8000;
++      if (i > 0) return i * field->logical_maximum / S16_MAX;
++      if (i < 0) return i * field->logical_minimum / S16_MIN;
+       return 0;
+ }
+@@ -255,7 +255,7 @@ static u32 pidff_rescale_time(u16 time, struct hid_field *field)
+ static void pidff_set(struct pidff_usage *usage, u16 value)
+ {
+-      usage->value[0] = pidff_rescale(value, 0xffff, usage->field);
++      usage->value[0] = pidff_rescale(value, U16_MAX, usage->field);
+       pr_debug("calculated from %d to %d\n", value, usage->value[0]);
+ }
+@@ -266,10 +266,10 @@ static void pidff_set_signed(struct pidff_usage *usage, s16 value)
+       else {
+               if (value < 0)
+                       usage->value[0] =
+-                          pidff_rescale(-value, 0x8000, usage->field);
++                          pidff_rescale(-value, -S16_MIN, usage->field);
+               else
+                       usage->value[0] =
+-                          pidff_rescale(value, 0x7fff, usage->field);
++                          pidff_rescale(value, S16_MAX, usage->field);
+       }
+       pr_debug("calculated from %d to %d\n", value, usage->value[0]);
+ }
+@@ -306,11 +306,11 @@ static void pidff_set_envelope_report(struct pidff_device *pidff,
+       pidff->set_envelope[PID_ATTACK_LEVEL].value[0] =
+           pidff_rescale(envelope->attack_level >
+-                        0x7fff ? 0x7fff : envelope->attack_level, 0x7fff,
++                        S16_MAX ? S16_MAX : envelope->attack_level, S16_MAX,
+                         pidff->set_envelope[PID_ATTACK_LEVEL].field);
+       pidff->set_envelope[PID_FADE_LEVEL].value[0] =
+           pidff_rescale(envelope->fade_level >
+-                        0x7fff ? 0x7fff : envelope->fade_level, 0x7fff,
++                        S16_MAX ? S16_MAX : envelope->fade_level, S16_MAX,
+                         pidff->set_envelope[PID_FADE_LEVEL].field);
+       pidff_set_time(&pidff->set_envelope[PID_ATTACK_TIME],
+@@ -399,7 +399,7 @@ static void pidff_set_effect_report(struct pidff_device *pidff,
+       pidff->effect_direction->value[0] = pidff_rescale(
+               pidff->quirks & HID_PIDFF_QUIRK_FIX_WHEEL_DIRECTION ?
+               PIDFF_FIXED_WHEEL_DIRECTION : effect->direction,
+-              0xffff, pidff->effect_direction);
++              U16_MAX, pidff->effect_direction);
+       /* Omit setting delay field if it's missing */
+       if (!(pidff->quirks & HID_PIDFF_QUIRK_MISSING_DELAY))
+@@ -1366,7 +1366,7 @@ static int pidff_check_autocenter(struct pidff_device *pidff,
+       if (pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0] ==
+           pidff->block_load[PID_EFFECT_BLOCK_INDEX].field->logical_minimum + 1) {
+-              pidff_autocenter(pidff, 0xffff);
++              pidff_autocenter(pidff, U16_MAX);
+               set_bit(FF_AUTOCENTER, dev->ffbit);
+       } else {
+               hid_notice(pidff->hid,
+@@ -1424,7 +1424,7 @@ int hid_pidff_init_with_quirks(struct hid_device *hid, u32 initial_quirks)
+       if (error)
+               goto fail;
+-      pidff_set_gain_report(pidff, 0xffff);
++      pidff_set_gain_report(pidff, U16_MAX);
+       error = pidff_check_autocenter(pidff, dev);
+       if (error)
+               goto fail;
+-- 
+2.39.5
+
index b14ca3630e12e15829de6684b32119036f31e281..a9b2db167d5d0712041a4db698a3107336326848 100644 (file)
@@ -171,3 +171,24 @@ erofs-set-error-to-bio-if-file-backed-io-fails.patch
 bpf-support-skf_net_off-and-skf_ll_off-on-skb-frags.patch
 ext4-don-t-treat-fhandle-lookup-of-ea_inode-as-fs-co.patch
 s390-pci-fix-s390_mmio_read-write-syscall-page-fault.patch
+hid-pidff-clamp-periodic-effect-period-to-device-s-l.patch
+hid-pidff-stop-all-effects-before-enabling-actuators.patch
+hid-pidff-completely-rework-and-fix-pidff_reset-func.patch
+hid-pidff-simplify-pidff_upload_effect-function.patch
+hid-pidff-define-values-used-in-pidff_find_special_f.patch
+hid-pidff-rescale-time-values-to-match-field-units.patch
+hid-pidff-factor-out-code-for-setting-gain.patch
+hid-pidff-move-all-hid-pidff-definitions-to-a-dedica.patch
+hid-pidff-simplify-pidff_rescale_signed.patch
+hid-pidff-use-macros-instead-of-hardcoded-min-max-va.patch
+hid-pidff-factor-out-pool-report-fetch-and-remove-ex.patch
+hid-pidff-make-sure-to-fetch-pool-before-checking-si.patch
+hid-hid-universal-pidff-add-asetek-wheelbases-suppor.patch
+hid-pidff-comment-and-code-style-update.patch
+hid-pidff-support-device-error-response-from-pid_blo.patch
+hid-pidff-remove-redundant-call-to-pidff_find_specia.patch
+hid-pidff-rename-two-functions-to-align-them-with-na.patch
+hid-pidff-clamp-effect-playback-loop_count-value.patch
+hid-pidff-compute-infinite-value-instead-of-using-ha.patch
+hid-pidff-fix-90-degrees-direction-name-north-east.patch
+hid-pidff-fix-set_device_control.patch