From db0eb5244954560c86da15b2ddd14ad0a400b408 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= Date: Tue, 2 Jul 2024 01:24:15 +0200 Subject: [PATCH 1/8] Add Moza periodic envelope and direction fixup --- hid-pidff.c | 49 +++++++++++++++++++++---- hid-pidff.h | 11 ++++-- hid-newpidff.c => hid-universal-pidff.c | 34 ++++++++--------- 3 files changed, 66 insertions(+), 28 deletions(-) rename hid-newpidff.c => hid-universal-pidff.c (77%) diff --git a/hid-pidff.c b/hid-pidff.c index 08a7c71..0411815 100644 --- a/hid-pidff.c +++ b/hid-pidff.c @@ -192,6 +192,7 @@ struct pidff_device { int pid_id[PID_EFFECTS_MAX]; unsigned quirks; + short autocenter_effect_ids[PID_AUTOCENTER_EFFECTS]; }; /* @@ -308,12 +309,8 @@ static void pidff_set_effect_report(struct pidff_device *pidff, /* check for device quirks */ unsigned short direction = effect->direction; - if ((effect->type == FF_DAMPER || - effect->type == FF_FRICTION || - effect->type == FF_SPRING || - effect->type == FF_INERTIA) && - pidff->quirks & PIDFF_QUIRK_FIX_WHEEL_DIRECTION) - direction = 0x3FFF; + if (pidff->quirks & PIDFF_QUIRK_FIX_WHEEL_DIRECTION) + direction = 0x4000; pidff->set_effect[PID_EFFECT_BLOCK_INDEX].value[0] = pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; @@ -637,6 +634,17 @@ 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 (pidff->quirks & PIDFF_QUIRK_FIX_PERIODIC_ENVELOPE) + { + effect->u.periodic.envelope.attack_level = + effect->u.periodic.envelope.attack_level == 0 + ? 0x7fff : effect->u.periodic.envelope.attack_level; + + effect->u.periodic.envelope.fade_level = + effect->u.periodic.envelope.fade_level == 0 + ? 0x7fff : effect->u.periodic.envelope.fade_level; + } if (!old || pidff_needs_set_envelope(&effect->u.periodic.envelope, &old->u.periodic.envelope)) @@ -1264,7 +1272,7 @@ static int pidff_check_autocenter(struct pidff_device *pidff, /* * Check if the device is PID and initialize it */ -int hid_new_pidff_init(struct hid_device *hid, const struct hid_device_id *id) +int hid_pidff_init(struct hid_device *hid) { struct pidff_device *pidff; struct hid_input *hidinput = list_entry(hid->inputs.next, @@ -1286,7 +1294,6 @@ int hid_new_pidff_init(struct hid_device *hid, const struct hid_device_id *id) return -ENOMEM; pidff->hid = hid; - pidff->quirks |= id->driver_data; hid_device_io_start(hid); @@ -1364,3 +1371,29 @@ int hid_new_pidff_init(struct hid_device *hid, const struct hid_device_id *id) kfree(pidff); return error; } + +/* + * Check if the device is PID and initialize it + * Add quirks after initialisation + */ +int hid_pidff_init_with_quirks(struct hid_device *hid, const struct hid_device_id *id) +{ + int error = hid_pidff_init(hid); + + if (error) + return error; + + struct hid_input *hidinput = list_entry(hid->inputs.next, + struct hid_input, list); + struct input_dev *dev = hidinput->input; + struct pidff_device *pidff = dev->ff->private; + + /* set quirks on the pidff device */ + hid_device_io_start(hid); + pidff->quirks |= id->driver_data; + hid_device_io_stop(hid); + + hid_dbg(dev, "Device quirks: %d\n", pidff->quirks); + + return 0; +} diff --git a/hid-pidff.h b/hid-pidff.h index 517683f..586ee96 100644 --- a/hid-pidff.h +++ b/hid-pidff.h @@ -5,8 +5,12 @@ /* PIDFF Quirks to solve issues with certain devices */ /* - * Ignore direction for spring/damping/friction/inertia effects - * and always set 16384 + * Always set a value > 0 for PERIODIC envelope attack and fade level +*/ +#define PIDFF_QUIRK_FIX_PERIODIC_ENVELOPE BIT(0) + +/* + * Ignore direction and always set 16384 (0x4000) */ #define PIDFF_QUIRK_FIX_WHEEL_DIRECTION BIT(1) @@ -16,6 +20,7 @@ #define PIDFF_QUIRK_NO_DELAY_EFFECT BIT(2) -int hid_new_pidff_init(struct hid_device *hid, const struct hid_device_id *id); +int hid_pidff_init(struct hid_device *hid); +int hid_pidff_init_with_quirks(struct hid_device *hid, const struct hid_device_id *id); #endif diff --git a/hid-newpidff.c b/hid-universal-pidff.c similarity index 77% rename from hid-newpidff.c rename to hid-universal-pidff.c index fde41a4..2b8dfb7 100644 --- a/hid-newpidff.c +++ b/hid-universal-pidff.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Improved HID PIDFF driver + * HID PIDFF wrapper * First of all targeting steering wheels and wheelbases * * Copyright (c) 2024 Makarenko Oleg @@ -14,15 +14,15 @@ static const struct hid_device_id pidff_wheel_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R3), - .driver_data = PIDFF_QUIRK_FIX_WHEEL_DIRECTION | PIDFF_QUIRK_FIX_0_INFINITE_LENGTH }, + .driver_data = PIDFF_QUIRK_FIX_WHEEL_DIRECTION | PIDFF_QUIRK_FIX_PERIODIC_ENVELOPE }, { HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R5), - .driver_data = PIDFF_QUIRK_FIX_WHEEL_DIRECTION | PIDFF_QUIRK_FIX_0_INFINITE_LENGTH }, + .driver_data = PIDFF_QUIRK_FIX_WHEEL_DIRECTION | PIDFF_QUIRK_FIX_PERIODIC_ENVELOPE }, { HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R9), - .driver_data = PIDFF_QUIRK_FIX_WHEEL_DIRECTION | PIDFF_QUIRK_FIX_0_INFINITE_LENGTH }, + .driver_data = PIDFF_QUIRK_FIX_WHEEL_DIRECTION | PIDFF_QUIRK_FIX_PERIODIC_ENVELOPE }, { HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R12), - .driver_data = PIDFF_QUIRK_FIX_WHEEL_DIRECTION | PIDFF_QUIRK_FIX_0_INFINITE_LENGTH }, + .driver_data = PIDFF_QUIRK_FIX_WHEEL_DIRECTION | PIDFF_QUIRK_FIX_PERIODIC_ENVELOPE }, { HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R16_R21), - .driver_data = PIDFF_QUIRK_FIX_WHEEL_DIRECTION | PIDFF_QUIRK_FIX_0_INFINITE_LENGTH }, + .driver_data = PIDFF_QUIRK_FIX_WHEEL_DIRECTION | PIDFF_QUIRK_FIX_PERIODIC_ENVELOPE }, { } }; MODULE_DEVICE_TABLE(hid, pidff_wheel_devices); @@ -39,7 +39,7 @@ static u8 *moza_report_fixup(struct hid_device *hdev, __u8 *rdesc, } -static u8 *new_pidff_report_fixup(struct hid_device *hdev, __u8 *rdesc, +static u8 *universal_pidff_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { if (hdev->vendor == USB_VENDOR_ID_MOZA) { @@ -53,7 +53,7 @@ static u8 *new_pidff_report_fixup(struct hid_device *hdev, __u8 *rdesc, * Check if the device is PID and initialize it * Add quirks after initialisation */ -static int new_pidff_probe(struct hid_device *hdev, +static int universal_pidff_probe(struct hid_device *hdev, const struct hid_device_id *id) { int ret; @@ -69,7 +69,7 @@ static int new_pidff_probe(struct hid_device *hdev, goto err; } - ret = hid_new_pidff_init(hdev, id); + ret = hid_pidff_init_with_quirks(hdev, id); if (ret) { hid_warn(hdev, "Force feedback not supported\n"); goto err; @@ -80,7 +80,7 @@ err: return ret; } -static int new_pidff_input_configured(struct hid_device *hdev, +static int universal_pidff_input_configured(struct hid_device *hdev, struct hid_input *hidinput) { struct input_dev *input = hidinput->input; @@ -90,15 +90,15 @@ static int new_pidff_input_configured(struct hid_device *hdev, return 0; } -static struct hid_driver new_pidff = { - .name = "new-pidff", +static struct hid_driver universal_pidff = { + .name = "hid-universal-pidff", .id_table = pidff_wheel_devices, - .probe = new_pidff_probe, - .input_configured = new_pidff_input_configured, - .report_fixup = new_pidff_report_fixup + .probe = universal_pidff_probe, + .input_configured = universal_pidff_input_configured, + .report_fixup = universal_pidff_report_fixup }; -module_hid_driver(new_pidff); +module_hid_driver(universal_pidff); MODULE_AUTHOR("Oleg Makarenko "); -MODULE_DESCRIPTION("Improved HID PIDFF Driver"); +MODULE_DESCRIPTION("Universal HID PIDFF Driver"); MODULE_LICENSE("GPL"); From a6ec74f90d11d97f11098ed0b468d38750b8d2c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= Date: Tue, 2 Jul 2024 10:47:22 +0200 Subject: [PATCH 2/8] Remove unneeded paramaters --- hid-pidff.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/hid-pidff.c b/hid-pidff.c index 0411815..7551253 100644 --- a/hid-pidff.c +++ b/hid-pidff.c @@ -192,7 +192,6 @@ struct pidff_device { int pid_id[PID_EFFECTS_MAX]; unsigned quirks; - short autocenter_effect_ids[PID_AUTOCENTER_EFFECTS]; }; /* @@ -316,7 +315,7 @@ 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] = + 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; @@ -1098,7 +1097,7 @@ static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev) if (pidff->quirks & PIDFF_QUIRK_NO_DELAY_EFFECT) { hid_dbg(pidff->hid, "Find fields for set_effect without delay\n"); - if (pidff_find_fields(pidff->set_effect, + if (pidff_find_fields(pidff->set_effect, pidff_set_effect_without_delay, pidff->reports[PID_SET_EFFECT], \ sizeof(pidff_set_effect_without_delay), 1)) { @@ -1112,7 +1111,7 @@ static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev) return -ENODEV; } } - + PIDFF_FIND_FIELDS(block_load, PID_BLOCK_LOAD, 0); if (!pidff->block_load[PID_EFFECT_BLOCK_INDEX].value) { From 9d9e4c47bde79ab97ab7f2615fcfe8e19f150662 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= Date: Tue, 2 Jul 2024 10:45:44 +0200 Subject: [PATCH 3/8] Update build configs --- Kbuild | 2 +- dkms.conf | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Kbuild b/Kbuild index 02cf0ff..acd2cc0 100644 --- a/Kbuild +++ b/Kbuild @@ -1,3 +1,3 @@ obj-m := hid-new-pidff.o -hid-new-pidff-y := hid-newpidff.o hid-pidff.o +hid-new-pidff-y := hid-universal-pidff.o hid-pidff.o ccflags-y := -Idrivers/hid diff --git a/dkms.conf b/dkms.conf index 0f32716..6beaf8c 100644 --- a/dkms.conf +++ b/dkms.conf @@ -1,8 +1,8 @@ -PACKAGE_NAME="new-pidff" +PACKAGE_NAME="universal-pidff" PACKAGE_VERSION="0.0.2" MAKE[0]="make KVERSION=$kernelver" CLEAN="make clean" -BUILT_MODULE_NAME[0]="hid-new-pidff" -DEST_MODULE_NAME[0]="hid-new-pidff" +BUILT_MODULE_NAME[0]="hid-univesal-pidff" +DEST_MODULE_NAME[0]="hid-universal-pidff" DEST_MODULE_LOCATION[0]="/kernel/drivers/hid" -AUTOINSTALL="yes" \ No newline at end of file +AUTOINSTALL="yes" From 33a99c7458ee154f18b20f6db15d73397a1a7b55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= Date: Tue, 2 Jul 2024 11:52:46 +0200 Subject: [PATCH 4/8] Add field value clamping functionality --- hid-pidff.c | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/hid-pidff.c b/hid-pidff.c index 7551253..710f6a5 100644 --- a/hid-pidff.c +++ b/hid-pidff.c @@ -213,6 +213,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); @@ -359,7 +389,7 @@ 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; + 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); From ffa4a05a1b295ba0cf8e90ba57fa1883ef457598 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= Date: Tue, 2 Jul 2024 11:55:36 +0200 Subject: [PATCH 5/8] Update attack/fade logging --- hid-pidff.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/hid-pidff.c b/hid-pidff.c index 710f6a5..0954721 100644 --- a/hid-pidff.c +++ b/hid-pidff.c @@ -285,7 +285,11 @@ static void pidff_set_envelope_report(struct pidff_device *pidff, pidff->set_envelope[PID_ATTACK_TIME].value[0] = envelope->attack_length; pidff->set_envelope[PID_FADE_TIME].value[0] = envelope->fade_length; - hid_dbg(pidff->hid, "attack %u => %d\n", + hid_dbg(pidff->hid, "attack level %u => %d\n", + envelope->attack_level, + pidff->set_envelope[PID_ATTACK_LEVEL].value[0]); + + hid_dbg(pidff->hid, "fade level %u => %d\n", envelope->attack_level, pidff->set_envelope[PID_ATTACK_LEVEL].value[0]); From 1da641aee464cbb38ad3cb0c05d2c61c4c998c39 Mon Sep 17 00:00:00 2001 From: Lawstorant Date: Fri, 12 Jul 2024 15:46:42 +0200 Subject: [PATCH 6/8] Explain WHEEL_DIRECTION_FIX value --- hid-pidff.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/hid-pidff.c b/hid-pidff.c index 0954721..5174036 100644 --- a/hid-pidff.c +++ b/hid-pidff.c @@ -25,6 +25,14 @@ #define PID_EFFECTS_MAX 64 +/* + * This is 16384 or 90 degrees in polar coordinates (up) + * Racing games exclusively use polar coordinates but sometimes + * SDL/Proton mess with this value as they try to do + * some conversions to fix FFB for flight sticks + */ +#define PIDFF_FIXED_DIRECTION 0x4000 + /* Report usage table used to put reports into an array */ #define PID_SET_EFFECT 0 @@ -343,7 +351,7 @@ static void pidff_set_effect_report(struct pidff_device *pidff, unsigned short direction = effect->direction; if (pidff->quirks & PIDFF_QUIRK_FIX_WHEEL_DIRECTION) - direction = 0x4000; + direction = PIDFF_FIXED_DIRECTION; pidff->set_effect[PID_EFFECT_BLOCK_INDEX].value[0] = pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; From 83d1374b63618051078e85e608c3f5a85c183172 Mon Sep 17 00:00:00 2001 From: Lawstorant Date: Fri, 12 Jul 2024 15:47:24 +0200 Subject: [PATCH 7/8] Mention Boxflat in the README --- README.md | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 503be39..cddbe27 100644 --- a/README.md +++ b/README.md @@ -10,10 +10,7 @@ And that's basically it ## What devices are supported? ### Bases: 1. MOZA R3, R5, R9, R12, R16, R21 -1. ... - -### Wheel rims (others yet untested): -1. MOZA RS V2 (with Moza wheelbases) +2. ... ## What works? 1. FFB (all effects from device descriptor) @@ -51,13 +48,13 @@ To unload module: `sudo rmmod hid_moza_ff` ## How to set up a base parameters? - ### MOZA -For now, please, use [Android App](https://play.google.com/store/apps/details?id=com.gudsen.mozapithouse) +**[Boxflat](https://github.com/Lawstorant/boxflat)** is a Linux Pit House alternative made by [@Lawstorant](https://github.com/Lawstorant) +**[Android App](https://play.google.com/store/apps/details?id=com.gudsen.mozapithouse)** ## Known issues with the driver -1. Firmware update does not work. Please use Windows machine or Windows VM for any firmware updates +- Buttons above 80 simply don't show up. This is a Linux limitation and we're trying to fix that in the upstream ## Known issues with the firmware You tell me please From dea4e51be58471c1c03ddb0c4eec55867c423144 Mon Sep 17 00:00:00 2001 From: Lawstorant Date: Sat, 13 Jul 2024 15:59:13 +0200 Subject: [PATCH 8/8] Fix dkms build --- dkms.conf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dkms.conf b/dkms.conf index 6beaf8c..49f8865 100644 --- a/dkms.conf +++ b/dkms.conf @@ -1,8 +1,8 @@ PACKAGE_NAME="universal-pidff" -PACKAGE_VERSION="0.0.2" +PACKAGE_VERSION="0.0.3" MAKE[0]="make KVERSION=$kernelver" CLEAN="make clean" -BUILT_MODULE_NAME[0]="hid-univesal-pidff" -DEST_MODULE_NAME[0]="hid-universal-pidff" +BUILT_MODULE_NAME[0]="hid-new-pidff" +DEST_MODULE_NAME[0]="hid-universal-ff" DEST_MODULE_LOCATION[0]="/kernel/drivers/hid" AUTOINSTALL="yes"