HID: pidff: Add MISSING_DELAY quirk and its detection
[ Upstream commit 2d5c7ce5bf4cc27db41632f357f682d0ee4518e7 ] A lot of devices do not include this field, and it's seldom used in force feedback implementations. I tested about three dozen applications and none of them make use of the delay. This fixes initialization of a lot of PID wheels like Cammus, VRS, FFBeast This change has no effect on fully compliant devices Co-developed-by: Makarenko Oleg <oleg@makarenk.ooo> Signed-off-by: Makarenko Oleg <oleg@makarenk.ooo> Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com> Reviewed-by: Michał Kopeć <michal@nozomi.space> Reviewed-by: Paul Dino Jones <paul@spacefreak18.xyz> Tested-by: Paul Dino Jones <paul@spacefreak18.xyz> Tested-by: Cristóferson Bueno <cbueno81@gmail.com> Tested-by: Pablo Cisneros <patchkez@protonmail.com> Signed-off-by: Jiri Kosina <jkosina@suse.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
d21ccf544c
commit
fab3dbb604
@@ -185,6 +185,8 @@ struct pidff_device {
|
|||||||
int operation_id[sizeof(pidff_effect_operation_status)];
|
int operation_id[sizeof(pidff_effect_operation_status)];
|
||||||
|
|
||||||
int pid_id[PID_EFFECTS_MAX];
|
int pid_id[PID_EFFECTS_MAX];
|
||||||
|
|
||||||
|
u32 quirks;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -329,7 +331,10 @@ static void pidff_set_effect_report(struct pidff_device *pidff,
|
|||||||
pidff->effect_direction->value[0] =
|
pidff->effect_direction->value[0] =
|
||||||
pidff_rescale(effect->direction, 0xffff,
|
pidff_rescale(effect->direction, 0xffff,
|
||||||
pidff->effect_direction);
|
pidff->effect_direction);
|
||||||
pidff->set_effect[PID_START_DELAY].value[0] = effect->replay.delay;
|
|
||||||
|
/* Omit setting delay field if it's missing */
|
||||||
|
if (!(pidff->quirks & HID_PIDFF_QUIRK_MISSING_DELAY))
|
||||||
|
pidff->set_effect[PID_START_DELAY].value[0] = effect->replay.delay;
|
||||||
|
|
||||||
hid_hw_request(pidff->hid, pidff->reports[PID_SET_EFFECT],
|
hid_hw_request(pidff->hid, pidff->reports[PID_SET_EFFECT],
|
||||||
HID_REQ_SET_REPORT);
|
HID_REQ_SET_REPORT);
|
||||||
@@ -748,7 +753,10 @@ static void pidff_autocenter(struct pidff_device *pidff, u16 magnitude)
|
|||||||
pidff->set_effect[PID_TRIGGER_REPEAT_INT].value[0] = 0;
|
pidff->set_effect[PID_TRIGGER_REPEAT_INT].value[0] = 0;
|
||||||
pidff_set(&pidff->set_effect[PID_GAIN], magnitude);
|
pidff_set(&pidff->set_effect[PID_GAIN], magnitude);
|
||||||
pidff->set_effect[PID_DIRECTION_ENABLE].value[0] = 1;
|
pidff->set_effect[PID_DIRECTION_ENABLE].value[0] = 1;
|
||||||
pidff->set_effect[PID_START_DELAY].value[0] = 0;
|
|
||||||
|
/* Omit setting delay field if it's missing */
|
||||||
|
if (!(pidff->quirks & HID_PIDFF_QUIRK_MISSING_DELAY))
|
||||||
|
pidff->set_effect[PID_START_DELAY].value[0] = 0;
|
||||||
|
|
||||||
hid_hw_request(pidff->hid, pidff->reports[PID_SET_EFFECT],
|
hid_hw_request(pidff->hid, pidff->reports[PID_SET_EFFECT],
|
||||||
HID_REQ_SET_REPORT);
|
HID_REQ_SET_REPORT);
|
||||||
@@ -771,6 +779,7 @@ static int pidff_find_fields(struct pidff_usage *usage, const u8 *table,
|
|||||||
struct hid_report *report, int count, int strict)
|
struct hid_report *report, int count, int strict)
|
||||||
{
|
{
|
||||||
int i, j, k, found;
|
int i, j, k, found;
|
||||||
|
int return_value = 0;
|
||||||
|
|
||||||
for (k = 0; k < count; k++) {
|
for (k = 0; k < count; k++) {
|
||||||
found = 0;
|
found = 0;
|
||||||
@@ -795,12 +804,17 @@ static int pidff_find_fields(struct pidff_usage *usage, const u8 *table,
|
|||||||
if (found)
|
if (found)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!found && strict) {
|
if (!found && table[k] == pidff_set_effect[PID_START_DELAY]) {
|
||||||
|
pr_debug("Delay field not found, but that's OK\n");
|
||||||
|
pr_debug("Setting MISSING_DELAY quirk\n");
|
||||||
|
return_value |= HID_PIDFF_QUIRK_MISSING_DELAY;
|
||||||
|
}
|
||||||
|
else if (!found && strict) {
|
||||||
pr_debug("failed to locate %d\n", k);
|
pr_debug("failed to locate %d\n", k);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return return_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1075,11 +1089,19 @@ static int pidff_find_effects(struct pidff_device *pidff,
|
|||||||
static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev)
|
static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev)
|
||||||
{
|
{
|
||||||
int envelope_ok = 0;
|
int envelope_ok = 0;
|
||||||
|
int status = 0;
|
||||||
|
|
||||||
if (PIDFF_FIND_FIELDS(set_effect, PID_SET_EFFECT, 1)) {
|
/* Save info about the device not having the DELAY ffb field. */
|
||||||
|
status = PIDFF_FIND_FIELDS(set_effect, PID_SET_EFFECT, 1);
|
||||||
|
if (status == -1) {
|
||||||
hid_err(pidff->hid, "unknown set_effect report layout\n");
|
hid_err(pidff->hid, "unknown set_effect report layout\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
pidff->quirks |= status;
|
||||||
|
|
||||||
|
if (status & HID_PIDFF_QUIRK_MISSING_DELAY)
|
||||||
|
hid_dbg(pidff->hid, "Adding MISSING_DELAY quirk\n");
|
||||||
|
|
||||||
|
|
||||||
PIDFF_FIND_FIELDS(block_load, PID_BLOCK_LOAD, 0);
|
PIDFF_FIND_FIELDS(block_load, PID_BLOCK_LOAD, 0);
|
||||||
if (!pidff->block_load[PID_EFFECT_BLOCK_INDEX].value) {
|
if (!pidff->block_load[PID_EFFECT_BLOCK_INDEX].value) {
|
||||||
@@ -1323,6 +1345,7 @@ int hid_pidff_init(struct hid_device *hid)
|
|||||||
ff->playback = pidff_playback;
|
ff->playback = pidff_playback;
|
||||||
|
|
||||||
hid_info(dev, "Force feedback for USB HID PID devices by Anssi Hannula <anssi.hannula@gmail.com>\n");
|
hid_info(dev, "Force feedback for USB HID PID devices by Anssi Hannula <anssi.hannula@gmail.com>\n");
|
||||||
|
hid_dbg(dev, "Active quirks mask: 0x%x\n", pidff->quirks);
|
||||||
|
|
||||||
hid_device_io_stop(hid);
|
hid_device_io_stop(hid);
|
||||||
|
|
||||||
|
|||||||
@@ -1227,6 +1227,9 @@ int hid_pidff_init(struct hid_device *hid);
|
|||||||
#define hid_pidff_init NULL
|
#define hid_pidff_init NULL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* HID PIDFF quirks */
|
||||||
|
#define HID_PIDFF_QUIRK_MISSING_DELAY BIT(0)
|
||||||
|
|
||||||
#define dbg_hid(fmt, ...) pr_debug("%s: " fmt, __FILE__, ##__VA_ARGS__)
|
#define dbg_hid(fmt, ...) pr_debug("%s: " fmt, __FILE__, ##__VA_ARGS__)
|
||||||
|
|
||||||
#define hid_err(hid, fmt, ...) \
|
#define hid_err(hid, fmt, ...) \
|
||||||
|
|||||||
Reference in New Issue
Block a user