HID: pidff: Simplify HID field/usage searching logic

Some deduplication and splitting into separate functions. This is now
way easier to comprehend and parse mentally.

Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.com>
This commit is contained in:
Tomasz Pakuła
2025-08-13 22:09:55 +02:00
committed by Jiri Kosina
parent 7f3d7bc0df
commit b974b372a9

View File

@@ -939,6 +939,43 @@ static void pidff_set_autocenter(struct input_dev *dev, u16 magnitude)
pidff_autocenter(dev->ff->private, magnitude);
}
/*
* Find specific usage in a given hid_field
*/
static int pidff_find_usage(struct hid_field *fld, unsigned int usage_code)
{
for (int i = 0; i < fld->maxusage; i++) {
if (fld->usage[i].hid == usage_code)
return i;
}
return -1;
}
/*
* Find hid_field with a specific usage. Return the usage index as well
*/
static int pidff_find_field_with_usage(int *usage_index,
struct hid_report *report,
unsigned int usage_code)
{
for (int i = 0; i < report->maxfield; i++) {
struct hid_field *fld = report->field[i];
if (fld->maxusage != fld->report_count) {
pr_debug("maxusage and report_count do not match, skipping\n");
continue;
}
int index = pidff_find_usage(fld, usage_code);
if (index >= 0) {
*usage_index = index;
return i;
}
}
return -1;
}
/*
* Find fields from a report and fill a pidff_usage
*/
@@ -946,46 +983,38 @@ static int pidff_find_fields(struct pidff_usage *usage, const u8 *table,
struct hid_report *report, int count, int strict,
u32 *quirks)
{
const u8 block_offset = pidff_set_condition[PID_PARAM_BLOCK_OFFSET];
const u8 delay = pidff_set_effect[PID_START_DELAY];
if (!report) {
pr_debug("%s, null report\n", __func__);
return -1;
}
int i, j, k, found;
for (int i = 0; i < count; i++) {
int index;
int found = pidff_find_field_with_usage(&index, report,
HID_UP_PID | table[i]);
for (k = 0; k < count; k++) {
found = 0;
for (i = 0; i < report->maxfield; i++) {
if (report->field[i]->maxusage !=
report->field[i]->report_count) {
pr_debug("maxusage and report_count do not match, skipping\n");
continue;
}
for (j = 0; j < report->field[i]->maxusage; j++) {
if (report->field[i]->usage[j].hid ==
(HID_UP_PID | table[k])) {
pr_debug("found %d at %d->%d\n",
k, i, j);
usage[k].field = report->field[i];
usage[k].value =
&report->field[i]->value[j];
found = 1;
break;
}
}
if (found)
break;
if (found >= 0) {
pr_debug("found %d at %d->%d\n", i, found, index);
usage[i].field = report->field[found];
usage[i].value = &report->field[found]->value[index];
continue;
}
if (!found && table[k] == pidff_set_effect[PID_START_DELAY]) {
if (table[i] == delay) {
pr_debug("Delay field not found, but that's OK\n");
pr_debug("Setting MISSING_DELAY quirk\n");
*quirks |= HID_PIDFF_QUIRK_MISSING_DELAY;
} else if (!found && table[k] == pidff_set_condition[PID_PARAM_BLOCK_OFFSET]) {
} else if (table[i] == block_offset) {
pr_debug("PBO field not found, but that's OK\n");
pr_debug("Setting MISSING_PBO quirk\n");
*quirks |= HID_PIDFF_QUIRK_MISSING_PBO;
} else if (!found && strict) {
pr_debug("failed to locate %d\n", k);
} else if (strict) {
pr_debug("failed to locate %d\n", i);
return -1;
}
}
@@ -1054,9 +1083,7 @@ static void pidff_find_reports(struct hid_device *hid, int report_type,
*/
static int pidff_reports_ok(struct pidff_device *pidff)
{
int i;
for (i = 0; i < PID_REQUIRED_REPORTS; i++) {
for (int i = 0; i < PID_REQUIRED_REPORTS; i++) {
if (!pidff->reports[i]) {
hid_dbg(pidff->hid, "%d missing\n", i);
return 0;
@@ -1077,9 +1104,7 @@ static struct hid_field *pidff_find_special_field(struct hid_report *report,
return NULL;
}
int i;
for (i = 0; i < report->maxfield; i++) {
for (int i = 0; i < report->maxfield; i++) {
if (report->field[i]->logical == (HID_UP_PID | usage) &&
report->field[i]->report_count > 0) {
if (!enforce_min ||
@@ -1099,18 +1124,12 @@ static struct hid_field *pidff_find_special_field(struct hid_report *report,
static int pidff_find_special_keys(int *keys, struct hid_field *fld,
const u8 *usagetable, int count)
{
int i, j;
int found = 0;
for (i = 0; i < count; i++) {
for (j = 0; j < fld->maxusage; j++) {
if (fld->usage[j].hid == (HID_UP_PID | usagetable[i])) {
keys[i] = j + 1;
found++;
break;
}
}
for (int i = 0; i < count; i++) {
keys[i] = pidff_find_usage(fld, HID_UP_PID | usagetable[i]) + 1;
if (keys[i])
found++;
}
return found;
}