]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
HID: pidff: Add FIX_WHEEL_DIRECTION quirk
authorTomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
Sat, 1 Feb 2025 11:38:52 +0000 (12:38 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 25 Apr 2025 08:45:12 +0000 (10:45 +0200)
[ Upstream commit 3051bf5ec773b803c474ea556b57d678a8885be3 ]

Most steering wheels simply ignore DIRECTION field, but some try to be
compliant with the PID standard and use it in force calculations. Games
often ignore setting this field properly and/or there can be issues with
dinput8 -> wine -> SDL -> Linux API translation, and this value can be
incorrect. This can lead to partial/complete loss of Force Feedback or
even unexpected force reversal.

Sadly, this quirk can't be detected automatically without sending out
effects that would move an axis.

This fixes FFB on Moza Racing devices and others where effect direction
is not simply ignored.

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>
Signed-off-by: Jiri Kosina <jkosina@suse.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/hid/usbhid/hid-pidff.c
include/linux/hid.h

index b8c2ba0a930c2e32c43b2fb859fca47a6d66e496..a37cf852a2836189611ff31e3bb53ee00e24e411 100644 (file)
@@ -137,6 +137,9 @@ static const u8 pidff_block_load_status[] = { 0x8c, 0x8d };
 #define PID_EFFECT_STOP                1
 static const u8 pidff_effect_operation_status[] = { 0x79, 0x7b };
 
+/* Polar direction 90 degrees (North) */
+#define PIDFF_FIXED_WHEEL_DIRECTION    0x4000
+
 struct pidff_usage {
        struct hid_field *field;
        s32 *value;
@@ -328,9 +331,12 @@ static void pidff_set_effect_report(struct pidff_device *pidff,
        pidff->set_effect[PID_GAIN].value[0] =
                pidff->set_effect[PID_GAIN].field->logical_maximum;
        pidff->set_effect[PID_DIRECTION_ENABLE].value[0] = 1;
-       pidff->effect_direction->value[0] =
-               pidff_rescale(effect->direction, 0xffff,
-                               pidff->effect_direction);
+
+       /* Use fixed direction if needed */
+       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);
 
        /* Omit setting delay field if it's missing */
        if (!(pidff->quirks & HID_PIDFF_QUIRK_MISSING_DELAY))
index 3f776ab47e27defc9c930d443a6500720a2daa4e..e3a55fd4e9fc4e6de7bb076aa162965585cad1a0 100644 (file)
@@ -1224,6 +1224,7 @@ int hid_pidff_init_with_quirks(struct hid_device *hid, __u32 initial_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 dbg_hid(fmt, ...) pr_debug("%s: " fmt, __FILE__, ##__VA_ARGS__)