]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
HID: pidff: Simplify HID field/usage searching logic
authorTomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
Wed, 13 Aug 2025 20:09:55 +0000 (22:09 +0200)
committerJiri Kosina <jkosina@suse.com>
Fri, 15 Aug 2025 13:58:02 +0000 (15:58 +0200)
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>
drivers/hid/usbhid/hid-pidff.c

index c88442a087f1aa6ae41be61fe3ea0f281c4c13b7..2e8eac944be02e9050b9ca6ffd491690c631a9dc 100644 (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;
 }