43 Commits

Author SHA1 Message Date
Oleg
0fefe3dbc8 Bump dkms version to 0.0.9 2024-10-17 17:50:50 +03:00
Makarenko Oleg
31b4aa55b8 Merge branch 'main' into vrs 2024-10-17 11:14:22 +03:00
Tomasz Pakuła
c29bb95c40 Bump dkms version to 0.0.8 2024-08-28 17:30:18 +03:00
Tomasz Pakuła
b62cc67397 Update ffb test file 2024-08-28 17:30:18 +03:00
Lawstorant
f3648cc3c5 Add support for Moza FH5 compatibility mode 2024-08-28 17:30:18 +03:00
Oleg
3afa74502e Bump dkms version to 0.0.7 2024-08-26 16:53:47 +03:00
Tomasz Pakuła
99b4ebb4ce Fix errors in code 2024-08-16 21:01:45 +03:00
Tomasz Pakuła
823a950f07 Fix missing return statement 2024-08-16 20:40:26 +03:00
Tomasz Pakuła
4326430856 Set flat value to 0 for additional axes
Flat value (deadzone) works around the center of
a given axis. With steering wheels, only steering axis returns to the center and flat
causes weird behavior in the middle of throttle,
brake, clutch etc.
2024-08-16 20:40:14 +03:00
Makarenko Oleg
3932a51126 Merge pull request #23 from Lawstorant/moza-fuzz
Defuzz additional axes
2024-08-16 00:52:07 +03:00
Tomasz Pakuła
561a50299b Simplyfy input mapping and increase button number
Wine didn't like button ranges that weren't sequential.
2024-08-15 22:34:05 +03:00
Tomasz Pakuła
164ad09ad8 Update README to mention new button limit 2024-08-15 22:34:05 +03:00
Tomasz Pakuła
baf35a36f0 Explain the mapping function better 2024-08-15 22:34:05 +03:00
Tomasz Pakuła
51982fd1e2 Add Tomasz Pakuła as author 2024-08-15 22:34:05 +03:00
Lawstorant
d7633c82fd Map buttons manually to present more than 80 2024-08-15 22:34:05 +03:00
Lawstorant
56fdaa11f8 Rename i -> axis for better readability 2024-08-15 13:24:32 +02:00
Lawstorant
c6649f3349 Rewrite the logic to not rely on defined data 2024-08-15 13:24:11 +02:00
Lawstorant
092bdbd661 Defuzz additional axes
Add .ffb file for effect testing
Mention Monocoque in readme for telemetry stuff
2024-08-14 23:14:28 +02:00
Makarenko Oleg
9e27df12cb Merge pull request #21 from KaJe5380/main
Add Cammus C12
2024-08-09 14:38:44 +03:00
Makarenko Oleg
b4a1a47284 Merge branch 'main' into vrs 2024-08-09 12:30:57 +03:00
KaJe
985182baf2 Add C12 to README.md 2024-08-08 17:20:37 -07:00
KaJe
55d456c9e1 Added Cammus C12 to the list with NO_DELAY quirk 2024-08-08 17:19:45 -07:00
KaJe
3b0f38483f Added Cammus C12 wheelbase ID 2024-08-08 17:19:04 -07:00
Oleg
3d19599175 Bump dkms package_version 2024-08-08 03:02:52 +03:00
Makarenko Oleg
6d0ac791b1 Merge pull request #19 from JacKeTUs/fix-alignment
Fix alignment on hid-ids.h
2024-08-08 03:00:47 +03:00
Oleg
bc87313267 Fix alignment on hid-ids.h 2024-08-08 03:00:27 +03:00
Makarenko Oleg
8f42ca6774 Merge pull request #16 from Lawstorant/rework-checks
Rework envelope check
2024-08-08 02:59:20 +03:00
Makarenko Oleg
2ee89cb9a4 Merge pull request #17 from JacKeTUs/aur-link-fix
Fix AUR package URL
2024-08-02 04:08:24 +03:00
Lawstorant
f8e9545f39 Fix AUR package URL 2024-08-02 04:07:57 +03:00
Lawstorant
241a25cee9 Fix AUR package URL 2024-07-27 00:12:07 +02:00
Lawstorant
8220bbbfb0 Rework envelope checks to fix FFB for Moza
Only set envelopes when they are needed (any value is != 0). This fixes
Moza FFB in games that use Sine effect to emulate constant force.

Remove FIX_PERIODIC_ENVELOPE quirk as it's no longer needed
2024-07-27 00:10:39 +02:00
Makarenko Oleg
96e036acda Merge pull request #15 from JacKeTUs/signing
Added signing section to the README
2024-07-22 13:07:07 +03:00
Oleg
e1c8ae6e54 Merge branch 'main' into vrs 2024-07-16 18:13:25 +03:00
Makarenko Oleg
49b38bcefb Merge branch 'main' into vrs 2024-07-16 17:29:07 +03:00
Oleg
6d25c361d2 Merge branch 'main' into vrs 2024-07-16 12:37:36 +03:00
Oleg
86b81767b6 Fix duplicate ids 2024-07-15 11:43:31 +03:00
Oleg
30ebc05078 Merge branch 'main' into vrs 2024-07-15 04:52:45 +03:00
Oleg
41c5bf3fd4 Added VRS DirectForce Pro wheelbase to README.md 2024-07-15 04:35:32 +03:00
Oleg
45360c7c34 Fix NO_DELAY_EFFECT quirk implementation 2024-07-15 04:31:27 +03:00
Oleg
6e39b84de7 Implement NO_STRICT_PID_CONTROL and NO_PID_PARAM_BLOCK_OFFSET quirks 2024-07-15 04:31:05 +03:00
Oleg
d11220c261 Clarification about new quirks 2024-07-15 04:29:55 +03:00
Oleg
9057ffeb6f Added quirks for VRS wheelbase 2024-07-15 04:19:37 +03:00
Oleg
365e585336 Added VRS DirectForce Pro ids 2024-07-15 04:19:20 +03:00
7 changed files with 289 additions and 49 deletions

View File

@@ -7,7 +7,7 @@ That driver allows most DirectDrive wheelbases to initialize and work.
Most of the DirectDrive wheelbases are basically DirectInput wheels, but with some caveats, which Windows allows, but pidff doesn't.
In that repository - pidff driver with some changes, which allows most of the DirectDrive wheelbases to work.
1. Added quirks for better initialization rules for different wheelbases (MOZA, VRS, Cammus)
1. Added multiple quirks for better initialization rules for different wheelbases (MOZA, VRS, Cammus)
2. Fixes for infinite-length effects
3. Fixes for out-of-bounds values (no more spam in kernel logs)
@@ -16,8 +16,9 @@ And that's basically it
## What devices are supported?
### Bases:
1. MOZA R3, R5, R9, R12, R16, R21
2. Cammus C5
3. ...
2. Cammus C5, C12
3. VRS DirectForce Pro
4. ...
## What works?
1. FFB (all effects from device descriptor)
@@ -25,9 +26,9 @@ And that's basically it
## What does not work?
1. Telemetry functions (Shift lights, displays, SimHub, etc), mostly because telemetry works only with proprietary soft, which can't get access to shared memory chunks from games.
1. Telemetry functions. They are handeled by [Monocoque](https://github.com/Spacefreak18/monocoque)
2. `Firmware Update` function. Use Windows PC or Windows VM at the moment.
3. Setup through proprietary software. May require [some tweaking](#how-to-set-up-a-base-parameters))
3. Setup through proprietary software. May require [some tweaking](#how-to-set-up-a-base-parameters)
## How to install this driver?
You can install it through AUR package, through DKMS or manually.
@@ -35,7 +36,7 @@ You can install it through AUR package, through DKMS or manually.
On SecureBoot enabled systems you will need additional steps for load this driver into the system. See [Signing](docs/SIGNING.md#signing) section.
### AUR package
There's an [AUR package](https://aur.archlinux.org/packages/universal-ff-dkms-git) for Arch Linux maintained by [@Lawstorant](https://github.com/Lawstorant).
There's an [AUR package](https://aur.archlinux.org/packages/universal-pidff-dkms-git) for Arch Linux maintained by [@Lawstorant](https://github.com/Lawstorant).
### DKMS
DKMS will install module into system, and will update it every time you update your kernel. Module will persist after reboots. It's the preferrable way to install it on the most distros.
@@ -61,7 +62,10 @@ Best for debugging purposes, where you need frequently change codebase/branches
To unload module:
`sudo rmmod hid_universal_pidff`
## How to set up a base parameters?
### Testing
To test the supported effects, use ffbplay from [ffbtools](https://github.com/berarma/ffbtools) and play the included [effect-test.ffb](./effect-test.ffb) file
## How to set up a base parameters (max rotation degree, max power, filters, etc)?
### MOZA
**[Boxflat](https://github.com/Lawstorant/boxflat)** is a Linux Pit House alternative made by [@Lawstorant](https://github.com/Lawstorant)
@@ -70,8 +74,37 @@ To unload module:
### Cammus
**[Android App](https://play.google.com/store/apps/details?id=com.cammus.simulator)**
### VRS DirectForce Pro
You can do it through VRS with Wine. You need to tweak Wine prefix for them.
That soft uses hidraw to set up a base. You need to create `udev` rule for allow access to hidraw device:
```
echo 'KERNEL=="hidraw*", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="a355", MODE="0666", TAG+="uaccess"' | sudo tee /etc/udev/rules.d/11-vrs.rules
udevadm control --reload-rules && udevadm trigger
```
Then you need to force VRS soft to use hidraw, not SDL, to find devices:
1. Create new Wine prefix for them:
`mkdir ~/vrs-wine`
2. Launch regedit in prefix:
`WINEPREFIX=$HOME/vrs-wine wine regedit`
3. Create two keys in
`HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\winebus`:
* `DisableInput` (DWORD) - set to `1`;
* `Enable SDL` (DWORD) - set to `0`; (yes, variable name contains space)
4. Now you can launch soft through that WINEPREFIX:
`WINEPREFIX=$HOME/vrs-wine wine VRS.exe` - launch your soft from installation directory.
## Known issues with the driver
- Buttons above 80 simply don't show up. This is a Linux limitation and we're trying to fix that in the upstream
### MOZA
- Current limit of usable buttons is 160 (up from the Linux default of 80). Create an issue if you want this increased further.
## Known issues with the firmware
You tell me please

View File

@@ -1,5 +1,5 @@
PACKAGE_NAME="universal-pidff"
PACKAGE_VERSION="0.0.3"
PACKAGE_VERSION="0.0.9"
MAKE[0]="make KVERSION=$kernelver"
CLEAN="make clean"
BUILT_MODULE_NAME[0]="hid-universal-pidff"

91
effect-test.ffb Normal file
View File

@@ -0,0 +1,91 @@
00000000 # Constant force left
00000000 > UPLOAD id:-1 dir:16384 type:CONSTANT level:5000
00000000 < 0 id:0
00000000 > PLAY 0 1
03000000 # Constant force right
03000000 > UPLOAD id:0 dir:16384 type:CONSTANT level:-5000
06000000 # Spring
06000000 > REMOVE 0
06000000 > UPLOAD id:-1 dir:16384 type:SPRING left_coeff:2000 right_coeff:2000
06000000 < 0 id:0
06000000 > PLAY 0 1
07000000 # Move the wheel yourself to test these next 3 effects
09000000 > STOP 0
09000000 # Damper
09000000 > REMOVE 0
09000000 > UPLOAD id:-1 dir:16384 type:DAMPER left_coeff:32767 right_coeff:32767
09000000 < 0 id:0
09000000 > PLAY 0 1
12000000 # Friction
12000000 > STOP 0
12000000 > REMOVE 0
12000000 > UPLOAD id:-1 dir:16384 type:FRICTION left_coeff:32767 right_coeff:32767
12000000 < 0 id:0
12000000 > PLAY 0 1
15000000 # Inertia
15000000 > STOP 0
15000000 > REMOVE 0
15000000 > UPLOAD id:-1 dir:16384 type:INERTIA left_coeff:32767 right_coeff:32767
15000000 < 0 id:0
15000000 > PLAY 0 1
18000000 # Periodic sine
18000000 > REMOVE 0
18000000 > UPLOAD id:-1 dir:16384 type:PERIODIC waveform:SINE period:100 magnitude:9000
18000000 < 0 id:0
18000000 > PLAY 0 1
21000000 # Periodic square
21000000 > REMOVE 0
21000000 > UPLOAD id:-1 dir:16384 type:PERIODIC waveform:SQUARE period:100 magnitude:4000
21000000 < 0 id:0
21000000 > PLAY 0 1
24000000 # Periodic triangle
24000000 > REMOVE 0
24000000 > UPLOAD id:-1 dir:16384 type:PERIODIC waveform:TRIANGLE period:100 magnitude:9000
24000000 < 0 id:0
24000000 > PLAY 0 1
27000000 # Periodic saw up
27000000 > REMOVE 0
27000000 > UPLOAD id:-1 dir:16384 type:PERIODIC waveform:SAW_UP period:100 magnitude:4000
27000000 < 0 id:0
27000000 > PLAY 0 1
30000000 # Periodic saw down
30000000 > REMOVE 0
30000000 > UPLOAD id:-1 dir:16384 type:PERIODIC waveform:SAW_DOWN period:100 magnitude:4000
30000000 < 0 id:0
30000000 > PLAY 0 1
33000000 # Sine constant force emulation left
33000000 > REMOVE 0
33000000 > UPLOAD id:-1 dir:16384 type:PERIODIC waveform:SINE period:1000 magnitude:0 offset:4000
33000000 < 0 id:0
33000000 > PLAY 0 1
36000000 # Sine constant force emulation right
36000000 > UPLOAD id:0 dir:16384 type:PERIODIC waveform:SINE period:1000 magnitude:0 offset:-4000
39000000 > STOP 0
39000000 > REMOVE 0
40000000 # Back to center
40000000 > UPLOAD id:-1 dir:16384 type:FRICTION left_coeff:16000 right_coeff:16000
40000000 > UPLOAD id:-1 dir:16384 type:SPRING left_coeff:3000 right_coeff:3000
40000000 < 0 id:0
40000000 < 1 id:1
40100000 > PLAY 0 1
40100000 > PLAY 1 1
42000000 > STOP 1
42000000 > STOP 0
42000000 > REMOVE 1
42000000 > REMOVE 0
42000000 # Test end

View File

@@ -2,14 +2,28 @@
#ifndef __HID_IDS_H
#define __HID_IDS_H
#define USB_VENDOR_ID_MOZA 0x346e
// Moza Racing
#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
// VRS DrivingForce Pro
#define USB_VENDOR_ID_VRS 0x0483
#define USB_DEVICE_ID_VRS_DFP 0xa355
// Moza Racing FH5 mode
#define USB_DEVICE_ID_MOZA_R3_FH5 0x0015
#define USB_DEVICE_ID_MOZA_R5_FH5 0x0014
#define USB_DEVICE_ID_MOZA_R9_FH5 0x0012
#define USB_DEVICE_ID_MOZA_R12_FH5 0x0016
#define USB_DEVICE_ID_MOZA_R16_R21_FH5 0x0010
// Cammus
#define USB_VENDOR_ID_CAMMUS 0x3416
#define USB_DEVICE_ID_CAMMUS_C5 0x0301
#define USB_DEVICE_ID_CAMMUS_C12 0x0302
#endif

View File

@@ -4,27 +4,47 @@
* First of all targeting steering wheels and wheelbases
*
* 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"
#include "hid-pidff.h"
#define JOY_RANGE (BTN_DEAD - BTN_JOYSTICK + 1)
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_PERIODIC_ENVELOPE },
.driver_data = PIDFF_QUIRK_FIX_WHEEL_DIRECTION },
{ HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R5),
.driver_data = PIDFF_QUIRK_FIX_WHEEL_DIRECTION | PIDFF_QUIRK_FIX_PERIODIC_ENVELOPE },
.driver_data = PIDFF_QUIRK_FIX_WHEEL_DIRECTION },
{ HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R9),
.driver_data = PIDFF_QUIRK_FIX_WHEEL_DIRECTION | PIDFF_QUIRK_FIX_PERIODIC_ENVELOPE },
.driver_data = PIDFF_QUIRK_FIX_WHEEL_DIRECTION },
{ HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R12),
.driver_data = PIDFF_QUIRK_FIX_WHEEL_DIRECTION | PIDFF_QUIRK_FIX_PERIODIC_ENVELOPE },
.driver_data = PIDFF_QUIRK_FIX_WHEEL_DIRECTION },
{ HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R16_R21),
.driver_data = PIDFF_QUIRK_FIX_WHEEL_DIRECTION | PIDFF_QUIRK_FIX_PERIODIC_ENVELOPE },
.driver_data = PIDFF_QUIRK_FIX_WHEEL_DIRECTION },
{ HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R3_FH5),
.driver_data = PIDFF_QUIRK_FIX_WHEEL_DIRECTION },
{ HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R5_FH5),
.driver_data = PIDFF_QUIRK_FIX_WHEEL_DIRECTION },
{ HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R9_FH5),
.driver_data = PIDFF_QUIRK_FIX_WHEEL_DIRECTION },
{ HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R12_FH5),
.driver_data = PIDFF_QUIRK_FIX_WHEEL_DIRECTION },
{ HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R16_R21_FH5),
.driver_data = PIDFF_QUIRK_FIX_WHEEL_DIRECTION },
{ HID_USB_DEVICE(USB_VENDOR_ID_CAMMUS, USB_DEVICE_ID_CAMMUS_C5),
.driver_data = PIDFF_QUIRK_NO_DELAY_EFFECT },
{ HID_USB_DEVICE(USB_VENDOR_ID_CAMMUS, USB_DEVICE_ID_CAMMUS_C12),
.driver_data = PIDFF_QUIRK_NO_DELAY_EFFECT },
{ HID_USB_DEVICE(USB_VENDOR_ID_VRS, USB_DEVICE_ID_VRS_DFP),
.driver_data = PIDFF_QUIRK_NO_DELAY_EFFECT
| PIDFF_QUIRK_NO_STRICT_PID_CONTROL
| PIDFF_QUIRK_NO_PID_PARAM_BLOCK_OFFSET },
{ }
};
MODULE_DEVICE_TABLE(hid, pidff_wheel_devices);
@@ -50,6 +70,36 @@ static u8 *universal_pidff_report_fixup(struct hid_device *hdev, __u8 *rdesc,
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 for the upcoming new input event
// It will handle button presses differently and won't depend on defined
// ranges. KEY_RESERVED usage is needed for the button to not be ignored.
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
@@ -85,17 +135,30 @@ err:
static int universal_pidff_input_configured(struct hid_device *hdev,
struct hid_input *hidinput)
{
// Remove fuzz and deadzone
// Remove fuzz and deadzone from the wheel 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);
}
return 0;
}
static struct hid_driver universal_pidff = {
.name = "hid-universal-pidff",
.id_table = pidff_wheel_devices,
.input_mapping = universal_pidff_input_mapping,
.probe = universal_pidff_probe,
.input_configured = universal_pidff_input_configured,
.report_fixup = universal_pidff_report_fixup
@@ -103,5 +166,6 @@ static struct hid_driver universal_pidff = {
module_hid_driver(universal_pidff);
MODULE_AUTHOR("Oleg Makarenko <oleg@makarenk.ooo>");
MODULE_AUTHOR("Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>");
MODULE_DESCRIPTION("Universal HID PIDFF Driver");
MODULE_LICENSE("GPL");

View File

@@ -94,6 +94,11 @@ static const u8 pidff_set_condition[] = {
0x22, 0x23, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65
};
static const u8 pidff_set_condition_without_pbo[] = {
0x22, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65
};
#define PID_MAGNITUDE 1
#define PID_OFFSET 2
#define PID_PHASE 3
@@ -311,6 +316,14 @@ static void pidff_set_envelope_report(struct pidff_device *pidff,
static int pidff_needs_set_envelope(struct ff_envelope *envelope,
struct ff_envelope *old)
{
if (!old) {
return envelope->attack_level != 0 ||
envelope->fade_level != 0 ||
envelope->attack_length != 0 ||
envelope->fade_length != 0;
}
return envelope->attack_level != old->attack_level ||
envelope->fade_level != old->fade_level ||
envelope->attack_length != old->attack_length ||
@@ -406,8 +419,8 @@ static void pidff_set_periodic_report(struct pidff_device *pidff,
// Actually we just can use clamp macro
// from include/linux/kernel.h#L59
// But for the debug purposes we're leaving it as is
pidff->set_periodic[PID_PERIOD].value[0] =
pidff_clamp(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],
@@ -434,12 +447,19 @@ static void pidff_set_condition_report(struct pidff_device *pidff,
struct ff_effect *effect)
{
int i;
// Later we should take axis number out of the device.
// Our driver must work with MOZA AB9 FFB Base
int max_axis = 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++) {
pidff->set_condition[PID_PARAM_BLOCK_OFFSET].value[0] = i;
if (pidff->quirks & PIDFF_QUIRK_NO_PID_PARAM_BLOCK_OFFSET)
max_axis = 1;
for (i = 0; i < max_axis; i++) {
if (! (pidff->quirks & PIDFF_QUIRK_NO_PID_PARAM_BLOCK_OFFSET) )
pidff->set_condition[PID_PARAM_BLOCK_OFFSET].value[0] = i;
pidff_set_signed(&pidff->set_condition[PID_CP_OFFSET],
effect->u.condition[i].center);
pidff_set_signed(&pidff->set_condition[PID_POS_COEFFICIENT],
@@ -643,9 +663,8 @@ 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))
if (pidff_needs_set_envelope(&effect->u.constant.envelope,
old ? &old->u.periodic.envelope : NULL))
pidff_set_envelope_report(pidff,
&effect->u.constant.envelope);
break;
@@ -683,19 +702,8 @@ static int pidff_upload_effect(struct input_dev *dev, struct ff_effect *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))
if (pidff_needs_set_envelope(&effect->u.periodic.envelope,
old ? &old->u.periodic.envelope : NULL))
pidff_set_envelope_report(pidff,
&effect->u.periodic.envelope);
break;
@@ -711,9 +719,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))
if (pidff_needs_set_envelope(&effect->u.ramp.envelope,
old ? &old->u.periodic.envelope : NULL))
pidff_set_envelope_report(pidff,
&effect->u.ramp.envelope);
break;
@@ -1003,6 +1011,10 @@ static int pidff_find_special_fields(struct pidff_device *pidff)
{
hid_dbg(pidff->hid, "finding special fields\n");
int strict_pid_device_control = 1;
if (pidff->quirks & PIDFF_QUIRK_NO_STRICT_PID_CONTROL)
strict_pid_device_control = 0;
pidff->create_new_effect_type =
pidff_find_special_field(pidff->reports[PID_CREATE_NEW_EFFECT],
0x25, 1);
@@ -1014,7 +1026,7 @@ 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, strict_pid_device_control);
pidff->block_load_status =
pidff_find_special_field(pidff->reports[PID_BLOCK_LOAD],
0x8b, 1);
@@ -1211,7 +1223,23 @@ 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) ||
if (pidff->quirks & PIDFF_QUIRK_NO_PID_PARAM_BLOCK_OFFSET) {
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(pidff->set_condition,
pidff_set_condition_without_pbo,
pidff->reports[PID_SET_CONDITION], \
sizeof(pidff_set_condition_without_pbo), 1)) {
hid_warn(pidff->hid, "unknown condition effect layout (w/o PBO)\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);
}
}
else 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)) &&

View File

@@ -4,21 +4,31 @@
/* PIDFF Quirks to solve issues with certain devices */
/*
* 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)
*/
#define PIDFF_QUIRK_FIX_WHEEL_DIRECTION BIT(0)
/*
* Skip initialization of 0xA7 descriptor (Delay effect)
* Fixes VRS DFP, Cammus, old Simagic wheelbases
*/
#define PIDFF_QUIRK_NO_DELAY_EFFECT BIT(2)
#define PIDFF_QUIRK_NO_DELAY_EFFECT BIT(1)
/*
* Ignore PARAM_BLOCK_OFFSET (Axis number).
* Most of the wheelbases have only one Axis anyway
* Fixes VRS DFP
*/
#define PIDFF_QUIRK_NO_PID_PARAM_BLOCK_OFFSET BIT(2)
/*
* Some wheelbases don't have some PID_CONTROL fields.
* PID standard does not define fields that MUST exist, but
* that driver was strict about them. This quirk disables it.
* Fixes VRS DFP
*/
#define PIDFF_QUIRK_NO_STRICT_PID_CONTROL BIT(3)
int hid_pidff_init_quirks(struct hid_device *hid, const struct hid_device_id *id);