27 Commits

Author SHA1 Message Date
a8d8a3a555 Litestar support? 2025-01-20 00:29:42 +01:00
Lawstorant
23ec6488ed Fix build for kernels older than 6.12 2024-12-13 20:33:46 +02:00
Lawstorant
f683cac1c9 Fix building with kernel 6.12 2024-11-28 08:36:41 +02:00
Lawstorant
d95b73e042 Update README again 2024-10-30 16:16:01 +02:00
Lawstorant
d4ac27a183 Update README 2024-10-30 16:16:01 +02:00
Lawstorant
f16837c0b3 Bump dkms version 2024-10-30 16:16:01 +02:00
Lawstorant
1748202f6d Add support for FFBeast Wheel device 2024-10-30 16:16:01 +02:00
Lawstorant
915d4678bd Slight styling changes for VRS_DFP 2024-10-30 16:16:01 +02:00
Oleg
330e7db32f Changes in VRS DFP config tool tinkering
Added installation of dotnet48
Switch Wine Windows version to 7
Move Wine prefix to hidden folder
Added VRS pedals into udev rules
2024-10-17 18:13:54 +03:00
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
Makarenko Oleg
b4a1a47284 Merge branch 'main' into vrs 2024-08-09 12:30:57 +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 194 additions and 37 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
2. Fixes for infinite-length effects
3. Fixes for out-of-bounds values (no more spam in kernel logs)
@@ -17,7 +17,9 @@ And that's basically it
### Bases:
1. MOZA R3, R5, R9, R12, R16, R21
2. Cammus C5, C12
3. ...
3. VRS DirectForce Pro
4. FFBeast Wheel
5. ...
## What works?
1. FFB (all effects from device descriptor)
@@ -64,7 +66,7 @@ To unload module:
### 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?
## 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)
@@ -73,6 +75,40 @@ To test the supported effects, use ffbplay from [ffbtools](https://github.com/be
### 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 software uses hidraw to set up a base. You need to create `udev` rule for allow access to hidraw device:
```
# VRS DFP
echo 'KERNEL=="hidraw*", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="a355", MODE="0666", TAG+="uaccess"' | sudo tee /etc/udev/rules.d/11-vrs.rules
# VRS pedals
echo 'KERNEL=="hidraw*", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="a3be", 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 software to use hidraw, not SDL, to find devices:
1. Create new Wine prefix for them:
`mkdir ~/.vrs-wine`
1. Launch regedit in prefix:
`WINEPREFIX=$HOME/.vrs-wine wine regedit`
1. 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)
1. Install important packages for VRS config tool to work:
`WINEPREFIX=$HOME/.vrs-wine winetricks win7`
`WINEPREFIX=$HOME/.vrs-wine winetricks dotnet48`
1. Now you can launch soft through that WINEPREFIX:
`WINEPREFIX=$HOME/.vrs-wine wine VRS.exe` - launch VRS software from installation directory.
## Known issues with the driver
- Current limit of usable buttons is 160 (up from the Linux default of 80). Create an issue if you want this increased further.

View File

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

View File

@@ -1,67 +1,91 @@
00000000 # Constant force left
00000000 > UPLOAD id:-1 dir:16384 type:CONSTANT level:9000
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:-9000
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:32767 right_coeff:32767
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:9000
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:9000
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:9000
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:12000
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:-12000
36000000 > UPLOAD id:0 dir:16384 type:PERIODIC waveform:SINE period:1000 magnitude:0 offset:-4000
39000000 > STOP 0
39000000 > REMOVE 0
39000000 # Sine constant force emulation right
39000000 > UPLOAD id:0 dir:16384 type:PERIODIC waveform:SINE period:1000 magnitude:0 offset:-12000
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,6 +2,7 @@
#ifndef __HID_IDS_H
#define __HID_IDS_H
// Moza Racing
#define USB_VENDOR_ID_MOZA 0x346e
#define USB_DEVICE_ID_MOZA_R3 0x0005
#define USB_DEVICE_ID_MOZA_R5 0x0004
@@ -9,8 +10,29 @@
#define USB_DEVICE_ID_MOZA_R12 0x0006
#define USB_DEVICE_ID_MOZA_R16_R21 0x0000
// 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
// VRS DrivingForce Pro
#define USB_VENDOR_ID_VRS 0x0483
#define USB_DEVICE_ID_VRS_DFP 0xa355
// FFBeast
#define USB_VENDOR_ID_FFBEAST 0x045b
#define USB_DEVICE_ID_FFBEAST_WHEEL 0x59d7
// LITESTAR
#define USB_VENDOR_ID_LITESTAR 0x11ff
#define USB_DEVICE_ID_LITESTAR_WHEEL 0x2141
#endif

View File

@@ -11,6 +11,7 @@
#include <linux/hid.h>
#include <linux/module.h>
#include <linux/input-event-codes.h>
#include <linux/version.h>
#include "hid-ids.h"
#include "hid-pidff.h"
@@ -27,16 +28,38 @@ static const struct hid_device_id pidff_wheel_devices[] = {
.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 },
{ 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 },
{ HID_USB_DEVICE(USB_VENDOR_ID_FFBEAST, USB_DEVICE_ID_FFBEAST_WHEEL),
.driver_data = PIDFF_QUIRK_NO_DELAY_EFFECT },
{ HID_USB_DEVICE(USB_VENDOR_ID_LITESTAR, USB_DEVICE_ID_LITESTAR_WHEEL),
.driver_data = PIDFF_QUIRK_FIX_WHEEL_DIRECTION },
{ }
};
MODULE_DEVICE_TABLE(hid, pidff_wheel_devices);
static u8 *moza_report_fixup(struct hid_device *hdev, __u8 *rdesc,
static
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,12,0)
const
#endif
u8 *moza_report_fixup(struct hid_device *hdev, __u8 *rdesc,
unsigned int *rsize)
{
// Fix data type on PID Device Control
@@ -47,7 +70,11 @@ static u8 *moza_report_fixup(struct hid_device *hdev, __u8 *rdesc,
}
static u8 *universal_pidff_report_fixup(struct hid_device *hdev, __u8 *rdesc,
static
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,12,0)
const
#endif
u8 *universal_pidff_report_fixup(struct hid_device *hdev, __u8 *rdesc,
unsigned int *rsize)
{
if (hdev->vendor == USB_VENDOR_ID_MOZA) {
@@ -71,7 +98,7 @@ static int universal_pidff_input_mapping(struct hid_device *hdev, struct hid_inp
int code = button + BTN_JOYSTICK;
// Detect the end of JOYSTICK buttons range
// KEY_AUDIO_DESC = 0x270
// KEY_NEXT_FAVORITE = 0x270
if (code > BTN_DEAD)
code = button + KEY_NEXT_FAVORITE - JOY_RANGE;

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
@@ -442,11 +447,18 @@ 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++) {
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);
@@ -999,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);
@@ -1010,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);
@@ -1207,10 +1223,26 @@ static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev)
clear_bit(FF_RAMP, 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)) &&
PIDFF_FIND_FIELDS(set_condition, PID_SET_CONDITION, 1)) {
hid_warn(pidff->hid, "unknown condition effect layout\n");
clear_bit(FF_SPRING, dev->ffbit);

View File

@@ -11,9 +11,25 @@
/*
* Skip initialization of 0xA7 descriptor (Delay effect)
*/
* Fixes VRS DFP, Cammus, old Simagic wheelbases
*/
#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);
#endif