Merge pull request #2 from Lawstorant/main
fix: direction for friction/damper/spring/inertia Added quirks for wheels
This commit is contained in:
18
README.md
18
README.md
@@ -16,8 +16,8 @@ And that's basically it
|
||||
1. MOZA R16
|
||||
1. MOZA R21
|
||||
|
||||
### Wheel rims:
|
||||
Not tested
|
||||
### Wheel rims (others yet untested):
|
||||
1. MOZA RS V2
|
||||
|
||||
## What works?
|
||||
1. FFB (all effects from device descriptor)
|
||||
@@ -29,12 +29,14 @@ Not tested
|
||||
2. `Firmware Update` function. Use Windows PC or Windows VM at the moment.
|
||||
3. Setup through MOZA PitHouse even with [some tweaking](#how-to-set-up-a-base-parameters))
|
||||
|
||||
## How to use that driver?
|
||||
You can install it through DKMS or manually.
|
||||
## How to use this driver?
|
||||
There's an [AUR packege](https://aur.archlinux.org/packages/moza-ff-dkms-git) for Arch Linux maintained by @Lawstorant
|
||||
|
||||
Alternatively, you can install it through DKMS or manually.
|
||||
### DKMS
|
||||
1. Install `dkms`
|
||||
2. Clone repository to `/usr/src/moza-ff`
|
||||
3. Install the module:
|
||||
3. Install the module:
|
||||
`sudo dkms install /usr/src/moza-ff`
|
||||
4. Update initramfs:
|
||||
`sudo update-initramfs -u`
|
||||
@@ -42,7 +44,7 @@ You can install it through DKMS or manually.
|
||||
|
||||
To remove module:
|
||||
`sudo dkms remove moza-ff/<version> --all`
|
||||
### Manually
|
||||
### Manually
|
||||
|
||||
1. Install `linux-headers-$(uname -r)`
|
||||
2. Clone repository
|
||||
@@ -86,8 +88,8 @@ Then you need to force MOZA soft to use hidraw, not SDL, to find devices:
|
||||
## Known issues with the driver
|
||||
1. Firmware update does not work. Please use Windows machine or Windows VM for any firmware updates
|
||||
|
||||
## Known issues with the firmware
|
||||
## Known issues with the firmware
|
||||
You tell me please
|
||||
|
||||
## DISCLAIMER
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
16
hid-moza.c
16
hid-moza.c
@@ -9,6 +9,7 @@
|
||||
#include <linux/hid.h>
|
||||
#include <linux/module.h>
|
||||
#include "hid-moza.h"
|
||||
#include "hid-pidff.h"
|
||||
|
||||
static const struct hid_device_id moza_devices[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R3) },
|
||||
@@ -32,8 +33,8 @@ static u8 *moza_report_fixup(struct hid_device *hdev, __u8 *rdesc,
|
||||
}
|
||||
|
||||
|
||||
static int moza_probe(struct hid_device *hdev,
|
||||
const struct hid_device_id *id)
|
||||
static int moza_probe(struct hid_device *hdev,
|
||||
const struct hid_device_id *id)
|
||||
{
|
||||
int ret;
|
||||
ret = hid_parse(hdev);
|
||||
@@ -48,7 +49,12 @@ static int moza_probe(struct hid_device *hdev,
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = hid_pidff_init_moza(hdev);
|
||||
/* set PIDFF quirks for moza wheelbases */
|
||||
unsigned quirks = 0;
|
||||
quirks |= PIDFF_QUIRK_FIX_0_INFINITE_LENGTH;
|
||||
quirks |= PIDFF_QUIRK_FIX_WHEEL_DIRECTION;
|
||||
|
||||
ret = hid_pidff_init_with_quirks(hdev, quirks);
|
||||
if (ret) {
|
||||
hid_warn(hdev, "Force feedback not supported\n");
|
||||
goto err;
|
||||
@@ -60,10 +66,10 @@ err:
|
||||
}
|
||||
|
||||
static int moza_input_configured(struct hid_device *hdev,
|
||||
struct hid_input *hidinput)
|
||||
struct hid_input *hidinput)
|
||||
{
|
||||
struct input_dev *input = hidinput->input;
|
||||
input_set_abs_params(input, ABS_X,
|
||||
input_set_abs_params(input, ABS_X,
|
||||
input->absinfo[ABS_X].minimum, input->absinfo[ABS_X].maximum, 0, 0);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -10,6 +10,4 @@
|
||||
#define USB_DEVICE_ID_MOZA_R16 0x0000
|
||||
#define USB_DEVICE_ID_MOZA_R21 0x0000
|
||||
|
||||
int hid_pidff_init_moza(struct hid_device *hdev);
|
||||
|
||||
#endif
|
||||
|
||||
64
hid-pidff.c
64
hid-pidff.c
@@ -3,6 +3,8 @@
|
||||
* Force feedback driver for USB HID PID compliant devices
|
||||
*
|
||||
* Copyright (c) 2005, 2006 Anssi Hannula <anssi.hannula@gmail.com>
|
||||
* Copyright (c) 2024 Makarenko Oleg <oleg@makarenk.ooo>
|
||||
* Copyright (c) 2024 Tomasz Pakuła <tomasz@pakula.org>
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -19,6 +21,7 @@
|
||||
#include <linux/hid.h>
|
||||
|
||||
//#include "usbhid.h"
|
||||
#include "hid-pidff.h"
|
||||
|
||||
#define PID_EFFECTS_MAX 64
|
||||
|
||||
@@ -184,6 +187,7 @@ struct pidff_device {
|
||||
int operation_id[sizeof(pidff_effect_operation_status)];
|
||||
|
||||
int pid_id[PID_EFFECTS_MAX];
|
||||
unsigned quirks;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -297,21 +301,35 @@ static int pidff_needs_set_constant(struct ff_effect *effect,
|
||||
static void pidff_set_effect_report(struct pidff_device *pidff,
|
||||
struct ff_effect *effect)
|
||||
{
|
||||
/* check for device quirks */
|
||||
unsigned short direction = effect->direction;
|
||||
unsigned short length = effect->replay.length;
|
||||
|
||||
if (pidff->quirks & PIDFF_QUIRK_FIX_0_INFINITE_LENGTH && length == 0)
|
||||
length = 0xffff;
|
||||
|
||||
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;
|
||||
|
||||
pidff->set_effect[PID_EFFECT_BLOCK_INDEX].value[0] =
|
||||
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 == 0 ? 0xffff: effect->replay.length;
|
||||
pidff->set_effect[PID_TRIGGER_BUTTON].value[0] = effect->trigger.button;
|
||||
pidff->set_effect[PID_DURATION].value[0] = length;
|
||||
pidff->set_effect[PID_TRIGGER_BUTTON].value[0] =
|
||||
effect->trigger.button;
|
||||
pidff->set_effect[PID_TRIGGER_REPEAT_INT].value[0] =
|
||||
effect->trigger.interval;
|
||||
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);
|
||||
pidff_rescale(direction, 0xffff, pidff->effect_direction);
|
||||
|
||||
pidff->set_effect[PID_START_DELAY].value[0] = effect->replay.delay;
|
||||
|
||||
hid_hw_request(pidff->hid, pidff->reports[PID_SET_EFFECT],
|
||||
@@ -499,12 +517,13 @@ static void pidff_playback_pid(struct pidff_device *pidff, int pid_id, int n)
|
||||
} else {
|
||||
pidff->effect_operation_status->value[0] =
|
||||
pidff->operation_id[PID_EFFECT_START];
|
||||
|
||||
n = clamp(n, pidff->effect_operation[PID_LOOP_COUNT].field->logical_minimum,
|
||||
|
||||
n = clamp(n, pidff->effect_operation[PID_LOOP_COUNT].field->logical_minimum,
|
||||
pidff->effect_operation[PID_LOOP_COUNT].field->logical_maximum);
|
||||
pidff->effect_operation[PID_LOOP_COUNT].value[0] = n;
|
||||
}
|
||||
|
||||
hid_dbg(pidff->hid, "Playing effect %d %d times\n", pid_id, n);
|
||||
hid_hw_request(pidff->hid, pidff->reports[PID_EFFECT_OPERATION],
|
||||
HID_REQ_SET_REPORT);
|
||||
}
|
||||
@@ -1231,7 +1250,7 @@ static int pidff_check_autocenter(struct pidff_device *pidff,
|
||||
/*
|
||||
* Check if the device is PID and initialize it
|
||||
*/
|
||||
int hid_pidff_init_moza(struct hid_device *hid)
|
||||
int hid_pidff_init(struct hid_device *hid)
|
||||
{
|
||||
struct pidff_device *pidff;
|
||||
struct hid_input *hidinput = list_entry(hid->inputs.next,
|
||||
@@ -1253,6 +1272,7 @@ int hid_pidff_init_moza(struct hid_device *hid)
|
||||
return -ENOMEM;
|
||||
|
||||
pidff->hid = hid;
|
||||
pidff->quirks = 0;
|
||||
|
||||
hid_device_io_start(hid);
|
||||
|
||||
@@ -1318,7 +1338,7 @@ int hid_pidff_init_moza(struct hid_device *hid)
|
||||
ff->set_autocenter = pidff_set_autocenter;
|
||||
ff->playback = pidff_playback;
|
||||
|
||||
hid_info(dev, "Force feedback for Moza wheel\n");
|
||||
hid_info(dev, "Force feedback for USB HID PID devices\n");
|
||||
|
||||
hid_device_io_stop(hid);
|
||||
|
||||
@@ -1330,3 +1350,29 @@ int hid_pidff_init_moza(struct hid_device *hid)
|
||||
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, unsigned quirks)
|
||||
{
|
||||
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 |= quirks;
|
||||
hid_device_io_stop(hid);
|
||||
|
||||
hid_dbg(dev, "Device quirks: %d\n", pidff->quirks);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
22
hid-pidff.h
Normal file
22
hid-pidff.h
Normal file
@@ -0,0 +1,22 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __HID_PIDFF_H
|
||||
#define __HID_PIDFF_H
|
||||
|
||||
/* PIDFF Quirks to solve issues with certain devices */
|
||||
|
||||
/*
|
||||
* Substitute 0 length with 0xffff to resolve issues with
|
||||
* infinite effects coming from windows API
|
||||
*/
|
||||
#define PIDFF_QUIRK_FIX_0_INFINITE_LENGTH BIT(0)
|
||||
|
||||
/*
|
||||
* Ignore direction for spring/damping/friction/inertia effects
|
||||
* and always set 16384
|
||||
*/
|
||||
#define PIDFF_QUIRK_FIX_WHEEL_DIRECTION BIT(1)
|
||||
|
||||
int hid_pidff_init(struct hid_device *hid);
|
||||
int hid_pidff_init_with_quirks(struct hid_device *hid, unsigned quirks);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user