HID: uclogic: Replace pen_frame_flag with subreport_list
authorNikolai Kondrashov <spbnick@gmail.com>
Sat, 19 Feb 2022 10:01:50 +0000 (11:01 +0100)
committerJiri Kosina <jkosina@suse.cz>
Tue, 1 Mar 2022 14:28:14 +0000 (15:28 +0100)
Replace a single pen_frame_flag in struct uclogic_params with
subreport_list in struct uclogic_params_pen to prepare for handling more
subreports in Huion HS610.

Signed-off-by: Nikolai Kondrashov <spbnick@gmail.com>
Signed-off-by: José Expósito <jose.exposito89@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
drivers/hid/hid-uclogic-core.c
drivers/hid/hid-uclogic-params.c
drivers/hid/hid-uclogic-params.h

index 26849f1f5459059fdcd94991d5b328267a3ce048..7092f86517a55fc57c7286bc2379853dcb437319 100644 (file)
@@ -350,26 +350,40 @@ static int uclogic_raw_event(struct hid_device *hdev,
        unsigned int report_id = report->id;
        struct uclogic_drvdata *drvdata = hid_get_drvdata(hdev);
        struct uclogic_params *params = &drvdata->params;
+       struct uclogic_params_pen_subreport *subreport;
+       struct uclogic_params_pen_subreport *subreport_list_end;
 
        /* Do not handle anything but input reports */
        if (report->type != HID_INPUT_REPORT)
                return 0;
 
-       /* Tweak pen reports, if necessary */
-       if ((report_id == params->pen.id) && (size >= 2)) {
-               /* If it's the "virtual" frame controls report */
-               if (params->frame.id != 0 &&
-                   data[1] & params->pen_frame_flag) {
-                       /* Change to virtual frame controls report ID */
-                       report_id = data[0] = params->frame.id;
-               } else {
-                       return uclogic_raw_event_pen(drvdata, data, size);
+       while (true) {
+               /* Tweak pen reports, if necessary */
+               if ((report_id == params->pen.id) && (size >= 2)) {
+                       subreport_list_end =
+                               params->pen.subreport_list +
+                               ARRAY_SIZE(params->pen.subreport_list);
+                       /* Try to match a subreport */
+                       for (subreport = params->pen.subreport_list;
+                            subreport < subreport_list_end &&
+                               (data[1] & subreport->mask) != subreport->mask;
+                            subreport++);
+                       /* If a subreport matched */
+                       if (subreport < subreport_list_end) {
+                               /* Change to subreport ID, and restart */
+                               report_id = data[0] = subreport->id;
+                               continue;
+                       } else {
+                               return uclogic_raw_event_pen(drvdata, data, size);
+                       }
                }
-       }
 
-       /* Tweak frame control reports, if necessary */
-       if (report_id == params->frame.id)
-               return uclogic_raw_event_frame(drvdata, data, size);
+               /* Tweak frame control reports, if necessary */
+               if (report_id == params->frame.id)
+                       return uclogic_raw_event_frame(drvdata, data, size);
+
+               break;
+       }
 
        return 0;
 }
index 71496735cbf04eee9dc6fa8384a9247838123b2a..138dd8b0a3603be618cf055935fcab5113a50b12 100644 (file)
@@ -762,8 +762,10 @@ static int uclogic_params_huion_init(struct uclogic_params *params,
                                        rc);
                                goto cleanup;
                        }
-                       /* Set bitmask marking frame reports in pen reports */
-                       p.pen_frame_flag = 0x20;
+                       /* Link frame button subreports from pen reports */
+                       p.pen.subreport_list[0].mask = 0x20;
+                       p.pen.subreport_list[0].id =
+                               UCLOGIC_RDESC_BUTTONPAD_V2_ID;
                        goto output;
                }
                hid_dbg(hdev, "pen v2 parameters not found\n");
@@ -788,8 +790,10 @@ static int uclogic_params_huion_init(struct uclogic_params *params,
                hid_dbg(hdev, "buttonpad v1 parameters%s found\n",
                        (found ? "" : " not"));
                if (found) {
-                       /* Set bitmask marking frame reports */
-                       p.pen_frame_flag = 0x20;
+                       /* Link frame button subreports from pen reports */
+                       p.pen.subreport_list[0].mask = 0x20;
+                       p.pen.subreport_list[0].id =
+                               UCLOGIC_RDESC_BUTTONPAD_V1_ID;
                }
                goto output;
        }
index 48b974943bb9c98fda63437f01ea2c6da7e005b2..82db8ab36fecbc5c7d9dc990606bbb2c6dbd4134 100644 (file)
@@ -33,6 +33,24 @@ enum uclogic_params_pen_inrange {
 extern const char *uclogic_params_pen_inrange_to_str(
                        enum uclogic_params_pen_inrange inrange);
 
+
+/*
+ * Pen report's subreport data.
+ */
+struct uclogic_params_pen_subreport {
+       /*
+        * The subreport's bitmask matching the second byte of the pen report.
+        * If zero, the subreport is considered invalid, and won't match.
+        */
+       __u8 mask;
+
+       /*
+        * The ID to be assigned to the report, if the "mask" matches.
+        * Only valid if "mask" is not zero.
+        */
+       __u8 id;
+};
+
 /*
  * Tablet interface's pen input parameters.
  *
@@ -54,6 +72,8 @@ struct uclogic_params_pen {
        unsigned int desc_size;
        /* Report ID, if reports should be tweaked, zero if not */
        unsigned int id;
+       /* The list of subreports */
+       struct uclogic_params_pen_subreport subreport_list[1];
        /* Type of in-range reporting, only valid if "id" is not zero */
        enum uclogic_params_pen_inrange inrange;
        /*
@@ -148,13 +168,6 @@ struct uclogic_params {
         * Only valid, if "invalid" is false.
         */
        struct uclogic_params_frame frame;
-       /*
-        * Bitmask matching frame controls "sub-report" flag in the second
-        * byte of the pen report, or zero if it's not expected.
-        * Only valid if both "pen" and "frame" are valid, and "frame.id" is
-        * not zero.
-        */
-       __u8 pen_frame_flag;
 };
 
 /* Initialize a tablet interface and discover its parameters */
@@ -163,21 +176,21 @@ extern int uclogic_params_init(struct uclogic_params *params,
 
 /* Tablet interface parameters *printf format string */
 #define UCLOGIC_PARAMS_FMT_STR \
-               ".invalid = %s\n"                   \
-               ".desc_ptr = %p\n"                  \
-               ".desc_size = %u\n"                 \
-               ".pen.desc_ptr = %p\n"              \
-               ".pen.desc_size = %u\n"             \
-               ".pen.id = %u\n"                    \
-               ".pen.inrange = %s\n"               \
-               ".pen.fragmented_hires = %s\n"      \
-               ".pen.tilt_y_flipped = %s\n"        \
-               ".frame.desc_ptr = %p\n"            \
-               ".frame.desc_size = %u\n"           \
-               ".frame.id = %u\n"                  \
-               ".frame.re_lsb = %u\n"              \
-               ".frame.dev_id_byte = %u\n"         \
-               ".pen_frame_flag = 0x%02x\n"
+               ".invalid = %s\n"                               \
+               ".desc_ptr = %p\n"                              \
+               ".desc_size = %u\n"                             \
+               ".pen.desc_ptr = %p\n"                          \
+               ".pen.desc_size = %u\n"                         \
+               ".pen.id = %u\n"                                \
+               ".pen.subreport_list[0] = {0x%02hhx, %hhu}\n"   \
+               ".pen.inrange = %s\n"                           \
+               ".pen.fragmented_hires = %s\n"                  \
+               ".pen.tilt_y_flipped = %s\n"                    \
+               ".frame.desc_ptr = %p\n"                        \
+               ".frame.desc_size = %u\n"                       \
+               ".frame.id = %u\n"                              \
+               ".frame.re_lsb = %u\n"                          \
+               ".frame.dev_id_byte = %u\n"
 
 /* Tablet interface parameters *printf format arguments */
 #define UCLOGIC_PARAMS_FMT_ARGS(_params) \
@@ -187,6 +200,8 @@ extern int uclogic_params_init(struct uclogic_params *params,
                (_params)->pen.desc_ptr,                                    \
                (_params)->pen.desc_size,                                   \
                (_params)->pen.id,                                          \
+               (_params)->pen.subreport_list[0].mask,                      \
+               (_params)->pen.subreport_list[0].id,                        \
                uclogic_params_pen_inrange_to_str((_params)->pen.inrange),  \
                ((_params)->pen.fragmented_hires ? "true" : "false"),       \
                ((_params)->pen.tilt_y_flipped ? "true" : "false"),         \
@@ -194,8 +209,7 @@ extern int uclogic_params_init(struct uclogic_params *params,
                (_params)->frame.desc_size,                                 \
                (_params)->frame.id,                                        \
                (_params)->frame.re_lsb,                                    \
-               (_params)->frame.dev_id_byte,                               \
-               (_params)->pen_frame_flag
+               (_params)->frame.dev_id_byte
 
 /* Get a replacement report descriptor for a tablet's interface. */
 extern int uclogic_params_get_desc(const struct uclogic_params *params,