* [PATCH v5 00/12] HID: Upgrade the generic pidff driver and add hid-universal-pidff
@ 2025-01-19 13:12 Tomasz Pakuła
2025-01-19 13:12 ` [PATCH v5 01/12] HID: pidff: Convert infinite length from Linux API to PID standard Tomasz Pakuła
` (11 more replies)
0 siblings, 12 replies; 20+ messages in thread
From: Tomasz Pakuła @ 2025-01-19 13:12 UTC (permalink / raw)
To: jikos, bentiss; +Cc: anssi.hannula, linux-input, linux-usb
This patch series is focused on improving the compatibility and usability of the
hid-pidff force feedback driver. Last patch introduces a new, universal driver
for PID devices that need some special handling like report fixups, remapping the
button range, managing new pidff quirks and setting desirable fuzz/flat values.
This work has been done in the span of the past months with the help of the great
Linux simracing community, with a little input from sim flight fans from FFBeast.
No changes interfere with compliant and currently working PID devices.
I'm not married to the name. It's what we used previously, but if "universal" is
confusing (pidff is already the generic driver), we can come up with something
better like "hid-quirky-pidff" :)
---
Changes in v2:
- Fix typo in a comment
- Fix a possible null pointer dereference when calling hid_pidff_init_with_quirks
especially when compiling with HID_PID=n
- Fix axis identifier when updating fuzz/flat for FFBeast Joystick
---
Changes in v3:
- Fixed a missed incompatible pointer type while assigning hid_pidff_init_with_quirks
to init_function pointer (void -> int)
- Improved Kconfig entry name to adhere to the alphabetical order of special
HID drivers
- Extended cover letter
---
Changes in v4:
- Added PXN devices and their hid ids
- Added hid-universal-pidff entry in the MAINTAINERS file
---
Changes in v5:
- Added PERIODIC_SINE_ONLY quirk
Tomasz Pakuła (12):
HID: pidff: Convert infinite length from Linux API to PID standard
HID: pidff: Do not send effect envelope if it's empty
HID: pidff: Clamp PERIODIC effect period to device's logical range
HID: pidff: Add MISSING_DELAY quirk and its detection
HID: pidff: Add MISSING_PBO quirk and its detection
HID: pidff: Add MISSING_DEVICE_CONTROL quirk
HID: pidff: Add hid_pidff_init_with_quirks and export as GPL symbol
HID: pidff: Add FIX_WHEEL_DIRECTION quirk
HID: pidff: Stop all effects before enabling actuators
HID: Add hid-universal-pidff driver and supported device ids
MAINTAINERS: Add entry for hid-universal-pidff driver
HID: pidff: Add PERIODIC_SINE_ONLY quirk
MAINTAINERS | 6 +
drivers/hid/Kconfig | 14 +++
drivers/hid/Makefile | 1 +
drivers/hid/hid-ids.h | 29 +++++
drivers/hid/hid-universal-pidff.c | 191 ++++++++++++++++++++++++++++
drivers/hid/usbhid/hid-pidff.c | 203 ++++++++++++++++++++++--------
include/linux/hid.h | 9 ++
7 files changed, 404 insertions(+), 49 deletions(-)
create mode 100644 drivers/hid/hid-universal-pidff.c
--
2.48.1
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v5 01/12] HID: pidff: Convert infinite length from Linux API to PID standard
2025-01-19 13:12 [PATCH v5 00/12] HID: Upgrade the generic pidff driver and add hid-universal-pidff Tomasz Pakuła
@ 2025-01-19 13:12 ` Tomasz Pakuła
2025-01-19 13:12 ` [PATCH v5 02/12] HID: pidff: Do not send effect envelope if it's empty Tomasz Pakuła
` (10 subsequent siblings)
11 siblings, 0 replies; 20+ messages in thread
From: Tomasz Pakuła @ 2025-01-19 13:12 UTC (permalink / raw)
To: jikos, bentiss; +Cc: anssi.hannula, linux-input, linux-usb
Linux defines 0 length as infinite in its force feedback API
while USB PID defines NULL (0xffff). Most PID devices do not expect a
0-length effect and can't interpret it as infinite. This change fixes
Force Feedback for most PID compliant devices.
As most games depend on updating the values of already playing infinite
effects, this is crucial to ensure they will actually work.
Previously, users had to rely on third-party software to do this conversion
and make their PID devices usable.
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>
---
drivers/hid/usbhid/hid-pidff.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
index 3b4ee21cd811..3899d72a0b02 100644
--- a/drivers/hid/usbhid/hid-pidff.c
+++ b/drivers/hid/usbhid/hid-pidff.c
@@ -301,7 +301,12 @@ static void pidff_set_effect_report(struct pidff_device *pidff,
pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0];
pidff->set_effect_type->value[0] =
pidff->create_new_effect_type->value[0];
- pidff->set_effect[PID_DURATION].value[0] = effect->replay.length;
+
+ // Convert infinite length from Linux API (0)
+ // to PID standard (NULL) if needed
+ pidff->set_effect[PID_DURATION].value[0] =
+ effect->replay.length == 0 ? 0xffff : 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;
--
2.48.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v5 02/12] HID: pidff: Do not send effect envelope if it's empty
2025-01-19 13:12 [PATCH v5 00/12] HID: Upgrade the generic pidff driver and add hid-universal-pidff Tomasz Pakuła
2025-01-19 13:12 ` [PATCH v5 01/12] HID: pidff: Convert infinite length from Linux API to PID standard Tomasz Pakuła
@ 2025-01-19 13:12 ` Tomasz Pakuła
2025-01-21 9:59 ` Oliver Neukum
2025-01-19 13:12 ` [PATCH v5 03/12] HID: pidff: Clamp PERIODIC effect period to device's logical range Tomasz Pakuła
` (9 subsequent siblings)
11 siblings, 1 reply; 20+ messages in thread
From: Tomasz Pakuła @ 2025-01-19 13:12 UTC (permalink / raw)
To: jikos, bentiss; +Cc: anssi.hannula, linux-input, linux-usb
Envelope struct is always initialized, but the envelope itself is
optional as described in USB PID Device class definition 1.0.
5.1.1.1 Type Specific Block Offsets
...
4) Effects that do not use Condition Blocks use 1 Parameter Block and
an *optional* Envelope Block.
Sending out "empty" envelope breaks force feedback on some devices with
games that use SINE effect + offset to emulate constant force effect, as
well as generally breaking Constant/Periodic effects. One of the affected
brands is Moza Racing.
This change prevents the envelope from being sent if it contains all
0 values while keeping the old behavior of only sending it, if it differs
from the old one.
Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
---
drivers/hid/usbhid/hid-pidff.c | 39 ++++++++++++++++++----------------
1 file changed, 21 insertions(+), 18 deletions(-)
diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
index 3899d72a0b02..cf8163d92ea4 100644
--- a/drivers/hid/usbhid/hid-pidff.c
+++ b/drivers/hid/usbhid/hid-pidff.c
@@ -261,10 +261,19 @@ static void pidff_set_envelope_report(struct pidff_device *pidff,
static int pidff_needs_set_envelope(struct ff_envelope *envelope,
struct ff_envelope *old)
{
- return envelope->attack_level != old->attack_level ||
- envelope->fade_level != old->fade_level ||
+ bool needs_new_envelope;
+ needs_new_envelope = envelope->attack_level != 0 ||
+ envelope->fade_level != 0 ||
+ envelope->attack_length != 0 ||
+ envelope->fade_length != 0;
+
+ if (!needs_new_envelope || !old)
+ return needs_new_envelope;
+
+ return envelope->attack_level != old->attack_level ||
+ envelope->fade_level != old->fade_level ||
envelope->attack_length != old->attack_length ||
- envelope->fade_length != old->fade_length;
+ envelope->fade_length != old->fade_length;
}
/*
@@ -579,11 +588,9 @@ static int pidff_upload_effect(struct input_dev *dev, struct ff_effect *effect,
pidff_set_effect_report(pidff, effect);
if (!old || pidff_needs_set_constant(effect, old))
pidff_set_constant_force_report(pidff, effect);
- if (!old ||
- pidff_needs_set_envelope(&effect->u.constant.envelope,
- &old->u.constant.envelope))
- pidff_set_envelope_report(pidff,
- &effect->u.constant.envelope);
+ if (pidff_needs_set_envelope(&effect->u.constant.envelope,
+ &old->u.constant.envelope))
+ pidff_set_envelope_report(pidff, &effect->u.constant.envelope);
break;
case FF_PERIODIC:
@@ -618,11 +625,9 @@ static int pidff_upload_effect(struct input_dev *dev, struct ff_effect *effect,
pidff_set_effect_report(pidff, effect);
if (!old || pidff_needs_set_periodic(effect, old))
pidff_set_periodic_report(pidff, effect);
- if (!old ||
- pidff_needs_set_envelope(&effect->u.periodic.envelope,
- &old->u.periodic.envelope))
- pidff_set_envelope_report(pidff,
- &effect->u.periodic.envelope);
+ if (pidff_needs_set_envelope(&effect->u.periodic.envelope,
+ &old->u.periodic.envelope))
+ pidff_set_envelope_report(pidff, &effect->u.periodic.envelope);
break;
case FF_RAMP:
@@ -636,11 +641,9 @@ static int pidff_upload_effect(struct input_dev *dev, struct ff_effect *effect,
pidff_set_effect_report(pidff, effect);
if (!old || pidff_needs_set_ramp(effect, old))
pidff_set_ramp_force_report(pidff, effect);
- if (!old ||
- pidff_needs_set_envelope(&effect->u.ramp.envelope,
- &old->u.ramp.envelope))
- pidff_set_envelope_report(pidff,
- &effect->u.ramp.envelope);
+ if (pidff_needs_set_envelope(&effect->u.ramp.envelope,
+ &old->u.ramp.envelope))
+ pidff_set_envelope_report(pidff, &effect->u.ramp.envelope);
break;
case FF_SPRING:
--
2.48.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v5 03/12] HID: pidff: Clamp PERIODIC effect period to device's logical range
2025-01-19 13:12 [PATCH v5 00/12] HID: Upgrade the generic pidff driver and add hid-universal-pidff Tomasz Pakuła
2025-01-19 13:12 ` [PATCH v5 01/12] HID: pidff: Convert infinite length from Linux API to PID standard Tomasz Pakuła
2025-01-19 13:12 ` [PATCH v5 02/12] HID: pidff: Do not send effect envelope if it's empty Tomasz Pakuła
@ 2025-01-19 13:12 ` Tomasz Pakuła
2025-01-19 13:12 ` [PATCH v5 04/12] HID: pidff: Add MISSING_DELAY quirk and its detection Tomasz Pakuła
` (8 subsequent siblings)
11 siblings, 0 replies; 20+ messages in thread
From: Tomasz Pakuła @ 2025-01-19 13:12 UTC (permalink / raw)
To: jikos, bentiss; +Cc: anssi.hannula, linux-input, linux-usb
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.
Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
---
drivers/hid/usbhid/hid-pidff.c | 36 +++++++++++++++++++++++++++++++++-
1 file changed, 35 insertions(+), 1 deletion(-)
diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
index cf8163d92ea4..7af7744e3cf2 100644
--- a/drivers/hid/usbhid/hid-pidff.c
+++ b/drivers/hid/usbhid/hid-pidff.c
@@ -205,6 +205,36 @@ static int pidff_rescale_signed(int i, struct hid_field *field)
field->logical_minimum / -0x8000;
}
+/*
+ * Clamp minimum value for the given field
+ */
+static int pidff_clamp_min(int i, struct hid_field *field)
+{
+ int ret = i < field->logical_minimum ? field->logical_minimum : i;
+ pr_debug("clamped min value from %d to %d\n", i, ret);
+ return ret;
+}
+
+/*
+ * Clamp maximum value for the given field
+ */
+static int pidff_clamp_max(int i, struct hid_field *field)
+{
+ int ret = i > field->logical_maximum ? field->logical_maximum : i;
+ pr_debug("clamped max value from %d to %d\n", i, ret);
+ return ret;
+}
+
+/*
+ * Clamp value for the given field
+ */
+static int pidff_clamp(int i, struct hid_field *field)
+{
+ i = pidff_clamp_min(i, field);
+ i = pidff_clamp_max(i, field);
+ return i;
+}
+
static void pidff_set(struct pidff_usage *usage, u16 value)
{
usage->value[0] = pidff_rescale(value, 0xffff, usage->field);
@@ -357,7 +387,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.48.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v5 04/12] HID: pidff: Add MISSING_DELAY quirk and its detection
2025-01-19 13:12 [PATCH v5 00/12] HID: Upgrade the generic pidff driver and add hid-universal-pidff Tomasz Pakuła
` (2 preceding siblings ...)
2025-01-19 13:12 ` [PATCH v5 03/12] HID: pidff: Clamp PERIODIC effect period to device's logical range Tomasz Pakuła
@ 2025-01-19 13:12 ` Tomasz Pakuła
2025-01-19 13:12 ` [PATCH v5 05/12] HID: pidff: Add MISSING_PBO " Tomasz Pakuła
` (7 subsequent siblings)
11 siblings, 0 replies; 20+ messages in thread
From: Tomasz Pakuła @ 2025-01-19 13:12 UTC (permalink / raw)
To: jikos, bentiss; +Cc: anssi.hannula, linux-input, linux-usb
A lot of devices do not include this field, and it's seldom used in force
feedback implementations. I tested about three dozen applications and
none of them make use of the delay.
This fixes initialization of a lot of PID wheels like Cammus, VRS, FFBeast
This change has no effect on fully compliant devices
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>
---
drivers/hid/usbhid/hid-pidff.c | 33 ++++++++++++++++++++++++++++-----
include/linux/hid.h | 3 +++
2 files changed, 31 insertions(+), 5 deletions(-)
diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
index 7af7744e3cf2..28f42f30e2b3 100644
--- a/drivers/hid/usbhid/hid-pidff.c
+++ b/drivers/hid/usbhid/hid-pidff.c
@@ -184,6 +184,8 @@ struct pidff_device {
int operation_id[sizeof(pidff_effect_operation_status)];
int pid_id[PID_EFFECTS_MAX];
+
+ u32 quirks;
};
/*
@@ -355,7 +357,10 @@ static void pidff_set_effect_report(struct pidff_device *pidff,
pidff->effect_direction->value[0] =
pidff_rescale(effect->direction, 0xffff,
pidff->effect_direction);
- pidff->set_effect[PID_START_DELAY].value[0] = effect->replay.delay;
+
+ // 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;
hid_hw_request(pidff->hid, pidff->reports[PID_SET_EFFECT],
HID_REQ_SET_REPORT);
@@ -778,7 +783,10 @@ static void pidff_autocenter(struct pidff_device *pidff, u16 magnitude)
pidff->set_effect[PID_TRIGGER_REPEAT_INT].value[0] = 0;
pidff_set(&pidff->set_effect[PID_GAIN], magnitude);
pidff->set_effect[PID_DIRECTION_ENABLE].value[0] = 1;
- pidff->set_effect[PID_START_DELAY].value[0] = 0;
+
+ // Omit setting delay field if it's missing
+ if (!(pidff->quirks & HID_PIDFF_QUIRK_MISSING_DELAY))
+ pidff->set_effect[PID_START_DELAY].value[0] = 0;
hid_hw_request(pidff->hid, pidff->reports[PID_SET_EFFECT],
HID_REQ_SET_REPORT);
@@ -801,6 +809,7 @@ static int pidff_find_fields(struct pidff_usage *usage, const u8 *table,
struct hid_report *report, int count, int strict)
{
int i, j, k, found;
+ int return_value = 0;
for (k = 0; k < count; k++) {
found = 0;
@@ -825,12 +834,17 @@ static int pidff_find_fields(struct pidff_usage *usage, const u8 *table,
if (found)
break;
}
- if (!found && strict) {
+ if (!found && table[k] == pidff_set_effect[PID_START_DELAY]) {
+ pr_debug("Delay field not found, but that's OK\n");
+ pr_debug("Setting MISSING_DELAY quirk\n");
+ return_value |= HID_PIDFF_QUIRK_MISSING_DELAY;
+ }
+ else if (!found && strict) {
pr_debug("failed to locate %d\n", k);
return -1;
}
}
- return 0;
+ return return_value;
}
/*
@@ -1105,11 +1119,19 @@ static int pidff_find_effects(struct pidff_device *pidff,
static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev)
{
int envelope_ok = 0;
+ int status = 0;
- if (PIDFF_FIND_FIELDS(set_effect, PID_SET_EFFECT, 1)) {
+ // Save info about the device not having the DELAY ffb field.
+ status = PIDFF_FIND_FIELDS(set_effect, PID_SET_EFFECT, 1);
+ if (status == -1) {
hid_err(pidff->hid, "unknown set_effect report layout\n");
return -ENODEV;
}
+ pidff->quirks |= status;
+
+ if (status & HID_PIDFF_QUIRK_MISSING_DELAY)
+ hid_dbg(pidff->hid, "Adding MISSING_DELAY quirk\n");
+
PIDFF_FIND_FIELDS(block_load, PID_BLOCK_LOAD, 0);
if (!pidff->block_load[PID_EFFECT_BLOCK_INDEX].value) {
@@ -1353,6 +1375,7 @@ int hid_pidff_init(struct hid_device *hid)
ff->playback = pidff_playback;
hid_info(dev, "Force feedback for USB HID PID devices by Anssi Hannula <anssi.hannula@gmail.com>\n");
+ hid_dbg(dev, "Active quirks mask: %x", pidff->quirks);
hid_device_io_stop(hid);
diff --git a/include/linux/hid.h b/include/linux/hid.h
index d11e9c9a5f15..94ad5a510639 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -1227,6 +1227,9 @@ int hid_pidff_init(struct hid_device *hid);
#define hid_pidff_init NULL
#endif
+/* HID PIDFF quirks */
+#define HID_PIDFF_QUIRK_MISSING_DELAY BIT(0)
+
#define dbg_hid(fmt, ...) pr_debug("%s: " fmt, __FILE__, ##__VA_ARGS__)
#define hid_err(hid, fmt, ...) \
--
2.48.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v5 05/12] HID: pidff: Add MISSING_PBO quirk and its detection
2025-01-19 13:12 [PATCH v5 00/12] HID: Upgrade the generic pidff driver and add hid-universal-pidff Tomasz Pakuła
` (3 preceding siblings ...)
2025-01-19 13:12 ` [PATCH v5 04/12] HID: pidff: Add MISSING_DELAY quirk and its detection Tomasz Pakuła
@ 2025-01-19 13:12 ` Tomasz Pakuła
2025-01-19 13:12 ` [PATCH v5 06/12] HID: pidff: Add MISSING_DEVICE_CONTROL quirk Tomasz Pakuła
` (6 subsequent siblings)
11 siblings, 0 replies; 20+ messages in thread
From: Tomasz Pakuła @ 2025-01-19 13:12 UTC (permalink / raw)
To: jikos, bentiss; +Cc: anssi.hannula, linux-input, linux-usb
Some devices with only one axis are missing PARAMETER_BLOCK_OFFSET field
for conditional effects. They can only have one axis, so we're limiting
the max_axis when setting the report for those effects.
Automatic detection ensures compatibility even if such device won't be
explicitly defined in the kernel.
Fixes initialization of VRS DirectForce PRO and possibly other devices.
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>
---
drivers/hid/usbhid/hid-pidff.c | 46 +++++++++++++++++++++-------------
include/linux/hid.h | 1 +
2 files changed, 30 insertions(+), 17 deletions(-)
diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
index 28f42f30e2b3..d792a07b5a5d 100644
--- a/drivers/hid/usbhid/hid-pidff.c
+++ b/drivers/hid/usbhid/hid-pidff.c
@@ -421,12 +421,19 @@ static int pidff_needs_set_periodic(struct ff_effect *effect,
static void pidff_set_condition_report(struct pidff_device *pidff,
struct ff_effect *effect)
{
- int i;
+ unsigned char i;
+
+ // Devices missing Parameter Block Offset can only have one axis
+ unsigned char max_axis = pidff->quirks & HID_PIDFF_QUIRK_MISSING_PBO ? 1 : 2;
pidff->set_condition[PID_EFFECT_BLOCK_INDEX].value[0] =
pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0];
- for (i = 0; i < 2; i++) {
+ for (i = 0; i < max_axis; i++) {
+ // Omit Parameter Block Offset if missing
+ if (!(pidff->quirks & HID_PIDFF_QUIRK_MISSING_PBO))
+ pidff->set_condition[PID_PARAM_BLOCK_OFFSET].value[0] = i;
+
pidff->set_condition[PID_PARAM_BLOCK_OFFSET].value[0] = i;
pidff_set_signed(&pidff->set_condition[PID_CP_OFFSET],
effect->u.condition[i].center);
@@ -839,6 +846,11 @@ static int pidff_find_fields(struct pidff_usage *usage, const u8 *table,
pr_debug("Setting MISSING_DELAY quirk\n");
return_value |= HID_PIDFF_QUIRK_MISSING_DELAY;
}
+ else if (!found && table[k] == pidff_set_condition[PID_PARAM_BLOCK_OFFSET]) {
+ pr_debug("PBO field not found, but that's OK\n");
+ pr_debug("Setting MISSING_PBO quirk\n");
+ return_value |= HID_PIDFF_QUIRK_MISSING_PBO;
+ }
else if (!found && strict) {
pr_debug("failed to locate %d\n", k);
return -1;
@@ -1118,7 +1130,6 @@ static int pidff_find_effects(struct pidff_device *pidff,
*/
static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev)
{
- int envelope_ok = 0;
int status = 0;
// Save info about the device not having the DELAY ffb field.
@@ -1149,13 +1160,10 @@ static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev)
return -ENODEV;
}
- if (!PIDFF_FIND_FIELDS(set_envelope, PID_SET_ENVELOPE, 1))
- envelope_ok = 1;
-
if (pidff_find_special_fields(pidff) || pidff_find_effects(pidff, dev))
return -ENODEV;
- if (!envelope_ok) {
+ if (PIDFF_FIND_FIELDS(set_envelope, PID_SET_ENVELOPE, 1)) {
if (test_and_clear_bit(FF_CONSTANT, dev->ffbit))
hid_warn(pidff->hid,
"has constant effect but no envelope\n");
@@ -1180,16 +1188,20 @@ static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev)
clear_bit(FF_RAMP, dev->ffbit);
}
- if ((test_bit(FF_SPRING, dev->ffbit) ||
- test_bit(FF_DAMPER, dev->ffbit) ||
- test_bit(FF_FRICTION, dev->ffbit) ||
- test_bit(FF_INERTIA, dev->ffbit)) &&
- PIDFF_FIND_FIELDS(set_condition, PID_SET_CONDITION, 1)) {
- hid_warn(pidff->hid, "unknown condition effect layout\n");
- clear_bit(FF_SPRING, dev->ffbit);
- clear_bit(FF_DAMPER, dev->ffbit);
- clear_bit(FF_FRICTION, dev->ffbit);
- clear_bit(FF_INERTIA, dev->ffbit);
+ if (test_bit(FF_SPRING, dev->ffbit) ||
+ test_bit(FF_DAMPER, dev->ffbit) ||
+ test_bit(FF_FRICTION, dev->ffbit) ||
+ test_bit(FF_INERTIA, dev->ffbit)) {
+ status = PIDFF_FIND_FIELDS(set_condition, PID_SET_CONDITION, 1);
+
+ if (status < 0) {
+ hid_warn(pidff->hid, "unknown condition effect layout\n");
+ clear_bit(FF_SPRING, dev->ffbit);
+ clear_bit(FF_DAMPER, dev->ffbit);
+ clear_bit(FF_FRICTION, dev->ffbit);
+ clear_bit(FF_INERTIA, dev->ffbit);
+ }
+ pidff->quirks |= status;
}
if (test_bit(FF_PERIODIC, dev->ffbit) &&
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 94ad5a510639..29f0a91f505f 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -1229,6 +1229,7 @@ int hid_pidff_init(struct hid_device *hid);
/* HID PIDFF quirks */
#define HID_PIDFF_QUIRK_MISSING_DELAY BIT(0)
+#define HID_PIDFF_QUIRK_MISSING_PBO BIT(1)
#define dbg_hid(fmt, ...) pr_debug("%s: " fmt, __FILE__, ##__VA_ARGS__)
--
2.48.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v5 06/12] HID: pidff: Add MISSING_DEVICE_CONTROL quirk
2025-01-19 13:12 [PATCH v5 00/12] HID: Upgrade the generic pidff driver and add hid-universal-pidff Tomasz Pakuła
` (4 preceding siblings ...)
2025-01-19 13:12 ` [PATCH v5 05/12] HID: pidff: Add MISSING_PBO " Tomasz Pakuła
@ 2025-01-19 13:12 ` Tomasz Pakuła
2025-01-19 13:12 ` [PATCH v5 07/12] HID: pidff: Add hid_pidff_init_with_quirks and export as GPL symbol Tomasz Pakuła
` (5 subsequent siblings)
11 siblings, 0 replies; 20+ messages in thread
From: Tomasz Pakuła @ 2025-01-19 13:12 UTC (permalink / raw)
To: jikos, bentiss; +Cc: anssi.hannula, linux-input, linux-usb
With this quirk, a PID device isn't required to have
the PID_DEVICE_CONTROL field available.
Some devices like VRS Direct Force Pro do not implement PID_DEVICE_CONTROL
in their descriptors while still having the necessary control fields like
PID_ENABLE_ACTUATORS or PID_RESET.
Fixes initialization of VRS Direct Force Pro
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>
---
drivers/hid/usbhid/hid-pidff.c | 3 ++-
include/linux/hid.h | 5 +++--
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
index d792a07b5a5d..53b16a4e54a6 100644
--- a/drivers/hid/usbhid/hid-pidff.c
+++ b/drivers/hid/usbhid/hid-pidff.c
@@ -1000,7 +1000,8 @@ static int pidff_find_special_fields(struct pidff_device *pidff)
0x57, 0);
pidff->device_control =
pidff_find_special_field(pidff->reports[PID_DEVICE_CONTROL],
- 0x96, 1);
+ 0x96, pidff->quirks & HID_PIDFF_QUIRK_MISSING_DEVICE_CONTROL ? 0 : 1);
+
pidff->block_load_status =
pidff_find_special_field(pidff->reports[PID_BLOCK_LOAD],
0x8b, 1);
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 29f0a91f505f..2af9db0296d1 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -1228,8 +1228,9 @@ int hid_pidff_init(struct hid_device *hid);
#endif
/* HID PIDFF quirks */
-#define HID_PIDFF_QUIRK_MISSING_DELAY BIT(0)
-#define HID_PIDFF_QUIRK_MISSING_PBO BIT(1)
+#define HID_PIDFF_QUIRK_MISSING_DELAY BIT(0)
+#define HID_PIDFF_QUIRK_MISSING_PBO BIT(1)
+#define HID_PIDFF_QUIRK_MISSING_DEVICE_CONTROL BIT(2)
#define dbg_hid(fmt, ...) pr_debug("%s: " fmt, __FILE__, ##__VA_ARGS__)
--
2.48.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v5 07/12] HID: pidff: Add hid_pidff_init_with_quirks and export as GPL symbol
2025-01-19 13:12 [PATCH v5 00/12] HID: Upgrade the generic pidff driver and add hid-universal-pidff Tomasz Pakuła
` (5 preceding siblings ...)
2025-01-19 13:12 ` [PATCH v5 06/12] HID: pidff: Add MISSING_DEVICE_CONTROL quirk Tomasz Pakuła
@ 2025-01-19 13:12 ` Tomasz Pakuła
2025-01-19 13:12 ` [PATCH v5 08/12] HID: pidff: Add FIX_WHEEL_DIRECTION quirk Tomasz Pakuła
` (4 subsequent siblings)
11 siblings, 0 replies; 20+ messages in thread
From: Tomasz Pakuła @ 2025-01-19 13:12 UTC (permalink / raw)
To: jikos, bentiss; +Cc: anssi.hannula, linux-input, linux-usb
This lays out a way to provide an initial set of quirks to enable before
device initialization takes place. GPL symbol export needed for the
possibility of building HID drivers which use this function as modules.
Adding a wrapper function to ensure compatibility with the old behavior
of hid_pidff_init.
Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
---
drivers/hid/usbhid/hid-pidff.c | 15 ++++++++++++++-
include/linux/hid.h | 2 ++
2 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
index 53b16a4e54a6..5a328860685b 100644
--- a/drivers/hid/usbhid/hid-pidff.c
+++ b/drivers/hid/usbhid/hid-pidff.c
@@ -1299,8 +1299,9 @@ 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(struct hid_device *hid)
+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,
@@ -1322,6 +1323,7 @@ int hid_pidff_init(struct hid_device *hid)
return -ENOMEM;
pidff->hid = hid;
+ pidff->quirks = initial_quirks;
hid_device_io_start(hid);
@@ -1400,3 +1402,14 @@ int hid_pidff_init(struct hid_device *hid)
kfree(pidff);
return error;
}
+EXPORT_SYMBOL_GPL(hid_pidff_init_with_quirks);
+
+/*
+ * Check if the device is PID and initialize it
+ * Wrapper made to keep the compatibility with old
+ * init function
+ */
+int hid_pidff_init(struct hid_device *hid)
+{
+ return hid_pidff_init_with_quirks(hid, 0);
+}
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 2af9db0296d1..93233c5b75a6 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -1223,8 +1223,10 @@ 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 */
--
2.48.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v5 08/12] HID: pidff: Add FIX_WHEEL_DIRECTION quirk
2025-01-19 13:12 [PATCH v5 00/12] HID: Upgrade the generic pidff driver and add hid-universal-pidff Tomasz Pakuła
` (6 preceding siblings ...)
2025-01-19 13:12 ` [PATCH v5 07/12] HID: pidff: Add hid_pidff_init_with_quirks and export as GPL symbol Tomasz Pakuła
@ 2025-01-19 13:12 ` Tomasz Pakuła
2025-01-19 13:13 ` [PATCH v5 09/12] HID: pidff: Stop all effects before enabling actuators Tomasz Pakuła
` (3 subsequent siblings)
11 siblings, 0 replies; 20+ messages in thread
From: Tomasz Pakuła @ 2025-01-19 13:12 UTC (permalink / raw)
To: jikos, bentiss; +Cc: anssi.hannula, linux-input, linux-usb
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 -> 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>
---
drivers/hid/usbhid/hid-pidff.c | 12 +++++++++---
include/linux/hid.h | 1 +
2 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
index 5a328860685b..6b4c4ecf4943 100644
--- a/drivers/hid/usbhid/hid-pidff.c
+++ b/drivers/hid/usbhid/hid-pidff.c
@@ -136,6 +136,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;
@@ -354,9 +357,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))
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 93233c5b75a6..5237f9040950 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -1233,6 +1233,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_MISSING_DEVICE_CONTROL BIT(2)
+#define HID_PIDFF_QUIRK_FIX_WHEEL_DIRECTION BIT(3)
#define dbg_hid(fmt, ...) pr_debug("%s: " fmt, __FILE__, ##__VA_ARGS__)
--
2.48.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v5 09/12] HID: pidff: Stop all effects before enabling actuators
2025-01-19 13:12 [PATCH v5 00/12] HID: Upgrade the generic pidff driver and add hid-universal-pidff Tomasz Pakuła
` (7 preceding siblings ...)
2025-01-19 13:12 ` [PATCH v5 08/12] HID: pidff: Add FIX_WHEEL_DIRECTION quirk Tomasz Pakuła
@ 2025-01-19 13:13 ` Tomasz Pakuła
2025-01-21 10:10 ` Oliver Neukum
2025-01-19 13:13 ` [PATCH v5 10/12] HID: Add hid-universal-pidff driver and supported device ids Tomasz Pakuła
` (2 subsequent siblings)
11 siblings, 1 reply; 20+ messages in thread
From: Tomasz Pakuła @ 2025-01-19 13:13 UTC (permalink / raw)
To: jikos, bentiss; +Cc: anssi.hannula, linux-input, linux-usb
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
Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
---
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 6b4c4ecf4943..25ae80f68507 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
@@ -1240,6 +1241,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.48.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v5 10/12] HID: Add hid-universal-pidff driver and supported device ids
2025-01-19 13:12 [PATCH v5 00/12] HID: Upgrade the generic pidff driver and add hid-universal-pidff Tomasz Pakuła
` (8 preceding siblings ...)
2025-01-19 13:13 ` [PATCH v5 09/12] HID: pidff: Stop all effects before enabling actuators Tomasz Pakuła
@ 2025-01-19 13:13 ` Tomasz Pakuła
2025-01-19 13:13 ` [PATCH v5 11/12] MAINTAINERS: Add entry for hid-universal-pidff driver Tomasz Pakuła
2025-01-19 13:13 ` [PATCH v5 12/12] HID: pidff: Add PERIODIC_SINE_ONLY quirk Tomasz Pakuła
11 siblings, 0 replies; 20+ messages in thread
From: Tomasz Pakuła @ 2025-01-19 13:13 UTC (permalink / raw)
To: jikos, bentiss; +Cc: anssi.hannula, linux-input, linux-usb
Extend pidff compatibility, usable button range, fix
device descriptors, manage pidff quirks and set improved
fuzz/flat default for high precision devices.
As many of PID devices are quite similar and not dependent on
custom drivers, this one can handle all of PID devices which
need special care.
Numerous sim racing/sim flight bases report a lot of buttons
in excess of 100. Moza Racing exposes 128 of them and thus
the need to extend the available range.
All the included devices were tested and confirmed working
with the help of the sim racing community.
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>
---
drivers/hid/Kconfig | 14 +++
drivers/hid/Makefile | 1 +
drivers/hid/hid-ids.h | 29 +++++
drivers/hid/hid-universal-pidff.c | 188 ++++++++++++++++++++++++++++++
4 files changed, 232 insertions(+)
create mode 100644 drivers/hid/hid-universal-pidff.c
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 4d2a89d65b65..59d8da16f5b4 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -1217,6 +1217,20 @@ config HID_U2FZERO
allow setting the brightness to anything but 1, which will
trigger a single blink and immediately reset back to 0.
+config HID_UNIVERSAL_PIDFF
+ tristate "universal-pidff: extended USB PID driver compatibility and usage"
+ depends on USB_HID
+ depends on HID_PID
+ help
+ Extended PID support for selected devices.
+
+ Contains report fixups, extended usable button range and
+ pidff quirk management to extend compatibility with slightly
+ non-compliant USB PID devices and better fuzz/flat values for
+ high precision direct drive devices.
+
+ Supports Moza Racing, Cammus, VRS, FFBeast and more.
+
config HID_WACOM
tristate "Wacom Intuos/Graphire tablet support (USB)"
depends on USB_HID
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 24de45f3677d..919d6a146077 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -140,6 +140,7 @@ hid-uclogic-objs := hid-uclogic-core.o \
hid-uclogic-params.o
obj-$(CONFIG_HID_UCLOGIC) += hid-uclogic.o
obj-$(CONFIG_HID_UDRAW_PS3) += hid-udraw-ps3.o
+obj-$(CONFIG_HID_UNIVERSAL_PIDFF) += hid-universal-pidff.o
obj-$(CONFIG_HID_LED) += hid-led.o
obj-$(CONFIG_HID_XIAOMI) += hid-xiaomi.o
obj-$(CONFIG_HID_XINMO) += hid-xinmo.o
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 1f47fda809b9..af74dbca69fd 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -261,6 +261,10 @@
#define USB_DEVICE_ID_BTC_EMPREX_REMOTE 0x5578
#define USB_DEVICE_ID_BTC_EMPREX_REMOTE_2 0x5577
+#define USB_VENDOR_ID_CAMMUS 0x3416
+#define USB_DEVICE_ID_CAMMUS_C5 0x0301
+#define USB_DEVICE_ID_CAMMUS_C12 0x0302
+
#define USB_VENDOR_ID_CANDO 0x2087
#define USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH 0x0703
#define USB_DEVICE_ID_CANDO_MULTI_TOUCH 0x0a01
@@ -452,6 +456,11 @@
#define USB_VENDOR_ID_EVISION 0x320f
#define USB_DEVICE_ID_EVISION_ICL01 0x5041
+#define USB_VENDOR_ID_FFBEAST 0x045b
+#define USB_DEVICE_ID_FFBEAST_JOYSTICK 0x58f9
+#define USB_DEVICE_ID_FFBEAST_RUDDER 0x5968
+#define USB_DEVICE_ID_FFBEAST_WHEEL 0x59d7
+
#define USB_VENDOR_ID_FLATFROG 0x25b5
#define USB_DEVICE_ID_MULTITOUCH_3200 0x0002
@@ -817,6 +826,11 @@
#define I2C_DEVICE_ID_LG_8001 0x8001
#define I2C_DEVICE_ID_LG_7010 0x7010
+#define USB_VENDOR_ID_LITE_STAR 0x11ff
+#define USB_DEVICE_ID_PXN_V12 0x1212
+#define USB_DEVICE_ID_PXN_V12_LITE 0x1112
+#define USB_DEVICE_ID_PXN_V12_LITE_2 0x1211
+
#define USB_VENDOR_ID_LOGITECH 0x046d
#define USB_DEVICE_ID_LOGITECH_Z_10_SPK 0x0a07
#define USB_DEVICE_ID_LOGITECH_AUDIOHUB 0x0a0e
@@ -964,6 +978,18 @@
#define USB_VENDOR_ID_MONTEREY 0x0566
#define USB_DEVICE_ID_GENIUS_KB29E 0x3004
+#define USB_VENDOR_ID_MOZA 0x346e
+#define USB_DEVICE_ID_MOZA_R3 0x0005
+#define USB_DEVICE_ID_MOZA_R5 0x0004
+#define USB_DEVICE_ID_MOZA_R9 0x0002
+#define USB_DEVICE_ID_MOZA_R12 0x0006
+#define USB_DEVICE_ID_MOZA_R16_R21 0x0000
+#define USB_DEVICE_ID_MOZA_R3_ALT 0x0015
+#define USB_DEVICE_ID_MOZA_R5_ALT 0x0014
+#define USB_DEVICE_ID_MOZA_R9_ALT 0x0012
+#define USB_DEVICE_ID_MOZA_R12_ALT 0x0016
+#define USB_DEVICE_ID_MOZA_R16_R21_ALT 0x0010
+
#define USB_VENDOR_ID_MSI 0x1770
#define USB_DEVICE_ID_MSI_GT683R_LED_PANEL 0xff00
@@ -1373,6 +1399,9 @@
#define USB_DEVICE_ID_VELLEMAN_K8061_FIRST 0x8061
#define USB_DEVICE_ID_VELLEMAN_K8061_LAST 0x8068
+#define USB_VENDOR_ID_VRS 0x0483
+#define USB_DEVICE_ID_VRS_DFP 0xa355
+
#define USB_VENDOR_ID_VTL 0x0306
#define USB_DEVICE_ID_VTL_MULTITOUCH_FF3F 0xff3f
diff --git a/drivers/hid/hid-universal-pidff.c b/drivers/hid/hid-universal-pidff.c
new file mode 100644
index 000000000000..0f81df9a019b
--- /dev/null
+++ b/drivers/hid/hid-universal-pidff.c
@@ -0,0 +1,188 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * HID UNIVERSAL PIDFF
+ * hid-pidff wrapper for PID-enabled devices
+ * Handles device reports, quirks and extends usable button range
+ *
+ * Copyright (c) 2024 Makarenko Oleg
+ * Copyright (c) 2024 Tomasz Pakuła
+ */
+
+#include <linux/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+#include <linux/input-event-codes.h>
+#include "hid-ids.h"
+
+#define JOY_RANGE (BTN_DEAD - BTN_JOYSTICK + 1)
+
+static const u8 *moza_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize)
+{
+ // Fix data type on PID Device Control
+ if (rdesc[1002] == 0x91 && rdesc[1003] == 0x02) {
+ rdesc[1003] = 0x00; // Fix header, it needs to be Array.
+ }
+ return rdesc;
+}
+
+
+static const u8 *universal_pidff_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+ unsigned int *rsize)
+{
+ if (hdev->vendor == USB_VENDOR_ID_MOZA) {
+ return moza_report_fixup(hdev, rdesc, rsize);
+ }
+ return rdesc;
+}
+
+/*
+ * Map buttons manually to extend the default joystick buttn limit
+ */
+static int universal_pidff_input_mapping(struct hid_device *hdev,
+ struct hid_input *hi, struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ // Let the default behavior handle mapping if usage is not a button
+ if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON)
+ return 0;
+
+ int button = ((usage->hid - 1) & HID_USAGE);
+ int code = button + BTN_JOYSTICK;
+
+ // Detect the end of JOYSTICK buttons range
+ // KEY_NEXT_FAVORITE = 0x270
+ if (code > BTN_DEAD)
+ code = button + KEY_NEXT_FAVORITE - JOY_RANGE;
+
+ // Map overflowing buttons to KEY_RESERVED to not ignore
+ // them and let them still trigger MSC_SCAN
+ if (code > KEY_MAX)
+ code = KEY_RESERVED;
+
+ hid_map_usage(hi, usage, bit, max, EV_KEY, code);
+ hid_dbg(hdev, "Button %d: usage %d", button, code);
+ return 1;
+}
+
+
+/*
+ * Check if the device is PID and initialize it
+ * Add quirks after initialisation
+ */
+static int universal_pidff_probe(struct hid_device *hdev,
+ const struct hid_device_id *id)
+{
+ int error;
+ error = hid_parse(hdev);
+ if (error) {
+ hid_err(hdev, "HID parse failed\n");
+ goto err;
+ }
+
+ error = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
+ if (error) {
+ hid_err(hdev, "HID hw start failed\n");
+ goto err;
+ }
+
+ // Check if HID_PID support is enabled
+ int (*init_function)(struct hid_device *, __u32);
+ init_function = hid_pidff_init_with_quirks;
+
+ if (!init_function) {
+ hid_warn(hdev, "HID_PID support not enabled!\n");
+ return 0;
+ }
+
+ error = init_function(hdev, id->driver_data);
+ if (error) {
+ hid_warn(hdev, "Force Feedback initialization failed\n");
+ goto err;
+ }
+
+ hid_info(hdev, "Universal pidff driver loaded sucesfully!");
+
+ return 0;
+err:
+ return error;
+}
+
+static int universal_pidff_input_configured(struct hid_device *hdev,
+ struct hid_input *hidinput)
+{
+ // Remove fuzz and deadzone from the wheel/joystick axis
+ struct input_dev *input = hidinput->input;
+ input_set_abs_params(input, ABS_X,
+ input->absinfo[ABS_X].minimum, input->absinfo[ABS_X].maximum, 0, 0);
+
+ // Decrease fuzz and deadzone on additional axes
+ // Default Linux values are 255 for fuzz and 4096 for flat (deadzone)
+ int axis;
+ for (axis = ABS_Y; axis <= ABS_BRAKE; axis++) {
+ if (!test_bit(axis, input->absbit))
+ continue;
+
+ input_set_abs_params(input, axis,
+ input->absinfo[axis].minimum,
+ input->absinfo[axis].maximum, 8, 0);
+ }
+
+ // Remove fuzz and deadzone from the second joystick axis
+ if (hdev->vendor == USB_VENDOR_ID_FFBEAST &&
+ hdev->product == USB_DEVICE_ID_FFBEAST_JOYSTICK)
+ input_set_abs_params(input, ABS_Y,
+ input->absinfo[ABS_Y].minimum,
+ input->absinfo[ABS_Y].maximum, 0, 0);
+
+ return 0;
+}
+
+static const struct hid_device_id universal_pidff_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R3),
+ .driver_data = HID_PIDFF_QUIRK_FIX_WHEEL_DIRECTION },
+ { HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R5),
+ .driver_data = HID_PIDFF_QUIRK_FIX_WHEEL_DIRECTION },
+ { HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R9),
+ .driver_data = HID_PIDFF_QUIRK_FIX_WHEEL_DIRECTION },
+ { HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R12),
+ .driver_data = HID_PIDFF_QUIRK_FIX_WHEEL_DIRECTION },
+ { HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R16_R21),
+ .driver_data = HID_PIDFF_QUIRK_FIX_WHEEL_DIRECTION },
+ { HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R3_ALT),
+ .driver_data = HID_PIDFF_QUIRK_FIX_WHEEL_DIRECTION },
+ { HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R5_ALT),
+ .driver_data = HID_PIDFF_QUIRK_FIX_WHEEL_DIRECTION },
+ { HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R9_ALT),
+ .driver_data = HID_PIDFF_QUIRK_FIX_WHEEL_DIRECTION },
+ { HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R12_ALT),
+ .driver_data = HID_PIDFF_QUIRK_FIX_WHEEL_DIRECTION },
+ { HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R16_R21_ALT),
+ .driver_data = HID_PIDFF_QUIRK_FIX_WHEEL_DIRECTION },
+ { HID_USB_DEVICE(USB_VENDOR_ID_CAMMUS, USB_DEVICE_ID_CAMMUS_C5) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_CAMMUS, USB_DEVICE_ID_CAMMUS_C12) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_VRS, USB_DEVICE_ID_VRS_DFP),
+ .driver_data = HID_PIDFF_QUIRK_MISSING_DEVICE_CONTROL },
+ { HID_USB_DEVICE(USB_VENDOR_ID_FFBEAST, USB_DEVICE_ID_FFBEAST_JOYSTICK), },
+ { HID_USB_DEVICE(USB_VENDOR_ID_FFBEAST, USB_DEVICE_ID_FFBEAST_RUDDER), },
+ { HID_USB_DEVICE(USB_VENDOR_ID_FFBEAST, USB_DEVICE_ID_FFBEAST_WHEEL) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_ID_PXN_V12) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_ID_PXN_V12_LITE) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_ID_PXN_V12_LITE_2) },
+ { }
+};
+MODULE_DEVICE_TABLE(hid, universal_pidff_devices);
+
+static struct hid_driver universal_pidff = {
+ .name = "hid-universal-pidff",
+ .id_table = universal_pidff_devices,
+ .input_mapping = universal_pidff_input_mapping,
+ .probe = universal_pidff_probe,
+ .input_configured = universal_pidff_input_configured,
+ .report_fixup = universal_pidff_report_fixup
+};
+module_hid_driver(universal_pidff);
+
+MODULE_DESCRIPTION("Universal driver for PID Force Feedback devices");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Makarenko Oleg <oleg@makarenk.ooo>");
+MODULE_AUTHOR("Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>");
--
2.48.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v5 11/12] MAINTAINERS: Add entry for hid-universal-pidff driver
2025-01-19 13:12 [PATCH v5 00/12] HID: Upgrade the generic pidff driver and add hid-universal-pidff Tomasz Pakuła
` (9 preceding siblings ...)
2025-01-19 13:13 ` [PATCH v5 10/12] HID: Add hid-universal-pidff driver and supported device ids Tomasz Pakuła
@ 2025-01-19 13:13 ` Tomasz Pakuła
2025-01-19 13:13 ` [PATCH v5 12/12] HID: pidff: Add PERIODIC_SINE_ONLY quirk Tomasz Pakuła
11 siblings, 0 replies; 20+ messages in thread
From: Tomasz Pakuła @ 2025-01-19 13:13 UTC (permalink / raw)
To: jikos, bentiss; +Cc: anssi.hannula, linux-input, linux-usb
Add the MAINTAINERS entries for the driver
---
MAINTAINERS | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 910305c11e8a..0a6ee05b6467 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -10212,6 +10212,12 @@ F: drivers/hid/hid-sensor-*
F: drivers/iio/*/hid-*
F: include/linux/hid-sensor-*
+HID UNIVERSAL PIDFF DRIVER
+M: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
+L: linux-input@vger.kernel.org
+S: Maintained
+F: drivers/hid/hid-universal-pidff.c
+
HID VRC-2 CAR CONTROLLER DRIVER
M: Marcus Folkesson <marcus.folkesson@gmail.com>
L: linux-input@vger.kernel.org
--
2.48.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v5 12/12] HID: pidff: Add PERIODIC_SINE_ONLY quirk
2025-01-19 13:12 [PATCH v5 00/12] HID: Upgrade the generic pidff driver and add hid-universal-pidff Tomasz Pakuła
` (10 preceding siblings ...)
2025-01-19 13:13 ` [PATCH v5 11/12] MAINTAINERS: Add entry for hid-universal-pidff driver Tomasz Pakuła
@ 2025-01-19 13:13 ` Tomasz Pakuła
11 siblings, 0 replies; 20+ messages in thread
From: Tomasz Pakuła @ 2025-01-19 13:13 UTC (permalink / raw)
To: jikos, bentiss; +Cc: anssi.hannula, linux-input, linux-usb
Some devices only support SINE periodic effect although they advertise
support for all PERIODIC effect in their HID descriptor. Some just do
nothing when trying to play such an effect (upload goes fine), some express
undefined behavior like turning to one side.
This quirk forces all the periodic effects to be uploaded as SINE. This is
acceptable as all these effects are similar in nature and are mostly used as
rumble. SINE is the most popular with others seldom used (especially SAW_UP
and SAW_DOWN).
Fixes periodic effects for PXN and LITE STAR wheels
---
drivers/hid/hid-universal-pidff.c | 9 ++++++---
drivers/hid/usbhid/hid-pidff.c | 3 +++
include/linux/hid.h | 1 +
3 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/drivers/hid/hid-universal-pidff.c b/drivers/hid/hid-universal-pidff.c
index 0f81df9a019b..c0f890e21521 100644
--- a/drivers/hid/hid-universal-pidff.c
+++ b/drivers/hid/hid-universal-pidff.c
@@ -165,9 +165,12 @@ static const struct hid_device_id universal_pidff_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_FFBEAST, USB_DEVICE_ID_FFBEAST_JOYSTICK), },
{ HID_USB_DEVICE(USB_VENDOR_ID_FFBEAST, USB_DEVICE_ID_FFBEAST_RUDDER), },
{ HID_USB_DEVICE(USB_VENDOR_ID_FFBEAST, USB_DEVICE_ID_FFBEAST_WHEEL) },
- { HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_ID_PXN_V12) },
- { HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_ID_PXN_V12_LITE) },
- { HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_ID_PXN_V12_LITE_2) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_ID_PXN_V12),
+ .driver_data = HID_PIDFF_QUIRK_PERIODIC_SINE_ONLY },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_ID_PXN_V12_LITE),
+ .driver_data = HID_PIDFF_QUIRK_PERIODIC_SINE_ONLY },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_ID_PXN_V12_LITE_2),
+ .driver_data = HID_PIDFF_QUIRK_PERIODIC_SINE_ONLY },
{ }
};
MODULE_DEVICE_TABLE(hid, universal_pidff_devices);
diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
index 25ae80f68507..8c4eda67bdb0 100644
--- a/drivers/hid/usbhid/hid-pidff.c
+++ b/drivers/hid/usbhid/hid-pidff.c
@@ -669,6 +669,9 @@ static int pidff_upload_effect(struct input_dev *dev, struct ff_effect *effect,
return -EINVAL;
}
+ if (pidff->quirks & HID_PIDFF_QUIRK_PERIODIC_SINE_ONLY)
+ type_id = PID_SINE;
+
error = pidff_request_effect_upload(pidff,
pidff->type_id[type_id]);
if (error)
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 5237f9040950..fbc1b6e46e0a 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -1234,6 +1234,7 @@ int hid_pidff_init_with_quirks(struct hid_device *hid, __u32 initial_quirks);
#define HID_PIDFF_QUIRK_MISSING_PBO BIT(1)
#define HID_PIDFF_QUIRK_MISSING_DEVICE_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__)
--
2.48.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH v5 02/12] HID: pidff: Do not send effect envelope if it's empty
2025-01-19 13:12 ` [PATCH v5 02/12] HID: pidff: Do not send effect envelope if it's empty Tomasz Pakuła
@ 2025-01-21 9:59 ` Oliver Neukum
2025-01-21 10:17 ` Tomasz Pakuła
0 siblings, 1 reply; 20+ messages in thread
From: Oliver Neukum @ 2025-01-21 9:59 UTC (permalink / raw)
To: Tomasz Pakuła, jikos, bentiss; +Cc: anssi.hannula, linux-input, linux-usb
On 19.01.25 14:12, Tomasz Pakuła wrote:
> Envelope struct is always initialized, but the envelope itself is
> optional as described in USB PID Device class definition 1.0.
>
> 5.1.1.1 Type Specific Block Offsets
> ...
> 4) Effects that do not use Condition Blocks use 1 Parameter Block and
> an *optional* Envelope Block.
>
> Sending out "empty" envelope breaks force feedback on some devices with
> games that use SINE effect + offset to emulate constant force effect, as
> well as generally breaking Constant/Periodic effects. One of the affected
> brands is Moza Racing.
[..]
> @@ -261,10 +261,19 @@ static void pidff_set_envelope_report(struct pidff_device *pidff,
> static int pidff_needs_set_envelope(struct ff_envelope *envelope,
> struct ff_envelope *old)
> {
> - return envelope->attack_level != old->attack_level ||
> - envelope->fade_level != old->fade_level ||
> + bool needs_new_envelope;
> + needs_new_envelope = envelope->attack_level != 0 ||
> + envelope->fade_level != 0 ||
> + envelope->attack_length != 0 ||
> + envelope->fade_length != 0;
> +
> + if (!needs_new_envelope || !old)
> + return needs_new_envelope;
I am afraid this is the most convoluted piece of boolean algebra I've seen
in a long time. In particular because it mixes things that do not belong together.
Regards
Oliver
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v5 09/12] HID: pidff: Stop all effects before enabling actuators
2025-01-19 13:13 ` [PATCH v5 09/12] HID: pidff: Stop all effects before enabling actuators Tomasz Pakuła
@ 2025-01-21 10:10 ` Oliver Neukum
2025-01-21 13:18 ` Tomasz Pakuła
2025-01-22 1:37 ` Tomasz Pakuła
0 siblings, 2 replies; 20+ messages in thread
From: Oliver Neukum @ 2025-01-21 10:10 UTC (permalink / raw)
To: Tomasz Pakuła, jikos, bentiss; +Cc: anssi.hannula, linux-input, linux-usb
On 19.01.25 14:13, Tomasz Pakuła wrote:
> 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
Hi,
it seems to me that the same thing would happen upon resumption
from S4. Will this be handled?
Regards
Oliver
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v5 02/12] HID: pidff: Do not send effect envelope if it's empty
2025-01-21 9:59 ` Oliver Neukum
@ 2025-01-21 10:17 ` Tomasz Pakuła
2025-01-21 13:01 ` Oliver Neukum
0 siblings, 1 reply; 20+ messages in thread
From: Tomasz Pakuła @ 2025-01-21 10:17 UTC (permalink / raw)
To: Oliver Neukum; +Cc: jikos, bentiss, anssi.hannula, linux-input, linux-usb, oleg
On Tue, 21 Jan 2025 at 10:59, Oliver Neukum <oneukum@suse.com> wrote:
> I am afraid this is the most convoluted piece of boolean algebra I've seen
> in a long time. In particular because it mixes things that do not belong together.
Could you elaborate on that? What here does not belong?
I think the diff is a bit unfortunate and doesn't make it justice, but
this is based on
code that was already there. Instead of just checking if the new
values differ from
old values, we first check if any values are different from 0. If
neither are != 0 OR
the effect didn't contain an envelope previously (NULL here), we
return the value
of the check.
Only if envelope isn't empty and if the effect already had an
envelope, we compare
the new and old values to decide if we need to send an envelope to the device.
if (!needs_new_envelope || !old)
return needs_new_envelope;
Could be represented as:
if (!needs_new_envelope)
// empty envelope
return 0;
if (!old)
// effect doesn't have an envelope yet
return needs_new_envelope;
The last part works exactly as it did before.
Just to make sure we're on the same page here, here's the resulting code:
static int pidff_needs_set_envelope(struct ff_envelope *envelope,
struct ff_envelope *old)
{
bool needs_new_envelope;
needs_new_envelope = envelope->attack_level != 0 ||
envelope->fade_level != 0 ||
envelope->attack_length != 0 ||
envelope->fade_length != 0;
if (!needs_new_envelope || !old)
return needs_new_envelope;
return envelope->attack_level != old->attack_level ||
envelope->fade_level != old->fade_level ||
envelope->attack_length != old->attack_length ||
envelope->fade_length != old->fade_length;
}
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v5 02/12] HID: pidff: Do not send effect envelope if it's empty
2025-01-21 10:17 ` Tomasz Pakuła
@ 2025-01-21 13:01 ` Oliver Neukum
2025-01-21 13:15 ` Tomasz Pakuła
0 siblings, 1 reply; 20+ messages in thread
From: Oliver Neukum @ 2025-01-21 13:01 UTC (permalink / raw)
To: Tomasz Pakuła, Oliver Neukum
Cc: jikos, bentiss, anssi.hannula, linux-input, linux-usb, oleg
On 21.01.25 11:17, Tomasz Pakuła wrote:
> On Tue, 21 Jan 2025 at 10:59, Oliver Neukum <oneukum@suse.com> wrote:
>> I am afraid this is the most convoluted piece of boolean algebra I've seen
>> in a long time. In particular because it mixes things that do not belong together.
>
> Could you elaborate on that? What here does not belong?
Hi,
>
> I think the diff is a bit unfortunate and doesn't make it justice, but
> this is based on
> code that was already there. Instead of just checking if the new
> values differ from
> old values, we first check if any values are different from 0. If
> neither are != 0 OR
> the effect didn't contain an envelope previously (NULL here), we
> return the value
> of the check.
Indeed. And that is the problem.
You could see the evaluation to contain either two or three main cases.
First view:
A - everything is 0. We return false.
B - we compare the old and the new and return the comparison. With a subcase
of no old old values existing.
In the first view you are mixing the test for no old values of the second case
with the test for no old values existing.
Or you split up the second condition into two independent cases.
[..]
>
> if (!needs_new_envelope || !old)
> return needs_new_envelope;
This boolean statement stems from a common result, not from a common
logical reason for acting so. This is clear because if the first half
is true, you are returning itself.
This statement would be so much more clear as:
if (!needs_new_envelope)
return false;
if (!old)
return needs_new_envelope;
Regards
Oliver
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v5 02/12] HID: pidff: Do not send effect envelope if it's empty
2025-01-21 13:01 ` Oliver Neukum
@ 2025-01-21 13:15 ` Tomasz Pakuła
0 siblings, 0 replies; 20+ messages in thread
From: Tomasz Pakuła @ 2025-01-21 13:15 UTC (permalink / raw)
To: Oliver Neukum; +Cc: jikos, bentiss, anssi.hannula, linux-input, linux-usb, oleg
On Tue, 21 Jan 2025 at 14:01, Oliver Neukum <oneukum@suse.com> wrote:
>
> This boolean statement stems from a common result, not from a common
> logical reason for acting so. This is clear because if the first half
> is true, you are returning itself.
>
> This statement would be so much more clear as:
>
> if (!needs_new_envelope)
> return false;
>
> if (!old)
> return needs_new_envelope;
>
Okay, thanks for the clarification!
I'll simplify and include this suggestion in the next version.
Tomasz
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v5 09/12] HID: pidff: Stop all effects before enabling actuators
2025-01-21 10:10 ` Oliver Neukum
@ 2025-01-21 13:18 ` Tomasz Pakuła
2025-01-22 1:37 ` Tomasz Pakuła
1 sibling, 0 replies; 20+ messages in thread
From: Tomasz Pakuła @ 2025-01-21 13:18 UTC (permalink / raw)
To: Oliver Neukum; +Cc: jikos, bentiss, anssi.hannula, linux-input, linux-usb, oleg
On Tue, 21 Jan 2025 at 11:10, Oliver Neukum <oneukum@suse.com> wrote:
>
> On 19.01.25 14:13, Tomasz Pakuła wrote:
> > 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
>
> Hi,
>
> it seems to me that the same thing would happen upon resumption
> from S4. Will this be handled?
>
> Regards
> Oliver
>
(Terribly sorry for double mailing, I mistakenly hit reply instead of reply all)
I just tested this with my devices and it sadly doesn't handle sleep properly.
If a device is powered off then back on during sleep, the driver seems to be
unaware of it and keeps on chugging along like nothing happened.
This causes two things to happen:
1. FFB breaks in programs that have been running when going to sleep
2. Possible auto centering forces are back on and won't go away without a
power cycle or a disconnect/connect.
Moreover, I noticed that the PID reset routine is only called upon during
device initialisation, while most other PID driver implementations don't do it
during device init and only call:
1. reset + enable actuators if an application initialises force feedback.
2. reset + stop all effects + disable actuators if there aren't any more
effects left on the device after effect removal.
I'll update the reset function and access it differently, to better manage
device state and maybe hook up .suspend, .resume and .reset_resume
in the universal driver.
Managing this in the generic way will necessitate more extensive changes in the
hid-core but resetting every time when an application actually takes control
should be enough for now.
This driver is very old and I plan on chipping away at it more in the future
to make it less strict and work even better with all sorts of USB PID devices.
Tomasz
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v5 09/12] HID: pidff: Stop all effects before enabling actuators
2025-01-21 10:10 ` Oliver Neukum
2025-01-21 13:18 ` Tomasz Pakuła
@ 2025-01-22 1:37 ` Tomasz Pakuła
1 sibling, 0 replies; 20+ messages in thread
From: Tomasz Pakuła @ 2025-01-22 1:37 UTC (permalink / raw)
To: Oliver Neukum; +Cc: jikos, bentiss, anssi.hannula, linux-input, linux-usb
On Tue, 21 Jan 2025 at 11:10, Oliver Neukum <oneukum@suse.com> wrote:
>
> On 19.01.25 14:13, Tomasz Pakuła wrote:
> > 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
>
> Hi,
>
> it seems to me that the same thing would happen upon resumption
> from S4. Will this be handled?
>
> Regards
> Oliver
>
Turns out, the whole pidff_reset function was completely wrong and mostly didn't
do anything. Is some edge cases, it could maybe enable actuators, but
as it stands
pidff->device_control was treated like a field to assign values to,
while it actually is
an array with boolean fields.
^ permalink raw reply [flat|nested] 20+ messages in thread
end of thread, other threads:[~2025-01-22 1:38 UTC | newest]
Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-01-19 13:12 [PATCH v5 00/12] HID: Upgrade the generic pidff driver and add hid-universal-pidff Tomasz Pakuła
2025-01-19 13:12 ` [PATCH v5 01/12] HID: pidff: Convert infinite length from Linux API to PID standard Tomasz Pakuła
2025-01-19 13:12 ` [PATCH v5 02/12] HID: pidff: Do not send effect envelope if it's empty Tomasz Pakuła
2025-01-21 9:59 ` Oliver Neukum
2025-01-21 10:17 ` Tomasz Pakuła
2025-01-21 13:01 ` Oliver Neukum
2025-01-21 13:15 ` Tomasz Pakuła
2025-01-19 13:12 ` [PATCH v5 03/12] HID: pidff: Clamp PERIODIC effect period to device's logical range Tomasz Pakuła
2025-01-19 13:12 ` [PATCH v5 04/12] HID: pidff: Add MISSING_DELAY quirk and its detection Tomasz Pakuła
2025-01-19 13:12 ` [PATCH v5 05/12] HID: pidff: Add MISSING_PBO " Tomasz Pakuła
2025-01-19 13:12 ` [PATCH v5 06/12] HID: pidff: Add MISSING_DEVICE_CONTROL quirk Tomasz Pakuła
2025-01-19 13:12 ` [PATCH v5 07/12] HID: pidff: Add hid_pidff_init_with_quirks and export as GPL symbol Tomasz Pakuła
2025-01-19 13:12 ` [PATCH v5 08/12] HID: pidff: Add FIX_WHEEL_DIRECTION quirk Tomasz Pakuła
2025-01-19 13:13 ` [PATCH v5 09/12] HID: pidff: Stop all effects before enabling actuators Tomasz Pakuła
2025-01-21 10:10 ` Oliver Neukum
2025-01-21 13:18 ` Tomasz Pakuła
2025-01-22 1:37 ` Tomasz Pakuła
2025-01-19 13:13 ` [PATCH v5 10/12] HID: Add hid-universal-pidff driver and supported device ids Tomasz Pakuła
2025-01-19 13:13 ` [PATCH v5 11/12] MAINTAINERS: Add entry for hid-universal-pidff driver Tomasz Pakuła
2025-01-19 13:13 ` [PATCH v5 12/12] HID: pidff: Add PERIODIC_SINE_ONLY quirk Tomasz Pakuła
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).