Skip to content

Commit fc7c154

Browse files
LawstorantJiri Kosina
authored andcommitted
HID: pidff: Add MISSING_PBO quirk and its detection
Some devices with only one axis are missing PARAMETER_BLOCK_OFFSET field for conditional effects. They can only have one axis, so we're limiting the max_axis when setting the report for those effects. Automatic detection ensures compatibility even if such device won't be explicitly defined in the kernel. Fixes initialization of VRS DirectForce PRO and possibly other devices. Changes in v6: - Fixed NULL pointer dereference. When PBO is missing, make sure not to set it anyway 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>
1 parent 2d5c7ce commit fc7c154

2 files changed

Lines changed: 30 additions & 18 deletions

File tree

drivers/hid/usbhid/hid-pidff.c

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -404,13 +404,19 @@ static int pidff_needs_set_periodic(struct ff_effect *effect,
404404
static void pidff_set_condition_report(struct pidff_device *pidff,
405405
struct ff_effect *effect)
406406
{
407-
int i;
407+
int i, max_axis;
408+
409+
/* Devices missing Parameter Block Offset can only have one axis */
410+
max_axis = pidff->quirks & HID_PIDFF_QUIRK_MISSING_PBO ? 1 : 2;
408411

409412
pidff->set_condition[PID_EFFECT_BLOCK_INDEX].value[0] =
410413
pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0];
411414

412-
for (i = 0; i < 2; i++) {
413-
pidff->set_condition[PID_PARAM_BLOCK_OFFSET].value[0] = i;
415+
for (i = 0; i < max_axis; i++) {
416+
/* Omit Parameter Block Offset if missing */
417+
if (!(pidff->quirks & HID_PIDFF_QUIRK_MISSING_PBO))
418+
pidff->set_condition[PID_PARAM_BLOCK_OFFSET].value[0] = i;
419+
414420
pidff_set_signed(&pidff->set_condition[PID_CP_OFFSET],
415421
effect->u.condition[i].center);
416422
pidff_set_signed(&pidff->set_condition[PID_POS_COEFFICIENT],
@@ -822,6 +828,11 @@ static int pidff_find_fields(struct pidff_usage *usage, const u8 *table,
822828
pr_debug("Setting MISSING_DELAY quirk\n");
823829
return_value |= HID_PIDFF_QUIRK_MISSING_DELAY;
824830
}
831+
else if (!found && table[k] == pidff_set_condition[PID_PARAM_BLOCK_OFFSET]) {
832+
pr_debug("PBO field not found, but that's OK\n");
833+
pr_debug("Setting MISSING_PBO quirk\n");
834+
return_value |= HID_PIDFF_QUIRK_MISSING_PBO;
835+
}
825836
else if (!found && strict) {
826837
pr_debug("failed to locate %d\n", k);
827838
return -1;
@@ -1101,7 +1112,6 @@ static int pidff_find_effects(struct pidff_device *pidff,
11011112
*/
11021113
static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev)
11031114
{
1104-
int envelope_ok = 0;
11051115
int status = 0;
11061116

11071117
/* Save info about the device not having the DELAY ffb field. */
@@ -1132,13 +1142,10 @@ static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev)
11321142
return -ENODEV;
11331143
}
11341144

1135-
if (!PIDFF_FIND_FIELDS(set_envelope, PID_SET_ENVELOPE, 1))
1136-
envelope_ok = 1;
1137-
11381145
if (pidff_find_special_fields(pidff) || pidff_find_effects(pidff, dev))
11391146
return -ENODEV;
11401147

1141-
if (!envelope_ok) {
1148+
if (PIDFF_FIND_FIELDS(set_envelope, PID_SET_ENVELOPE, 1)) {
11421149
if (test_and_clear_bit(FF_CONSTANT, dev->ffbit))
11431150
hid_warn(pidff->hid,
11441151
"has constant effect but no envelope\n");
@@ -1163,16 +1170,20 @@ static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev)
11631170
clear_bit(FF_RAMP, dev->ffbit);
11641171
}
11651172

1166-
if ((test_bit(FF_SPRING, dev->ffbit) ||
1167-
test_bit(FF_DAMPER, dev->ffbit) ||
1168-
test_bit(FF_FRICTION, dev->ffbit) ||
1169-
test_bit(FF_INERTIA, dev->ffbit)) &&
1170-
PIDFF_FIND_FIELDS(set_condition, PID_SET_CONDITION, 1)) {
1171-
hid_warn(pidff->hid, "unknown condition effect layout\n");
1172-
clear_bit(FF_SPRING, dev->ffbit);
1173-
clear_bit(FF_DAMPER, dev->ffbit);
1174-
clear_bit(FF_FRICTION, dev->ffbit);
1175-
clear_bit(FF_INERTIA, dev->ffbit);
1173+
if (test_bit(FF_SPRING, dev->ffbit) ||
1174+
test_bit(FF_DAMPER, dev->ffbit) ||
1175+
test_bit(FF_FRICTION, dev->ffbit) ||
1176+
test_bit(FF_INERTIA, dev->ffbit)) {
1177+
status = PIDFF_FIND_FIELDS(set_condition, PID_SET_CONDITION, 1);
1178+
1179+
if (status < 0) {
1180+
hid_warn(pidff->hid, "unknown condition effect layout\n");
1181+
clear_bit(FF_SPRING, dev->ffbit);
1182+
clear_bit(FF_DAMPER, dev->ffbit);
1183+
clear_bit(FF_FRICTION, dev->ffbit);
1184+
clear_bit(FF_INERTIA, dev->ffbit);
1185+
}
1186+
pidff->quirks |= status;
11761187
}
11771188

11781189
if (test_bit(FF_PERIODIC, dev->ffbit) &&

include/linux/hid.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1230,6 +1230,7 @@ int hid_pidff_init(struct hid_device *hid);
12301230

12311231
/* HID PIDFF quirks */
12321232
#define HID_PIDFF_QUIRK_MISSING_DELAY BIT(0)
1233+
#define HID_PIDFF_QUIRK_MISSING_PBO BIT(1)
12331234

12341235
#define dbg_hid(fmt, ...) pr_debug("%s: " fmt, __FILE__, ##__VA_ARGS__)
12351236

0 commit comments

Comments
 (0)