1 Commits

Author SHA1 Message Date
Oleg
f8809a3a3f Bump dkms package_version 2024-08-08 03:02:21 +03:00
7 changed files with 16 additions and 278 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 multiple quirks for better initialization rules for different wheelbases
1. Added 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,10 +16,8 @@ And that's basically it
## What devices are supported?
### Bases:
1. MOZA R3, R5, R9, R12, R16, R21
2. Cammus C5, C12
3. VRS DirectForce Pro
4. FFBeast Wheel
5. ...
2. Cammus C5
3. ...
## What works?
1. FFB (all effects from device descriptor)
@@ -27,9 +25,9 @@ And that's basically it
## What does not work?
1. Telemetry functions. They are handeled by [Monocoque](https://github.com/Spacefreak18/monocoque)
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.
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.
@@ -63,10 +61,7 @@ Best for debugging purposes, where you need frequently change codebase/branches
To unload module:
`sudo rmmod hid_universal_pidff`
### 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)?
## How to set up a base parameters?
### MOZA
**[Boxflat](https://github.com/Lawstorant/boxflat)** is a Linux Pit House alternative made by [@Lawstorant](https://github.com/Lawstorant)
@@ -75,42 +70,8 @@ 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.
- 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

View File

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

View File

@@ -1,91 +0,0 @@
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,7 +2,6 @@
#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
@@ -10,24 +9,7 @@
#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
#endif

View File

@@ -4,18 +4,14 @@
* 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 },
@@ -27,26 +23,8 @@ 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 },
{ }
};
MODULE_DEVICE_TABLE(hid, pidff_wheel_devices);
@@ -72,36 +50,6 @@ 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
@@ -137,30 +85,17 @@ err:
static int universal_pidff_input_configured(struct hid_device *hdev,
struct hid_input *hidinput)
{
// Remove fuzz and deadzone from the wheel axis
// Remove fuzz and deadzone
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
@@ -168,6 +103,5 @@ 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,11 +94,6 @@ 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
@@ -447,18 +442,11 @@ 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];
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) )
for (i = 0; i < 2; 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);
@@ -1011,10 +999,6 @@ 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);
@@ -1026,7 +1010,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, strict_pid_device_control);
0x96, 1);
pidff->block_load_status =
pidff_find_special_field(pidff->reports[PID_BLOCK_LOAD],
0x8b, 1);
@@ -1223,26 +1207,10 @@ 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,25 +11,9 @@
/*
* 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