From 1324c5ac76bf7dccdac0fb128d0a675e1ee21b39 Mon Sep 17 00:00:00 2001 From: Nikolai Kondrashov Date: Thu, 10 Feb 2022 20:04:31 +0100 Subject: [PATCH 01/16] HID: uclogic: Support Huion tilt reporting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for Huion v2 protocol tilt reporting. Describe reports as angles in degrees, which is not exactly true, but there doesn't seem to be a straightforward, consistent conversion possible, and what's reported would have to be enough. Signed-off-by: Nikolai Kondrashov Signed-off-by: José Expósito Signed-off-by: Jiri Kosina --- drivers/hid/hid-uclogic-core.c | 3 +++ drivers/hid/hid-uclogic-params.c | 1 + drivers/hid/hid-uclogic-params.h | 8 ++++++++ drivers/hid/hid-uclogic-rdesc.c | 12 +++++++++++- 4 files changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/hid/hid-uclogic-core.c b/drivers/hid/hid-uclogic-core.c index d8ab0139e5cd..823704bc02ef 100644 --- a/drivers/hid/hid-uclogic-core.c +++ b/drivers/hid/hid-uclogic-core.c @@ -304,6 +304,9 @@ static int uclogic_raw_event(struct hid_device *hdev, mod_timer(&drvdata->inrange_timer, jiffies + msecs_to_jiffies(100)); } + /* If we report tilt and Y direction is flipped */ + if (size >= 12 && params->pen.tilt_y_flipped) + data[11] = -data[11]; } /* Tweak frame control reports, if necessary */ diff --git a/drivers/hid/hid-uclogic-params.c b/drivers/hid/hid-uclogic-params.c index 3e70f969fb84..30e0f69ed5af 100644 --- a/drivers/hid/hid-uclogic-params.c +++ b/drivers/hid/hid-uclogic-params.c @@ -369,6 +369,7 @@ static int uclogic_params_pen_init_v2(struct uclogic_params_pen *pen, pen->id = UCLOGIC_RDESC_PEN_V2_ID; pen->inrange = UCLOGIC_PARAMS_PEN_INRANGE_NONE; pen->fragmented_hires = true; + pen->tilt_y_flipped = true; found = true; finish: *pfound = found; diff --git a/drivers/hid/hid-uclogic-params.h b/drivers/hid/hid-uclogic-params.h index ba48b1c7a0e5..e8381bb77bd0 100644 --- a/drivers/hid/hid-uclogic-params.h +++ b/drivers/hid/hid-uclogic-params.h @@ -62,6 +62,12 @@ struct uclogic_params_pen { * Only valid if "id" is not zero. */ bool fragmented_hires; + /* + * True if the pen reports tilt in bytes at offset 10 (X) and 11 (Y), + * and the Y tilt direction is flipped. + * Only valid if "id" is not zero. + */ + bool tilt_y_flipped; }; /* @@ -171,6 +177,7 @@ extern int uclogic_params_init(struct uclogic_params *params, ".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" \ @@ -189,6 +196,7 @@ extern int uclogic_params_init(struct uclogic_params *params, (_params)->pen.id, \ uclogic_params_pen_inrange_to_str((_params)->pen.inrange), \ ((_params)->pen.fragmented_hires ? "true" : "false"), \ + ((_params)->pen.tilt_y_flipped ? "true" : "false"), \ (_params)->frame.desc_ptr, \ (_params)->frame.desc_size, \ (_params)->frame.id, \ diff --git a/drivers/hid/hid-uclogic-rdesc.c b/drivers/hid/hid-uclogic-rdesc.c index 6dd6dcd09c8b..2607cbdf8ff2 100644 --- a/drivers/hid/hid-uclogic-rdesc.c +++ b/drivers/hid/hid-uclogic-rdesc.c @@ -633,7 +633,17 @@ const __u8 uclogic_rdesc_pen_v2_template_arr[] = { 0x27, UCLOGIC_RDESC_PEN_PH(PRESSURE_LM), /* Logical Maximum (PLACEHOLDER), */ 0x81, 0x02, /* Input (Variable), */ - 0x81, 0x03, /* Input (Constant, Variable), */ + 0x54, /* Unit Exponent (0), */ + 0x65, 0x14, /* Unit (Degrees), */ + 0x35, 0xC4, /* Physical Minimum (-60), */ + 0x45, 0x3C, /* Physical Maximum (60), */ + 0x15, 0xC4, /* Logical Minimum (-60), */ + 0x25, 0x3C, /* Logical Maximum (60), */ + 0x75, 0x08, /* Report Size (8), */ + 0x95, 0x02, /* Report Count (2), */ + 0x09, 0x3D, /* Usage (X Tilt), */ + 0x09, 0x3E, /* Usage (Y Tilt), */ + 0x81, 0x02, /* Input (Variable), */ 0xC0, /* End Collection, */ 0xC0 /* End Collection */ }; From 85e860715e2ccf8c99fb9ad747d6f01d0ed92076 Mon Sep 17 00:00:00 2001 From: Nikolai Kondrashov Date: Thu, 10 Feb 2022 20:04:32 +0100 Subject: [PATCH 02/16] HID: uclogic: Rename Huion HS64 PID to Huion Tablet 2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since the 006d Huion PID is used by multiple tablets (at least HS64 and HS610), rename its constant to a more general "USB_DEVICE_ID_HUION_TABLET2". Signed-off-by: Nikolai Kondrashov Signed-off-by: José Expósito Signed-off-by: Jiri Kosina --- drivers/hid/hid-ids.h | 2 +- drivers/hid/hid-uclogic-core.c | 2 +- drivers/hid/hid-uclogic-params.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 78bd3ddda442..cef51e93e220 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -606,7 +606,7 @@ #define USB_VENDOR_ID_HUION 0x256c #define USB_DEVICE_ID_HUION_TABLET 0x006e -#define USB_DEVICE_ID_HUION_HS64 0x006d +#define USB_DEVICE_ID_HUION_TABLET2 0x006d #define USB_VENDOR_ID_IBM 0x04b3 #define USB_DEVICE_ID_IBM_SCROLLPOINT_III 0x3100 diff --git a/drivers/hid/hid-uclogic-core.c b/drivers/hid/hid-uclogic-core.c index 823704bc02ef..850c660ec2ab 100644 --- a/drivers/hid/hid-uclogic-core.c +++ b/drivers/hid/hid-uclogic-core.c @@ -376,7 +376,7 @@ static const struct hid_device_id uclogic_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_HUION, USB_DEVICE_ID_HUION_TABLET) }, { HID_USB_DEVICE(USB_VENDOR_ID_HUION, - USB_DEVICE_ID_HUION_HS64) }, + USB_DEVICE_ID_HUION_TABLET2) }, { HID_USB_DEVICE(USB_VENDOR_ID_TRUST, USB_DEVICE_ID_TRUST_PANORA_TABLET) }, { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, diff --git a/drivers/hid/hid-uclogic-params.c b/drivers/hid/hid-uclogic-params.c index 30e0f69ed5af..98910d8dae92 100644 --- a/drivers/hid/hid-uclogic-params.c +++ b/drivers/hid/hid-uclogic-params.c @@ -993,7 +993,7 @@ int uclogic_params_init(struct uclogic_params *params, case VID_PID(USB_VENDOR_ID_HUION, USB_DEVICE_ID_HUION_TABLET): case VID_PID(USB_VENDOR_ID_HUION, - USB_DEVICE_ID_HUION_HS64): + USB_DEVICE_ID_HUION_TABLET2): case VID_PID(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_HUION_TABLET): case VID_PID(USB_VENDOR_ID_UCLOGIC, From 5591403cd67c28f3c49d76d7f43170de1b950d57 Mon Sep 17 00:00:00 2001 From: Nikolai Kondrashov Date: Thu, 10 Feb 2022 20:04:33 +0100 Subject: [PATCH 03/16] HID: uclogic: Support Huion 13th frame button MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Support reporting 13th frame button for Huion tablets. This supports reporting the button in the center of the dial for Huion HS610. Signed-off-by: Nikolai Kondrashov Signed-off-by: José Expósito Signed-off-by: Jiri Kosina --- drivers/hid/hid-uclogic-rdesc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/hid/hid-uclogic-rdesc.c b/drivers/hid/hid-uclogic-rdesc.c index 2607cbdf8ff2..ec16355d200b 100644 --- a/drivers/hid/hid-uclogic-rdesc.c +++ b/drivers/hid/hid-uclogic-rdesc.c @@ -689,8 +689,8 @@ const size_t uclogic_rdesc_pen_v2_template_size = 0xA0, /* Collection (Physical), */ \ 0x05, 0x09, /* Usage Page (Button), */ \ 0x19, 0x01, /* Usage Minimum (01h), */ \ - 0x29, 0x02, /* Usage Maximum (02h), */ \ - 0x95, 0x02, /* Report Count (2), */ \ + 0x29, 0x03, /* Usage Maximum (03h), */ \ + 0x95, 0x03, /* Report Count (3), */ \ 0x81, 0x02, /* Input (Variable), */ \ 0x95, _padding, /* Report Count (_padding), */ \ 0x81, 0x01, /* Input (Constant), */ \ @@ -699,14 +699,14 @@ const size_t uclogic_rdesc_pen_v2_template_size = /* Fixed report descriptor for (tweaked) v1 buttonpad reports */ const __u8 uclogic_rdesc_buttonpad_v1_arr[] = { - UCLOGIC_RDESC_BUTTONPAD_BYTES(20) + UCLOGIC_RDESC_BUTTONPAD_BYTES(19) }; const size_t uclogic_rdesc_buttonpad_v1_size = sizeof(uclogic_rdesc_buttonpad_v1_arr); /* Fixed report descriptor for (tweaked) v2 buttonpad reports */ const __u8 uclogic_rdesc_buttonpad_v2_arr[] = { - UCLOGIC_RDESC_BUTTONPAD_BYTES(52) + UCLOGIC_RDESC_BUTTONPAD_BYTES(51) }; const size_t uclogic_rdesc_buttonpad_v2_size = sizeof(uclogic_rdesc_buttonpad_v2_arr); From 7e418667f2ed035445f8631b451e41d4ec13533c Mon Sep 17 00:00:00 2001 From: Nikolai Kondrashov Date: Thu, 10 Feb 2022 20:04:34 +0100 Subject: [PATCH 04/16] HID: uclogic: Split pen and frame raw event handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to avoid ending up with a big uclogic_raw_event function, split it in two smaller functions: uclogic_raw_event_pen for the pen events and uclogic_raw_event_frame for the pad events. Signed-off-by: Nikolai Kondrashov Signed-off-by: José Expósito Signed-off-by: Jiri Kosina --- drivers/hid/hid-uclogic-core.c | 195 ++++++++++++++++++++------------- 1 file changed, 120 insertions(+), 75 deletions(-) diff --git a/drivers/hid/hid-uclogic-core.c b/drivers/hid/hid-uclogic-core.c index 850c660ec2ab..9187fd835a46 100644 --- a/drivers/hid/hid-uclogic-core.c +++ b/drivers/hid/hid-uclogic-core.c @@ -246,6 +246,123 @@ static int uclogic_resume(struct hid_device *hdev) } #endif +/** + * uclogic_raw_event_pen - handle raw pen events (pen HID reports). + * + * @drvdata: Driver data. + * @data: Report data buffer, can be modified. + * @size: Report data size, bytes. + * + * Returns: + * Negative value on error (stops event delivery), zero for success. + */ +static int uclogic_raw_event_pen(struct uclogic_drvdata *drvdata, + u8 *data, int size) +{ + struct uclogic_params *params = &drvdata->params; + + WARN_ON(drvdata == NULL); + WARN_ON(data == NULL && size != 0); + + /* If in-range reports are inverted */ + if (params->pen.inrange == + UCLOGIC_PARAMS_PEN_INRANGE_INVERTED) { + /* Invert the in-range bit */ + data[1] ^= 0x40; + } + /* + * If report contains fragmented high-resolution pen + * coordinates + */ + if (size >= 10 && params->pen.fragmented_hires) { + u8 pressure_low_byte; + u8 pressure_high_byte; + + /* Lift pressure bytes */ + pressure_low_byte = data[6]; + pressure_high_byte = data[7]; + /* + * Move Y coord to make space for high-order X + * coord byte + */ + data[6] = data[5]; + data[5] = data[4]; + /* Move high-order X coord byte */ + data[4] = data[8]; + /* Move high-order Y coord byte */ + data[7] = data[9]; + /* Place pressure bytes */ + data[8] = pressure_low_byte; + data[9] = pressure_high_byte; + } + /* If we need to emulate in-range detection */ + if (params->pen.inrange == UCLOGIC_PARAMS_PEN_INRANGE_NONE) { + /* Set in-range bit */ + data[1] |= 0x40; + /* (Re-)start in-range timeout */ + mod_timer(&drvdata->inrange_timer, + jiffies + msecs_to_jiffies(100)); + } + /* If we report tilt and Y direction is flipped */ + if (size >= 12 && params->pen.tilt_y_flipped) + data[11] = -data[11]; + + return 0; +} + +/** + * uclogic_raw_event_frame - handle raw frame events (frame HID reports). + * + * @drvdata: Driver data. + * @data: Report data buffer, can be modified. + * @size: Report data size, bytes. + * + * Returns: + * Negative value on error (stops event delivery), zero for success. + */ +static int uclogic_raw_event_frame(struct uclogic_drvdata *drvdata, + u8 *data, int size) +{ + struct uclogic_params *params = &drvdata->params; + + WARN_ON(drvdata == NULL); + WARN_ON(data == NULL && size != 0); + + /* If need to, and can, set pad device ID for Wacom drivers */ + if (params->frame.dev_id_byte > 0 && + params->frame.dev_id_byte < size) { + data[params->frame.dev_id_byte] = 0xf; + } + /* If need to, and can, read rotary encoder state change */ + if (params->frame.re_lsb > 0 && + params->frame.re_lsb / 8 < size) { + unsigned int byte = params->frame.re_lsb / 8; + unsigned int bit = params->frame.re_lsb % 8; + + u8 change; + u8 prev_state = drvdata->re_state; + /* Read Gray-coded state */ + u8 state = (data[byte] >> bit) & 0x3; + /* Encode state change into 2-bit signed integer */ + if ((prev_state == 1 && state == 0) || + (prev_state == 2 && state == 3)) { + change = 1; + } else if ((prev_state == 2 && state == 0) || + (prev_state == 1 && state == 3)) { + change = 3; + } else { + change = 0; + } + /* Write change */ + data[byte] = (data[byte] & ~((u8)3 << bit)) | + (change << bit); + /* Remember state */ + drvdata->re_state = state; + } + + return 0; +} + static int uclogic_raw_event(struct hid_device *hdev, struct hid_report *report, u8 *data, int size) @@ -265,85 +382,13 @@ static int uclogic_raw_event(struct hid_device *hdev, data[0] = params->frame.id; return 0; } - /* If in-range reports are inverted */ - if (params->pen.inrange == - UCLOGIC_PARAMS_PEN_INRANGE_INVERTED) { - /* Invert the in-range bit */ - data[1] ^= 0x40; - } - /* - * If report contains fragmented high-resolution pen - * coordinates - */ - if (size >= 10 && params->pen.fragmented_hires) { - u8 pressure_low_byte; - u8 pressure_high_byte; - - /* Lift pressure bytes */ - pressure_low_byte = data[6]; - pressure_high_byte = data[7]; - /* - * Move Y coord to make space for high-order X - * coord byte - */ - data[6] = data[5]; - data[5] = data[4]; - /* Move high-order X coord byte */ - data[4] = data[8]; - /* Move high-order Y coord byte */ - data[7] = data[9]; - /* Place pressure bytes */ - data[8] = pressure_low_byte; - data[9] = pressure_high_byte; - } - /* If we need to emulate in-range detection */ - if (params->pen.inrange == UCLOGIC_PARAMS_PEN_INRANGE_NONE) { - /* Set in-range bit */ - data[1] |= 0x40; - /* (Re-)start in-range timeout */ - mod_timer(&drvdata->inrange_timer, - jiffies + msecs_to_jiffies(100)); - } - /* If we report tilt and Y direction is flipped */ - if (size >= 12 && params->pen.tilt_y_flipped) - data[11] = -data[11]; + return uclogic_raw_event_pen(drvdata, data, size); } /* Tweak frame control reports, if necessary */ if ((report->type == HID_INPUT_REPORT) && - (report->id == params->frame.id)) { - /* If need to, and can, set pad device ID for Wacom drivers */ - if (params->frame.dev_id_byte > 0 && - params->frame.dev_id_byte < size) { - data[params->frame.dev_id_byte] = 0xf; - } - /* If need to, and can, read rotary encoder state change */ - if (params->frame.re_lsb > 0 && - params->frame.re_lsb / 8 < size) { - unsigned int byte = params->frame.re_lsb / 8; - unsigned int bit = params->frame.re_lsb % 8; - - u8 change; - u8 prev_state = drvdata->re_state; - /* Read Gray-coded state */ - u8 state = (data[byte] >> bit) & 0x3; - /* Encode state change into 2-bit signed integer */ - if ((prev_state == 1 && state == 0) || - (prev_state == 2 && state == 3)) { - change = 1; - } else if ((prev_state == 2 && state == 0) || - (prev_state == 1 && state == 3)) { - change = 3; - } else { - change = 0; - } - /* Write change */ - data[byte] = (data[byte] & ~((u8)3 << bit)) | - (change << bit); - /* Remember state */ - drvdata->re_state = state; - } - } + (report->id == params->frame.id)) + return uclogic_raw_event_frame(drvdata, data, size); return 0; } From 7f12dd246906de2504b157700a15f49935dc9598 Mon Sep 17 00:00:00 2001 From: Nikolai Kondrashov Date: Thu, 10 Feb 2022 20:04:35 +0100 Subject: [PATCH 05/16] HID: uclogic: Access pen/frame params directly in raw_event handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Simplify the raw event handling code by accessing the uclogic_params_pen/uclogic_params_frame structs directly. Signed-off-by: Nikolai Kondrashov Signed-off-by: José Expósito Signed-off-by: Jiri Kosina --- drivers/hid/hid-uclogic-core.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/drivers/hid/hid-uclogic-core.c b/drivers/hid/hid-uclogic-core.c index 9187fd835a46..56b76d9b46af 100644 --- a/drivers/hid/hid-uclogic-core.c +++ b/drivers/hid/hid-uclogic-core.c @@ -259,13 +259,13 @@ static int uclogic_resume(struct hid_device *hdev) static int uclogic_raw_event_pen(struct uclogic_drvdata *drvdata, u8 *data, int size) { - struct uclogic_params *params = &drvdata->params; + struct uclogic_params_pen *pen = &drvdata->params.pen; WARN_ON(drvdata == NULL); WARN_ON(data == NULL && size != 0); /* If in-range reports are inverted */ - if (params->pen.inrange == + if (pen->inrange == UCLOGIC_PARAMS_PEN_INRANGE_INVERTED) { /* Invert the in-range bit */ data[1] ^= 0x40; @@ -274,7 +274,7 @@ static int uclogic_raw_event_pen(struct uclogic_drvdata *drvdata, * If report contains fragmented high-resolution pen * coordinates */ - if (size >= 10 && params->pen.fragmented_hires) { + if (size >= 10 && pen->fragmented_hires) { u8 pressure_low_byte; u8 pressure_high_byte; @@ -296,7 +296,7 @@ static int uclogic_raw_event_pen(struct uclogic_drvdata *drvdata, data[9] = pressure_high_byte; } /* If we need to emulate in-range detection */ - if (params->pen.inrange == UCLOGIC_PARAMS_PEN_INRANGE_NONE) { + if (pen->inrange == UCLOGIC_PARAMS_PEN_INRANGE_NONE) { /* Set in-range bit */ data[1] |= 0x40; /* (Re-)start in-range timeout */ @@ -304,7 +304,7 @@ static int uclogic_raw_event_pen(struct uclogic_drvdata *drvdata, jiffies + msecs_to_jiffies(100)); } /* If we report tilt and Y direction is flipped */ - if (size >= 12 && params->pen.tilt_y_flipped) + if (size >= 12 && pen->tilt_y_flipped) data[11] = -data[11]; return 0; @@ -323,21 +323,19 @@ static int uclogic_raw_event_pen(struct uclogic_drvdata *drvdata, static int uclogic_raw_event_frame(struct uclogic_drvdata *drvdata, u8 *data, int size) { - struct uclogic_params *params = &drvdata->params; + struct uclogic_params_frame *frame = &drvdata->params.frame; WARN_ON(drvdata == NULL); WARN_ON(data == NULL && size != 0); /* If need to, and can, set pad device ID for Wacom drivers */ - if (params->frame.dev_id_byte > 0 && - params->frame.dev_id_byte < size) { - data[params->frame.dev_id_byte] = 0xf; + if (frame->dev_id_byte > 0 && frame->dev_id_byte < size) { + data[frame->dev_id_byte] = 0xf; } /* If need to, and can, read rotary encoder state change */ - if (params->frame.re_lsb > 0 && - params->frame.re_lsb / 8 < size) { - unsigned int byte = params->frame.re_lsb / 8; - unsigned int bit = params->frame.re_lsb % 8; + if (frame->re_lsb > 0 && frame->re_lsb / 8 < size) { + unsigned int byte = frame->re_lsb / 8; + unsigned int bit = frame->re_lsb % 8; u8 change; u8 prev_state = drvdata->re_state; From fea53b9f159cd039e86aebde5cbbfd37765257fb Mon Sep 17 00:00:00 2001 From: Nikolai Kondrashov Date: Thu, 10 Feb 2022 20:04:36 +0100 Subject: [PATCH 06/16] HID: uclogic: Skip non-input raw events earlier MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Early return when a non-input raw event is received to simplify the logic present in uclogic_raw_event. Signed-off-by: Nikolai Kondrashov Signed-off-by: José Expósito Signed-off-by: Jiri Kosina --- drivers/hid/hid-uclogic-core.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/hid/hid-uclogic-core.c b/drivers/hid/hid-uclogic-core.c index 56b76d9b46af..8aac3f7a9cda 100644 --- a/drivers/hid/hid-uclogic-core.c +++ b/drivers/hid/hid-uclogic-core.c @@ -368,9 +368,12 @@ static int uclogic_raw_event(struct hid_device *hdev, struct uclogic_drvdata *drvdata = hid_get_drvdata(hdev); struct uclogic_params *params = &drvdata->params; + /* Do not handle anything but input reports */ + if (report->type != HID_INPUT_REPORT) + return 0; + /* Tweak pen reports, if necessary */ if (!params->pen_unused && - (report->type == HID_INPUT_REPORT) && (report->id == params->pen.id) && (size >= 2)) { /* If it's the "virtual" frame controls report */ @@ -384,8 +387,7 @@ static int uclogic_raw_event(struct hid_device *hdev, } /* Tweak frame control reports, if necessary */ - if ((report->type == HID_INPUT_REPORT) && - (report->id == params->frame.id)) + if (report->id == params->frame.id) return uclogic_raw_event_frame(drvdata, data, size); return 0; From 044fa8162dc10686fcffa5501d4ca3947df047ca Mon Sep 17 00:00:00 2001 From: Nikolai Kondrashov Date: Thu, 10 Feb 2022 20:04:37 +0100 Subject: [PATCH 07/16] HID: uclogic: Handle virtual frame reports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Explicitly change report ID to virtual ID and handle virtual frame reports as real for consistency. Signed-off-by: Nikolai Kondrashov Signed-off-by: José Expósito Signed-off-by: Jiri Kosina --- drivers/hid/hid-uclogic-core.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/hid/hid-uclogic-core.c b/drivers/hid/hid-uclogic-core.c index 8aac3f7a9cda..73d79d149869 100644 --- a/drivers/hid/hid-uclogic-core.c +++ b/drivers/hid/hid-uclogic-core.c @@ -365,6 +365,7 @@ static int uclogic_raw_event(struct hid_device *hdev, struct hid_report *report, u8 *data, int size) { + unsigned int report_id = report->id; struct uclogic_drvdata *drvdata = hid_get_drvdata(hdev); struct uclogic_params *params = &drvdata->params; @@ -374,20 +375,20 @@ static int uclogic_raw_event(struct hid_device *hdev, /* Tweak pen reports, if necessary */ if (!params->pen_unused && - (report->id == params->pen.id) && + (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 */ - data[0] = params->frame.id; - return 0; + report_id = data[0] = params->frame.id; + } else { + return uclogic_raw_event_pen(drvdata, data, size); } - return uclogic_raw_event_pen(drvdata, data, size); } /* Tweak frame control reports, if necessary */ - if (report->id == params->frame.id) + if (report_id == params->frame.id) return uclogic_raw_event_frame(drvdata, data, size); return 0; From 606dadc1878f2fdeaa6e435c9c83f58a01387a7d Mon Sep 17 00:00:00 2001 From: Nikolai Kondrashov Date: Sat, 19 Feb 2022 11:01:49 +0100 Subject: [PATCH 08/16] HID: uclogic: Remove pen usage masking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove support for pen usage masking from hid-uclogic. Disable whole interfaces instead. Most of those interfaces are useless, and if there is one which has an unused pen usage, but also has useful reports, its report descriptor should be rewritten instead. This simplifies the code and the data structures. Signed-off-by: Nikolai Kondrashov Signed-off-by: José Expósito Signed-off-by: Jiri Kosina --- drivers/hid/hid-uclogic-core.c | 23 +---------------------- drivers/hid/hid-uclogic-params.c | 29 +++++------------------------ drivers/hid/hid-uclogic-params.h | 9 +-------- 3 files changed, 7 insertions(+), 54 deletions(-) diff --git a/drivers/hid/hid-uclogic-core.c b/drivers/hid/hid-uclogic-core.c index 73d79d149869..26849f1f5459 100644 --- a/drivers/hid/hid-uclogic-core.c +++ b/drivers/hid/hid-uclogic-core.c @@ -81,24 +81,6 @@ static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc, return rdesc; } -static int uclogic_input_mapping(struct hid_device *hdev, - struct hid_input *hi, - struct hid_field *field, - struct hid_usage *usage, - unsigned long **bit, - int *max) -{ - struct uclogic_drvdata *drvdata = hid_get_drvdata(hdev); - struct uclogic_params *params = &drvdata->params; - - /* discard the unused pen interface */ - if (params->pen_unused && (field->application == HID_DG_PEN)) - return -1; - - /* let hid-core decide what to do */ - return 0; -} - static int uclogic_input_configured(struct hid_device *hdev, struct hid_input *hi) { @@ -374,9 +356,7 @@ static int uclogic_raw_event(struct hid_device *hdev, return 0; /* Tweak pen reports, if necessary */ - if (!params->pen_unused && - (report_id == params->pen.id) && - (size >= 2)) { + 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) { @@ -464,7 +444,6 @@ static struct hid_driver uclogic_driver = { .remove = uclogic_remove, .report_fixup = uclogic_report_fixup, .raw_event = uclogic_raw_event, - .input_mapping = uclogic_input_mapping, .input_configured = uclogic_input_configured, #ifdef CONFIG_PM .resume = uclogic_resume, diff --git a/drivers/hid/hid-uclogic-params.c b/drivers/hid/hid-uclogic-params.c index 98910d8dae92..71496735cbf0 100644 --- a/drivers/hid/hid-uclogic-params.c +++ b/drivers/hid/hid-uclogic-params.c @@ -514,8 +514,7 @@ void uclogic_params_cleanup(struct uclogic_params *params) { if (!params->invalid) { kfree(params->desc_ptr); - if (!params->pen_unused) - uclogic_params_pen_cleanup(¶ms->pen); + uclogic_params_pen_cleanup(¶ms->pen); uclogic_params_frame_cleanup(¶ms->frame); memset(params, 0, sizeof(*params)); } @@ -557,7 +556,7 @@ int uclogic_params_get_desc(const struct uclogic_params *params, size = 0; common_present = (params->desc_ptr != NULL); - pen_present = (!params->pen_unused && params->pen.desc_ptr != NULL); + pen_present = (params->pen.desc_ptr != NULL); frame_present = (params->frame.desc_ptr != NULL); if (common_present) @@ -680,21 +679,6 @@ cleanup: return rc; } -/** - * uclogic_params_init_with_pen_unused() - initialize tablet interface - * parameters preserving original reports and generic HID processing, but - * disabling pen usage. - * - * @params: Parameters to initialize (to be cleaned with - * uclogic_params_cleanup()). Not modified in case of - * error. Cannot be NULL. - */ -static void uclogic_params_init_with_pen_unused(struct uclogic_params *params) -{ - memset(params, 0, sizeof(*params)); - params->pen_unused = true; -} - /** * uclogic_params_huion_init() - initialize a Huion tablet interface and discover * its parameters. @@ -734,8 +718,7 @@ static int uclogic_params_huion_init(struct uclogic_params *params, /* If it's not a pen interface */ if (bInterfaceNumber != 0) { - /* TODO: Consider marking the interface invalid */ - uclogic_params_init_with_pen_unused(&p); + uclogic_params_init_invalid(&p); goto output; } @@ -1033,8 +1016,7 @@ int uclogic_params_init(struct uclogic_params *params, uclogic_params_init_invalid(&p); } } else { - /* TODO: Consider marking the interface invalid */ - uclogic_params_init_with_pen_unused(&p); + uclogic_params_init_invalid(&p); } break; case VID_PID(USB_VENDOR_ID_UGEE, @@ -1056,8 +1038,7 @@ int uclogic_params_init(struct uclogic_params *params, if (rc != 0) goto cleanup; } else { - /* TODO: Consider marking the interface invalid */ - uclogic_params_init_with_pen_unused(&p); + uclogic_params_init_invalid(&p); } break; case VID_PID(USB_VENDOR_ID_TRUST, diff --git a/drivers/hid/hid-uclogic-params.h b/drivers/hid/hid-uclogic-params.h index e8381bb77bd0..48b974943bb9 100644 --- a/drivers/hid/hid-uclogic-params.h +++ b/drivers/hid/hid-uclogic-params.h @@ -138,14 +138,9 @@ struct uclogic_params { * Only valid, if "desc_ptr" is not NULL. */ unsigned int desc_size; - /* - * True, if pen usage in report descriptor is invalid, when present. - * Only valid, if "invalid" is false. - */ - bool pen_unused; /* * Pen parameters and optional report descriptor part. - * Only valid if "pen_unused" is valid and false. + * Only valid, if "invalid" is false. */ struct uclogic_params_pen pen; /* @@ -171,7 +166,6 @@ extern int uclogic_params_init(struct uclogic_params *params, ".invalid = %s\n" \ ".desc_ptr = %p\n" \ ".desc_size = %u\n" \ - ".pen_unused = %s\n" \ ".pen.desc_ptr = %p\n" \ ".pen.desc_size = %u\n" \ ".pen.id = %u\n" \ @@ -190,7 +184,6 @@ extern int uclogic_params_init(struct uclogic_params *params, ((_params)->invalid ? "true" : "false"), \ (_params)->desc_ptr, \ (_params)->desc_size, \ - ((_params)->pen_unused ? "true" : "false"), \ (_params)->pen.desc_ptr, \ (_params)->pen.desc_size, \ (_params)->pen.id, \ From 8b013098be2c91ea5e15225c8b39ace08fdd7448 Mon Sep 17 00:00:00 2001 From: Nikolai Kondrashov Date: Sat, 19 Feb 2022 11:01:50 +0100 Subject: [PATCH 09/16] HID: uclogic: Replace pen_frame_flag with subreport_list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Signed-off-by: José Expósito Signed-off-by: Jiri Kosina --- drivers/hid/hid-uclogic-core.c | 40 ++++++++++++++------- drivers/hid/hid-uclogic-params.c | 12 ++++--- drivers/hid/hid-uclogic-params.h | 62 +++++++++++++++++++------------- 3 files changed, 73 insertions(+), 41 deletions(-) diff --git a/drivers/hid/hid-uclogic-core.c b/drivers/hid/hid-uclogic-core.c index 26849f1f5459..7092f86517a5 100644 --- a/drivers/hid/hid-uclogic-core.c +++ b/drivers/hid/hid-uclogic-core.c @@ -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; } diff --git a/drivers/hid/hid-uclogic-params.c b/drivers/hid/hid-uclogic-params.c index 71496735cbf0..138dd8b0a360 100644 --- a/drivers/hid/hid-uclogic-params.c +++ b/drivers/hid/hid-uclogic-params.c @@ -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; } diff --git a/drivers/hid/hid-uclogic-params.h b/drivers/hid/hid-uclogic-params.h index 48b974943bb9..82db8ab36fec 100644 --- a/drivers/hid/hid-uclogic-params.h +++ b/drivers/hid/hid-uclogic-params.h @@ -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, From e6be956fd7e834428a940e23442c5d934c1c8835 Mon Sep 17 00:00:00 2001 From: Nikolai Kondrashov Date: Sat, 19 Feb 2022 11:01:51 +0100 Subject: [PATCH 10/16] HID: uclogic: Switch to matching subreport bytes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Switch from matching UC-Logic subreport with a mask to a full value to support detecting Huion HS610 touch dial reports. Those would match the button mask otherwise. Signed-off-by: Nikolai Kondrashov Signed-off-by: José Expósito Signed-off-by: Jiri Kosina --- drivers/hid/hid-uclogic-core.c | 9 ++++++--- drivers/hid/hid-uclogic-params.c | 4 ++-- drivers/hid/hid-uclogic-params.h | 13 +++++++------ 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/drivers/hid/hid-uclogic-core.c b/drivers/hid/hid-uclogic-core.c index 7092f86517a5..a02edeb30a35 100644 --- a/drivers/hid/hid-uclogic-core.c +++ b/drivers/hid/hid-uclogic-core.c @@ -365,9 +365,12 @@ static int uclogic_raw_event(struct hid_device *hdev, 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++); + subreport < subreport_list_end; subreport++) { + if (subreport->value != 0 && + subreport->value == data[1]) { + break; + } + } /* If a subreport matched */ if (subreport < subreport_list_end) { /* Change to subreport ID, and restart */ diff --git a/drivers/hid/hid-uclogic-params.c b/drivers/hid/hid-uclogic-params.c index 138dd8b0a360..a4a53ab1e72c 100644 --- a/drivers/hid/hid-uclogic-params.c +++ b/drivers/hid/hid-uclogic-params.c @@ -763,7 +763,7 @@ static int uclogic_params_huion_init(struct uclogic_params *params, goto cleanup; } /* Link frame button subreports from pen reports */ - p.pen.subreport_list[0].mask = 0x20; + p.pen.subreport_list[0].value = 0xe0; p.pen.subreport_list[0].id = UCLOGIC_RDESC_BUTTONPAD_V2_ID; goto output; @@ -791,7 +791,7 @@ static int uclogic_params_huion_init(struct uclogic_params *params, (found ? "" : " not")); if (found) { /* Link frame button subreports from pen reports */ - p.pen.subreport_list[0].mask = 0x20; + p.pen.subreport_list[0].value = 0xe0; p.pen.subreport_list[0].id = UCLOGIC_RDESC_BUTTONPAD_V1_ID; } diff --git a/drivers/hid/hid-uclogic-params.h b/drivers/hid/hid-uclogic-params.h index 82db8ab36fec..c18569591b75 100644 --- a/drivers/hid/hid-uclogic-params.h +++ b/drivers/hid/hid-uclogic-params.h @@ -39,14 +39,15 @@ extern const char *uclogic_params_pen_inrange_to_str( */ 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. + * The value of the second byte of the pen report indicating this + * subreport. If zero, the subreport should be considered invalid and + * not matched. */ - __u8 mask; + __u8 value; /* - * The ID to be assigned to the report, if the "mask" matches. - * Only valid if "mask" is not zero. + * The ID to be assigned to the report, if the second byte of the pen + * report is equal to "value". Only valid if "value" is not zero. */ __u8 id; }; @@ -200,7 +201,7 @@ 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].value, \ (_params)->pen.subreport_list[0].id, \ uclogic_params_pen_inrange_to_str((_params)->pen.inrange), \ ((_params)->pen.fragmented_hires ? "true" : "false"), \ From ce2401047520c917aa140c3658f8875ad0381553 Mon Sep 17 00:00:00 2001 From: Nikolai Kondrashov Date: Sat, 19 Feb 2022 11:01:52 +0100 Subject: [PATCH 11/16] HID: uclogic: Specify total report size to buttonpad macro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Simplify the UCLOGIC_RDESC_BUTTONPAD_BYTES macro by passing as param the size of the report to pad to in bytes. Signed-off-by: Nikolai Kondrashov Signed-off-by: José Expósito Signed-off-by: Jiri Kosina --- drivers/hid/hid-uclogic-rdesc.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/hid/hid-uclogic-rdesc.c b/drivers/hid/hid-uclogic-rdesc.c index ec16355d200b..6e5bef39417e 100644 --- a/drivers/hid/hid-uclogic-rdesc.c +++ b/drivers/hid/hid-uclogic-rdesc.c @@ -654,10 +654,9 @@ const size_t uclogic_rdesc_pen_v2_template_size = /* * Expand to the contents of a generic buttonpad report descriptor. * - * @_padding: Padding from the end of button bits at bit 44, until - * the end of the report, in bits. + * @_size: Size of the report to pad to, including report ID, bytes. */ -#define UCLOGIC_RDESC_BUTTONPAD_BYTES(_padding) \ +#define UCLOGIC_RDESC_BUTTONPAD_BYTES(_size) \ 0x05, 0x01, /* Usage Page (Desktop), */ \ 0x09, 0x07, /* Usage (Keypad), */ \ 0xA1, 0x01, /* Collection (Application), */ \ @@ -692,21 +691,22 @@ const size_t uclogic_rdesc_pen_v2_template_size = 0x29, 0x03, /* Usage Maximum (03h), */ \ 0x95, 0x03, /* Report Count (3), */ \ 0x81, 0x02, /* Input (Variable), */ \ - 0x95, _padding, /* Report Count (_padding), */ \ + 0x95, ((_size) * 8 - 45), \ + /* Report Count (padding), */ \ 0x81, 0x01, /* Input (Constant), */ \ 0xC0, /* End Collection, */ \ 0xC0 /* End Collection */ /* Fixed report descriptor for (tweaked) v1 buttonpad reports */ const __u8 uclogic_rdesc_buttonpad_v1_arr[] = { - UCLOGIC_RDESC_BUTTONPAD_BYTES(19) + UCLOGIC_RDESC_BUTTONPAD_BYTES(8) }; const size_t uclogic_rdesc_buttonpad_v1_size = sizeof(uclogic_rdesc_buttonpad_v1_arr); /* Fixed report descriptor for (tweaked) v2 buttonpad reports */ const __u8 uclogic_rdesc_buttonpad_v2_arr[] = { - UCLOGIC_RDESC_BUTTONPAD_BYTES(51) + UCLOGIC_RDESC_BUTTONPAD_BYTES(12) }; const size_t uclogic_rdesc_buttonpad_v2_size = sizeof(uclogic_rdesc_buttonpad_v2_arr); From 2f290b39e6a005385584e00718e4a2d6aff1710d Mon Sep 17 00:00:00 2001 From: Nikolai Kondrashov Date: Sat, 19 Feb 2022 11:01:53 +0100 Subject: [PATCH 12/16] HID: uclogic: Use different constants for frame report IDs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allow to set the report ID in UCLOGIC_RDESC_FRAME_BYTES instead of using a hardcoded value. Signed-off-by: Nikolai Kondrashov Signed-off-by: José Expósito Signed-off-by: Jiri Kosina --- drivers/hid/hid-uclogic-rdesc.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/hid/hid-uclogic-rdesc.c b/drivers/hid/hid-uclogic-rdesc.c index 6e5bef39417e..66aa83f67ccc 100644 --- a/drivers/hid/hid-uclogic-rdesc.c +++ b/drivers/hid/hid-uclogic-rdesc.c @@ -654,13 +654,14 @@ const size_t uclogic_rdesc_pen_v2_template_size = /* * Expand to the contents of a generic buttonpad report descriptor. * + * @_id: The report ID to use. * @_size: Size of the report to pad to, including report ID, bytes. */ -#define UCLOGIC_RDESC_BUTTONPAD_BYTES(_size) \ +#define UCLOGIC_RDESC_BUTTONPAD_BYTES(_id, _size) \ 0x05, 0x01, /* Usage Page (Desktop), */ \ 0x09, 0x07, /* Usage (Keypad), */ \ 0xA1, 0x01, /* Collection (Application), */ \ - 0x85, 0xF7, /* Report ID (247), */ \ + 0x85, (_id), /* Report ID (_id), */ \ 0x14, /* Logical Minimum (0), */ \ 0x25, 0x01, /* Logical Maximum (1), */ \ 0x75, 0x01, /* Report Size (1), */ \ @@ -699,14 +700,14 @@ const size_t uclogic_rdesc_pen_v2_template_size = /* Fixed report descriptor for (tweaked) v1 buttonpad reports */ const __u8 uclogic_rdesc_buttonpad_v1_arr[] = { - UCLOGIC_RDESC_BUTTONPAD_BYTES(8) + UCLOGIC_RDESC_BUTTONPAD_BYTES(UCLOGIC_RDESC_BUTTONPAD_V1_ID, 8) }; const size_t uclogic_rdesc_buttonpad_v1_size = sizeof(uclogic_rdesc_buttonpad_v1_arr); /* Fixed report descriptor for (tweaked) v2 buttonpad reports */ const __u8 uclogic_rdesc_buttonpad_v2_arr[] = { - UCLOGIC_RDESC_BUTTONPAD_BYTES(12) + UCLOGIC_RDESC_BUTTONPAD_BYTES(UCLOGIC_RDESC_BUTTONPAD_V2_ID, 12) }; const size_t uclogic_rdesc_buttonpad_v2_size = sizeof(uclogic_rdesc_buttonpad_v2_arr); From 2e28f3e099f24bf976624baa1fe3a6ab90702406 Mon Sep 17 00:00:00 2001 From: Nikolai Kondrashov Date: Sat, 19 Feb 2022 11:01:54 +0100 Subject: [PATCH 13/16] HID: uclogic: Use "frame" instead of "buttonpad" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the term "frame" instead of "buttonpad" for consistency, in UC-Logic driver. Signed-off-by: Nikolai Kondrashov Signed-off-by: José Expósito Signed-off-by: Jiri Kosina --- drivers/hid/hid-uclogic-params.c | 46 +++++++++++++++----------------- drivers/hid/hid-uclogic-rdesc.c | 32 +++++++++++----------- drivers/hid/hid-uclogic-rdesc.h | 26 +++++++++--------- 3 files changed, 51 insertions(+), 53 deletions(-) diff --git a/drivers/hid/hid-uclogic-params.c b/drivers/hid/hid-uclogic-params.c index a4a53ab1e72c..168749d9a112 100644 --- a/drivers/hid/hid-uclogic-params.c +++ b/drivers/hid/hid-uclogic-params.c @@ -431,8 +431,8 @@ static int uclogic_params_frame_init_with_desc( } /** - * uclogic_params_frame_init_v1_buttonpad() - initialize abstract buttonpad - * on a v1 tablet interface. + * uclogic_params_frame_init_v1() - initialize v1 tablet interface frame + * controls. * * @frame: Pointer to the frame parameters to initialize (to be cleaned * up with uclogic_params_frame_cleanup()). Not modified in case @@ -446,8 +446,7 @@ static int uclogic_params_frame_init_with_desc( * Returns: * Zero, if successful. A negative errno code on error. */ -static int uclogic_params_frame_init_v1_buttonpad( - struct uclogic_params_frame *frame, +static int uclogic_params_frame_init_v1(struct uclogic_params_frame *frame, bool *pfound, struct hid_device *hdev) { @@ -488,9 +487,9 @@ static int uclogic_params_frame_init_v1_buttonpad( hid_dbg(hdev, "generic buttons enabled\n"); rc = uclogic_params_frame_init_with_desc( frame, - uclogic_rdesc_buttonpad_v1_arr, - uclogic_rdesc_buttonpad_v1_size, - UCLOGIC_RDESC_BUTTONPAD_V1_ID); + uclogic_rdesc_frame_v1_arr, + uclogic_rdesc_frame_v1_size, + UCLOGIC_RDESC_FRAME_V1_ID); if (rc != 0) goto cleanup; found = true; @@ -750,22 +749,22 @@ static int uclogic_params_huion_init(struct uclogic_params *params, goto cleanup; } else if (found) { hid_dbg(hdev, "pen v2 parameters found\n"); - /* Create v2 buttonpad parameters */ + /* Create v2 frame parameters */ rc = uclogic_params_frame_init_with_desc( &p.frame, - uclogic_rdesc_buttonpad_v2_arr, - uclogic_rdesc_buttonpad_v2_size, - UCLOGIC_RDESC_BUTTONPAD_V2_ID); + uclogic_rdesc_frame_v2_arr, + uclogic_rdesc_frame_v2_size, + UCLOGIC_RDESC_FRAME_V2_ID); if (rc != 0) { hid_err(hdev, - "failed creating v2 buttonpad parameters: %d\n", + "failed creating v2 frame parameters: %d\n", rc); goto cleanup; } /* Link frame button subreports from pen reports */ p.pen.subreport_list[0].value = 0xe0; p.pen.subreport_list[0].id = - UCLOGIC_RDESC_BUTTONPAD_V2_ID; + UCLOGIC_RDESC_FRAME_V2_ID; goto output; } hid_dbg(hdev, "pen v2 parameters not found\n"); @@ -779,21 +778,20 @@ static int uclogic_params_huion_init(struct uclogic_params *params, goto cleanup; } else if (found) { hid_dbg(hdev, "pen v1 parameters found\n"); - /* Try to probe v1 buttonpad */ - rc = uclogic_params_frame_init_v1_buttonpad( - &p.frame, - &found, hdev); + /* Try to probe v1 frame */ + rc = uclogic_params_frame_init_v1(&p.frame, + &found, hdev); if (rc != 0) { - hid_err(hdev, "v1 buttonpad probing failed: %d\n", rc); + hid_err(hdev, "v1 frame probing failed: %d\n", rc); goto cleanup; } - hid_dbg(hdev, "buttonpad v1 parameters%s found\n", + hid_dbg(hdev, "frame v1 parameters%s found\n", (found ? "" : " not")); if (found) { /* Link frame button subreports from pen reports */ p.pen.subreport_list[0].value = 0xe0; p.pen.subreport_list[0].id = - UCLOGIC_RDESC_BUTTONPAD_V1_ID; + UCLOGIC_RDESC_FRAME_V1_ID; } goto output; } @@ -1067,7 +1065,7 @@ int uclogic_params_init(struct uclogic_params *params, UCLOGIC_RDESC_UGEE_G5_FRAME_ID); if (rc != 0) { hid_err(hdev, - "failed creating buttonpad parameters: %d\n", + "failed creating frame parameters: %d\n", rc); goto cleanup; } @@ -1096,12 +1094,12 @@ int uclogic_params_init(struct uclogic_params *params, } else if (found) { rc = uclogic_params_frame_init_with_desc( &p.frame, - uclogic_rdesc_ugee_ex07_buttonpad_arr, - uclogic_rdesc_ugee_ex07_buttonpad_size, + uclogic_rdesc_ugee_ex07_frame_arr, + uclogic_rdesc_ugee_ex07_frame_size, 0); if (rc != 0) { hid_err(hdev, - "failed creating buttonpad parameters: %d\n", + "failed creating frame parameters: %d\n", rc); goto cleanup; } diff --git a/drivers/hid/hid-uclogic-rdesc.c b/drivers/hid/hid-uclogic-rdesc.c index 66aa83f67ccc..e8dedede3395 100644 --- a/drivers/hid/hid-uclogic-rdesc.c +++ b/drivers/hid/hid-uclogic-rdesc.c @@ -652,12 +652,12 @@ const size_t uclogic_rdesc_pen_v2_template_size = sizeof(uclogic_rdesc_pen_v2_template_arr); /* - * Expand to the contents of a generic buttonpad report descriptor. + * Expand to the contents of a generic frame report descriptor. * * @_id: The report ID to use. * @_size: Size of the report to pad to, including report ID, bytes. */ -#define UCLOGIC_RDESC_BUTTONPAD_BYTES(_id, _size) \ +#define UCLOGIC_RDESC_FRAME_BYTES(_id, _size) \ 0x05, 0x01, /* Usage Page (Desktop), */ \ 0x09, 0x07, /* Usage (Keypad), */ \ 0xA1, 0x01, /* Collection (Application), */ \ @@ -698,22 +698,22 @@ const size_t uclogic_rdesc_pen_v2_template_size = 0xC0, /* End Collection, */ \ 0xC0 /* End Collection */ -/* Fixed report descriptor for (tweaked) v1 buttonpad reports */ -const __u8 uclogic_rdesc_buttonpad_v1_arr[] = { - UCLOGIC_RDESC_BUTTONPAD_BYTES(UCLOGIC_RDESC_BUTTONPAD_V1_ID, 8) +/* Fixed report descriptor for (tweaked) v1 frame reports */ +const __u8 uclogic_rdesc_frame_v1_arr[] = { + UCLOGIC_RDESC_FRAME_BYTES(UCLOGIC_RDESC_FRAME_V1_ID, 8) }; -const size_t uclogic_rdesc_buttonpad_v1_size = - sizeof(uclogic_rdesc_buttonpad_v1_arr); +const size_t uclogic_rdesc_frame_v1_size = + sizeof(uclogic_rdesc_frame_v1_arr); -/* Fixed report descriptor for (tweaked) v2 buttonpad reports */ -const __u8 uclogic_rdesc_buttonpad_v2_arr[] = { - UCLOGIC_RDESC_BUTTONPAD_BYTES(UCLOGIC_RDESC_BUTTONPAD_V2_ID, 12) +/* Fixed report descriptor for (tweaked) v2 frame reports */ +const __u8 uclogic_rdesc_frame_v2_arr[] = { + UCLOGIC_RDESC_FRAME_BYTES(UCLOGIC_RDESC_FRAME_V2_ID, 12) }; -const size_t uclogic_rdesc_buttonpad_v2_size = - sizeof(uclogic_rdesc_buttonpad_v2_arr); +const size_t uclogic_rdesc_frame_v2_size = + sizeof(uclogic_rdesc_frame_v2_arr); -/* Fixed report descriptor for Ugee EX07 buttonpad */ -const __u8 uclogic_rdesc_ugee_ex07_buttonpad_arr[] = { +/* Fixed report descriptor for Ugee EX07 frame */ +const __u8 uclogic_rdesc_ugee_ex07_frame_arr[] = { 0x05, 0x01, /* Usage Page (Desktop), */ 0x09, 0x07, /* Usage (Keypad), */ 0xA1, 0x01, /* Collection (Application), */ @@ -736,8 +736,8 @@ const __u8 uclogic_rdesc_ugee_ex07_buttonpad_arr[] = { 0xC0, /* End Collection, */ 0xC0 /* End Collection */ }; -const size_t uclogic_rdesc_ugee_ex07_buttonpad_size = - sizeof(uclogic_rdesc_ugee_ex07_buttonpad_arr); +const size_t uclogic_rdesc_ugee_ex07_frame_size = + sizeof(uclogic_rdesc_ugee_ex07_frame_arr); /* Fixed report descriptor for Ugee G5 frame controls */ const __u8 uclogic_rdesc_ugee_g5_frame_arr[] = { diff --git a/drivers/hid/hid-uclogic-rdesc.h b/drivers/hid/hid-uclogic-rdesc.h index c5da51055af3..40c6f02c6bab 100644 --- a/drivers/hid/hid-uclogic-rdesc.h +++ b/drivers/hid/hid-uclogic-rdesc.h @@ -117,23 +117,23 @@ extern const size_t uclogic_rdesc_pen_v1_template_size; extern const __u8 uclogic_rdesc_pen_v2_template_arr[]; extern const size_t uclogic_rdesc_pen_v2_template_size; -/* Fixed report descriptor for (tweaked) v1 buttonpad reports */ -extern const __u8 uclogic_rdesc_buttonpad_v1_arr[]; -extern const size_t uclogic_rdesc_buttonpad_v1_size; +/* Fixed report descriptor for (tweaked) v1 frame reports */ +extern const __u8 uclogic_rdesc_frame_v1_arr[]; +extern const size_t uclogic_rdesc_frame_v1_size; -/* Report ID for tweaked v1 buttonpad reports */ -#define UCLOGIC_RDESC_BUTTONPAD_V1_ID 0xf7 +/* Report ID for tweaked v1 frame reports */ +#define UCLOGIC_RDESC_FRAME_V1_ID 0xf7 -/* Fixed report descriptor for (tweaked) v2 buttonpad reports */ -extern const __u8 uclogic_rdesc_buttonpad_v2_arr[]; -extern const size_t uclogic_rdesc_buttonpad_v2_size; +/* Fixed report descriptor for (tweaked) v2 frame reports */ +extern const __u8 uclogic_rdesc_frame_v2_arr[]; +extern const size_t uclogic_rdesc_frame_v2_size; -/* Report ID for tweaked v2 buttonpad reports */ -#define UCLOGIC_RDESC_BUTTONPAD_V2_ID 0xf7 +/* Report ID for tweaked v2 frame reports */ +#define UCLOGIC_RDESC_FRAME_V2_ID 0xf7 -/* Fixed report descriptor for Ugee EX07 buttonpad */ -extern const __u8 uclogic_rdesc_ugee_ex07_buttonpad_arr[]; -extern const size_t uclogic_rdesc_ugee_ex07_buttonpad_size; +/* Fixed report descriptor for Ugee EX07 frame */ +extern const __u8 uclogic_rdesc_ugee_ex07_frame_arr[]; +extern const size_t uclogic_rdesc_ugee_ex07_frame_size; /* Fixed report descriptor for XP-Pen Deco 01 frame controls */ extern const __u8 uclogic_rdesc_xppen_deco01_frame_arr[]; From a985de58186fc37992bbebc386ced8d7d25aa400 Mon Sep 17 00:00:00 2001 From: Nikolai Kondrashov Date: Sat, 19 Feb 2022 11:01:55 +0100 Subject: [PATCH 14/16] HID: uclogic: Put version first in rdesc namespace MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Put general hardware version before everything else in uclogic_rdesc_ namespace. Signed-off-by: Nikolai Kondrashov Signed-off-by: José Expósito Signed-off-by: Jiri Kosina --- drivers/hid/hid-uclogic-params.c | 32 ++++++++++++++++---------------- drivers/hid/hid-uclogic-rdesc.c | 28 ++++++++++++++-------------- drivers/hid/hid-uclogic-rdesc.h | 24 ++++++++++++------------ 3 files changed, 42 insertions(+), 42 deletions(-) diff --git a/drivers/hid/hid-uclogic-params.c b/drivers/hid/hid-uclogic-params.c index 168749d9a112..f667347ad0df 100644 --- a/drivers/hid/hid-uclogic-params.c +++ b/drivers/hid/hid-uclogic-params.c @@ -207,8 +207,8 @@ static int uclogic_params_pen_init_v1(struct uclogic_params_pen *pen, * Generate pen report descriptor */ desc_ptr = uclogic_rdesc_template_apply( - uclogic_rdesc_pen_v1_template_arr, - uclogic_rdesc_pen_v1_template_size, + uclogic_rdesc_v1_pen_template_arr, + uclogic_rdesc_v1_pen_template_size, desc_params, ARRAY_SIZE(desc_params)); if (desc_ptr == NULL) { rc = -ENOMEM; @@ -221,8 +221,8 @@ static int uclogic_params_pen_init_v1(struct uclogic_params_pen *pen, memset(pen, 0, sizeof(*pen)); pen->desc_ptr = desc_ptr; desc_ptr = NULL; - pen->desc_size = uclogic_rdesc_pen_v1_template_size; - pen->id = UCLOGIC_RDESC_PEN_V1_ID; + pen->desc_size = uclogic_rdesc_v1_pen_template_size; + pen->id = UCLOGIC_RDESC_V1_PEN_ID; pen->inrange = UCLOGIC_PARAMS_PEN_INRANGE_INVERTED; found = true; finish: @@ -351,8 +351,8 @@ static int uclogic_params_pen_init_v2(struct uclogic_params_pen *pen, * Generate pen report descriptor */ desc_ptr = uclogic_rdesc_template_apply( - uclogic_rdesc_pen_v2_template_arr, - uclogic_rdesc_pen_v2_template_size, + uclogic_rdesc_v2_pen_template_arr, + uclogic_rdesc_v2_pen_template_size, desc_params, ARRAY_SIZE(desc_params)); if (desc_ptr == NULL) { rc = -ENOMEM; @@ -365,8 +365,8 @@ static int uclogic_params_pen_init_v2(struct uclogic_params_pen *pen, memset(pen, 0, sizeof(*pen)); pen->desc_ptr = desc_ptr; desc_ptr = NULL; - pen->desc_size = uclogic_rdesc_pen_v2_template_size; - pen->id = UCLOGIC_RDESC_PEN_V2_ID; + pen->desc_size = uclogic_rdesc_v2_pen_template_size; + pen->id = UCLOGIC_RDESC_V2_PEN_ID; pen->inrange = UCLOGIC_PARAMS_PEN_INRANGE_NONE; pen->fragmented_hires = true; pen->tilt_y_flipped = true; @@ -487,9 +487,9 @@ static int uclogic_params_frame_init_v1(struct uclogic_params_frame *frame, hid_dbg(hdev, "generic buttons enabled\n"); rc = uclogic_params_frame_init_with_desc( frame, - uclogic_rdesc_frame_v1_arr, - uclogic_rdesc_frame_v1_size, - UCLOGIC_RDESC_FRAME_V1_ID); + uclogic_rdesc_v1_frame_arr, + uclogic_rdesc_v1_frame_size, + UCLOGIC_RDESC_V1_FRAME_ID); if (rc != 0) goto cleanup; found = true; @@ -752,9 +752,9 @@ static int uclogic_params_huion_init(struct uclogic_params *params, /* Create v2 frame parameters */ rc = uclogic_params_frame_init_with_desc( &p.frame, - uclogic_rdesc_frame_v2_arr, - uclogic_rdesc_frame_v2_size, - UCLOGIC_RDESC_FRAME_V2_ID); + uclogic_rdesc_v2_frame_arr, + uclogic_rdesc_v2_frame_size, + UCLOGIC_RDESC_V2_FRAME_ID); if (rc != 0) { hid_err(hdev, "failed creating v2 frame parameters: %d\n", @@ -764,7 +764,7 @@ static int uclogic_params_huion_init(struct uclogic_params *params, /* Link frame button subreports from pen reports */ p.pen.subreport_list[0].value = 0xe0; p.pen.subreport_list[0].id = - UCLOGIC_RDESC_FRAME_V2_ID; + UCLOGIC_RDESC_V2_FRAME_ID; goto output; } hid_dbg(hdev, "pen v2 parameters not found\n"); @@ -791,7 +791,7 @@ static int uclogic_params_huion_init(struct uclogic_params *params, /* Link frame button subreports from pen reports */ p.pen.subreport_list[0].value = 0xe0; p.pen.subreport_list[0].id = - UCLOGIC_RDESC_FRAME_V1_ID; + UCLOGIC_RDESC_V1_FRAME_ID; } goto output; } diff --git a/drivers/hid/hid-uclogic-rdesc.c b/drivers/hid/hid-uclogic-rdesc.c index e8dedede3395..04644d93bd11 100644 --- a/drivers/hid/hid-uclogic-rdesc.c +++ b/drivers/hid/hid-uclogic-rdesc.c @@ -532,7 +532,7 @@ const size_t uclogic_rdesc_twha60_fixed1_size = sizeof(uclogic_rdesc_twha60_fixed1_arr); /* Fixed report descriptor template for (tweaked) v1 pen reports */ -const __u8 uclogic_rdesc_pen_v1_template_arr[] = { +const __u8 uclogic_rdesc_v1_pen_template_arr[] = { 0x05, 0x0D, /* Usage Page (Digitizer), */ 0x09, 0x02, /* Usage (Pen), */ 0xA1, 0x01, /* Collection (Application), */ @@ -582,11 +582,11 @@ const __u8 uclogic_rdesc_pen_v1_template_arr[] = { 0xC0 /* End Collection */ }; -const size_t uclogic_rdesc_pen_v1_template_size = - sizeof(uclogic_rdesc_pen_v1_template_arr); +const size_t uclogic_rdesc_v1_pen_template_size = + sizeof(uclogic_rdesc_v1_pen_template_arr); /* Fixed report descriptor template for (tweaked) v2 pen reports */ -const __u8 uclogic_rdesc_pen_v2_template_arr[] = { +const __u8 uclogic_rdesc_v2_pen_template_arr[] = { 0x05, 0x0D, /* Usage Page (Digitizer), */ 0x09, 0x02, /* Usage (Pen), */ 0xA1, 0x01, /* Collection (Application), */ @@ -648,8 +648,8 @@ const __u8 uclogic_rdesc_pen_v2_template_arr[] = { 0xC0 /* End Collection */ }; -const size_t uclogic_rdesc_pen_v2_template_size = - sizeof(uclogic_rdesc_pen_v2_template_arr); +const size_t uclogic_rdesc_v2_pen_template_size = + sizeof(uclogic_rdesc_v2_pen_template_arr); /* * Expand to the contents of a generic frame report descriptor. @@ -699,18 +699,18 @@ const size_t uclogic_rdesc_pen_v2_template_size = 0xC0 /* End Collection */ /* Fixed report descriptor for (tweaked) v1 frame reports */ -const __u8 uclogic_rdesc_frame_v1_arr[] = { - UCLOGIC_RDESC_FRAME_BYTES(UCLOGIC_RDESC_FRAME_V1_ID, 8) +const __u8 uclogic_rdesc_v1_frame_arr[] = { + UCLOGIC_RDESC_FRAME_BYTES(UCLOGIC_RDESC_V1_FRAME_ID, 8) }; -const size_t uclogic_rdesc_frame_v1_size = - sizeof(uclogic_rdesc_frame_v1_arr); +const size_t uclogic_rdesc_v1_frame_size = + sizeof(uclogic_rdesc_v1_frame_arr); /* Fixed report descriptor for (tweaked) v2 frame reports */ -const __u8 uclogic_rdesc_frame_v2_arr[] = { - UCLOGIC_RDESC_FRAME_BYTES(UCLOGIC_RDESC_FRAME_V2_ID, 12) +const __u8 uclogic_rdesc_v2_frame_arr[] = { + UCLOGIC_RDESC_FRAME_BYTES(UCLOGIC_RDESC_V2_FRAME_ID, 12) }; -const size_t uclogic_rdesc_frame_v2_size = - sizeof(uclogic_rdesc_frame_v2_arr); +const size_t uclogic_rdesc_v2_frame_size = + sizeof(uclogic_rdesc_v2_frame_arr); /* Fixed report descriptor for Ugee EX07 frame */ const __u8 uclogic_rdesc_ugee_ex07_frame_arr[] = { diff --git a/drivers/hid/hid-uclogic-rdesc.h b/drivers/hid/hid-uclogic-rdesc.h index 40c6f02c6bab..d1ab1f346f22 100644 --- a/drivers/hid/hid-uclogic-rdesc.h +++ b/drivers/hid/hid-uclogic-rdesc.h @@ -104,32 +104,32 @@ enum uclogic_rdesc_pen_ph_id { UCLOGIC_RDESC_PH_HEAD, UCLOGIC_RDESC_PEN_PH_ID_##_ID /* Report ID for v1 pen reports */ -#define UCLOGIC_RDESC_PEN_V1_ID 0x07 +#define UCLOGIC_RDESC_V1_PEN_ID 0x07 /* Fixed report descriptor template for (tweaked) v1 pen reports */ -extern const __u8 uclogic_rdesc_pen_v1_template_arr[]; -extern const size_t uclogic_rdesc_pen_v1_template_size; +extern const __u8 uclogic_rdesc_v1_pen_template_arr[]; +extern const size_t uclogic_rdesc_v1_pen_template_size; /* Report ID for v2 pen reports */ -#define UCLOGIC_RDESC_PEN_V2_ID 0x08 +#define UCLOGIC_RDESC_V2_PEN_ID 0x08 /* Fixed report descriptor template for (tweaked) v2 pen reports */ -extern const __u8 uclogic_rdesc_pen_v2_template_arr[]; -extern const size_t uclogic_rdesc_pen_v2_template_size; +extern const __u8 uclogic_rdesc_v2_pen_template_arr[]; +extern const size_t uclogic_rdesc_v2_pen_template_size; /* Fixed report descriptor for (tweaked) v1 frame reports */ -extern const __u8 uclogic_rdesc_frame_v1_arr[]; -extern const size_t uclogic_rdesc_frame_v1_size; +extern const __u8 uclogic_rdesc_v1_frame_arr[]; +extern const size_t uclogic_rdesc_v1_frame_size; /* Report ID for tweaked v1 frame reports */ -#define UCLOGIC_RDESC_FRAME_V1_ID 0xf7 +#define UCLOGIC_RDESC_V1_FRAME_ID 0xf7 /* Fixed report descriptor for (tweaked) v2 frame reports */ -extern const __u8 uclogic_rdesc_frame_v2_arr[]; -extern const size_t uclogic_rdesc_frame_v2_size; +extern const __u8 uclogic_rdesc_v2_frame_arr[]; +extern const size_t uclogic_rdesc_v2_frame_size; /* Report ID for tweaked v2 frame reports */ -#define UCLOGIC_RDESC_FRAME_V2_ID 0xf7 +#define UCLOGIC_RDESC_V2_FRAME_ID 0xf7 /* Fixed report descriptor for Ugee EX07 frame */ extern const __u8 uclogic_rdesc_ugee_ex07_frame_arr[]; From 2daaeff3824dfb27409f499a2a945970729ba86f Mon Sep 17 00:00:00 2001 From: Nikolai Kondrashov Date: Sat, 19 Feb 2022 11:01:56 +0100 Subject: [PATCH 15/16] HID: uclogic: Define report IDs before their descriptors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Nikolai Kondrashov Signed-off-by: José Expósito Signed-off-by: Jiri Kosina --- drivers/hid/hid-uclogic-rdesc.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/hid/hid-uclogic-rdesc.h b/drivers/hid/hid-uclogic-rdesc.h index d1ab1f346f22..3d904c27b86a 100644 --- a/drivers/hid/hid-uclogic-rdesc.h +++ b/drivers/hid/hid-uclogic-rdesc.h @@ -117,20 +117,20 @@ extern const size_t uclogic_rdesc_v1_pen_template_size; extern const __u8 uclogic_rdesc_v2_pen_template_arr[]; extern const size_t uclogic_rdesc_v2_pen_template_size; +/* Report ID for tweaked v1 frame reports */ +#define UCLOGIC_RDESC_V1_FRAME_ID 0xf7 + /* Fixed report descriptor for (tweaked) v1 frame reports */ extern const __u8 uclogic_rdesc_v1_frame_arr[]; extern const size_t uclogic_rdesc_v1_frame_size; -/* Report ID for tweaked v1 frame reports */ -#define UCLOGIC_RDESC_V1_FRAME_ID 0xf7 +/* Report ID for tweaked v2 frame reports */ +#define UCLOGIC_RDESC_V2_FRAME_ID 0xf7 /* Fixed report descriptor for (tweaked) v2 frame reports */ extern const __u8 uclogic_rdesc_v2_frame_arr[]; extern const size_t uclogic_rdesc_v2_frame_size; -/* Report ID for tweaked v2 frame reports */ -#define UCLOGIC_RDESC_V2_FRAME_ID 0xf7 - /* Fixed report descriptor for Ugee EX07 frame */ extern const __u8 uclogic_rdesc_ugee_ex07_frame_arr[]; extern const size_t uclogic_rdesc_ugee_ex07_frame_size; From 337fa051d9b8aabf7081795d40e92e9d96f3442d Mon Sep 17 00:00:00 2001 From: Nikolai Kondrashov Date: Sat, 19 Feb 2022 11:01:57 +0100 Subject: [PATCH 16/16] HID: uclogic: Support multiple frame input devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for multiple frame input devices and their parameters to the UC-Logic driver. This prepares for creating a separate input device for Huion HS610 virtual touch ring reports. Signed-off-by: Nikolai Kondrashov Signed-off-by: José Expósito Signed-off-by: Jiri Kosina --- drivers/hid/hid-uclogic-core.c | 19 ++++-- drivers/hid/hid-uclogic-params.c | 102 +++++++++++++++---------------- drivers/hid/hid-uclogic-params.h | 26 ++++---- 3 files changed, 75 insertions(+), 72 deletions(-) diff --git a/drivers/hid/hid-uclogic-core.c b/drivers/hid/hid-uclogic-core.c index a02edeb30a35..05147f2d7564 100644 --- a/drivers/hid/hid-uclogic-core.c +++ b/drivers/hid/hid-uclogic-core.c @@ -296,17 +296,18 @@ static int uclogic_raw_event_pen(struct uclogic_drvdata *drvdata, * uclogic_raw_event_frame - handle raw frame events (frame HID reports). * * @drvdata: Driver data. + * @frame: The parameters of the frame controls to handle. * @data: Report data buffer, can be modified. * @size: Report data size, bytes. * * Returns: * Negative value on error (stops event delivery), zero for success. */ -static int uclogic_raw_event_frame(struct uclogic_drvdata *drvdata, - u8 *data, int size) +static int uclogic_raw_event_frame( + struct uclogic_drvdata *drvdata, + const struct uclogic_params_frame *frame, + u8 *data, int size) { - struct uclogic_params_frame *frame = &drvdata->params.frame; - WARN_ON(drvdata == NULL); WARN_ON(data == NULL && size != 0); @@ -352,6 +353,7 @@ static int uclogic_raw_event(struct hid_device *hdev, struct uclogic_params *params = &drvdata->params; struct uclogic_params_pen_subreport *subreport; struct uclogic_params_pen_subreport *subreport_list_end; + size_t i; /* Do not handle anything but input reports */ if (report->type != HID_INPUT_REPORT) @@ -382,8 +384,13 @@ static int uclogic_raw_event(struct hid_device *hdev, } /* Tweak frame control reports, if necessary */ - if (report_id == params->frame.id) - return uclogic_raw_event_frame(drvdata, data, size); + for (i = 0; i < ARRAY_SIZE(params->frame_list); i++) { + if (report_id == params->frame_list[i].id) { + return uclogic_raw_event_frame( + drvdata, ¶ms->frame_list[i], + data, size); + } + } break; } diff --git a/drivers/hid/hid-uclogic-params.c b/drivers/hid/hid-uclogic-params.c index f667347ad0df..5f50ceb875d6 100644 --- a/drivers/hid/hid-uclogic-params.c +++ b/drivers/hid/hid-uclogic-params.c @@ -512,9 +512,12 @@ cleanup: void uclogic_params_cleanup(struct uclogic_params *params) { if (!params->invalid) { + size_t i; kfree(params->desc_ptr); uclogic_params_pen_cleanup(¶ms->pen); - uclogic_params_frame_cleanup(¶ms->frame); + for (i = 0; i < ARRAY_SIZE(params->frame_list); i++) + uclogic_params_frame_cleanup(¶ms->frame_list[i]); + memset(params, 0, sizeof(*params)); } } @@ -542,60 +545,53 @@ int uclogic_params_get_desc(const struct uclogic_params *params, __u8 **pdesc, unsigned int *psize) { - bool common_present; - bool pen_present; - bool frame_present; - unsigned int size; + int rc = -ENOMEM; + bool present = false; + unsigned int size = 0; __u8 *desc = NULL; + size_t i; /* Check arguments */ if (params == NULL || pdesc == NULL || psize == NULL) return -EINVAL; - size = 0; + /* Concatenate descriptors */ +#define ADD_DESC(_desc_ptr, _desc_size) \ + do { \ + unsigned int new_size; \ + __u8 *new_desc; \ + if ((_desc_ptr) == NULL) { \ + break; \ + } \ + new_size = size + (_desc_size); \ + new_desc = krealloc(desc, new_size, GFP_KERNEL); \ + if (new_desc == NULL) { \ + goto cleanup; \ + } \ + memcpy(new_desc + size, (_desc_ptr), (_desc_size)); \ + desc = new_desc; \ + size = new_size; \ + present = true; \ + } while (0) - common_present = (params->desc_ptr != NULL); - pen_present = (params->pen.desc_ptr != NULL); - frame_present = (params->frame.desc_ptr != NULL); - - if (common_present) - size += params->desc_size; - if (pen_present) - size += params->pen.desc_size; - if (frame_present) - size += params->frame.desc_size; - - if (common_present || pen_present || frame_present) { - __u8 *p; - - desc = kmalloc(size, GFP_KERNEL); - if (desc == NULL) - return -ENOMEM; - p = desc; - - if (common_present) { - memcpy(p, params->desc_ptr, - params->desc_size); - p += params->desc_size; - } - if (pen_present) { - memcpy(p, params->pen.desc_ptr, - params->pen.desc_size); - p += params->pen.desc_size; - } - if (frame_present) { - memcpy(p, params->frame.desc_ptr, - params->frame.desc_size); - p += params->frame.desc_size; - } - - WARN_ON(p != desc + size); - - *psize = size; + ADD_DESC(params->desc_ptr, params->desc_size); + ADD_DESC(params->pen.desc_ptr, params->pen.desc_size); + for (i = 0; i < ARRAY_SIZE(params->frame_list); i++) { + ADD_DESC(params->frame_list[i].desc_ptr, + params->frame_list[i].desc_size); } - *pdesc = desc; - return 0; +#undef ADD_DESC + + if (present) { + *pdesc = desc; + *psize = size; + desc = NULL; + } + rc = 0; +cleanup: + kfree(desc); + return rc; } /** @@ -751,7 +747,7 @@ static int uclogic_params_huion_init(struct uclogic_params *params, hid_dbg(hdev, "pen v2 parameters found\n"); /* Create v2 frame parameters */ rc = uclogic_params_frame_init_with_desc( - &p.frame, + &p.frame_list[0], uclogic_rdesc_v2_frame_arr, uclogic_rdesc_v2_frame_size, UCLOGIC_RDESC_V2_FRAME_ID); @@ -779,7 +775,7 @@ static int uclogic_params_huion_init(struct uclogic_params *params, } else if (found) { hid_dbg(hdev, "pen v1 parameters found\n"); /* Try to probe v1 frame */ - rc = uclogic_params_frame_init_v1(&p.frame, + rc = uclogic_params_frame_init_v1(&p.frame_list[0], &found, hdev); if (rc != 0) { hid_err(hdev, "v1 frame probing failed: %d\n", rc); @@ -1033,7 +1029,7 @@ int uclogic_params_init(struct uclogic_params *params, } /* Initialize frame parameters */ rc = uclogic_params_frame_init_with_desc( - &p.frame, + &p.frame_list[0], uclogic_rdesc_xppen_deco01_frame_arr, uclogic_rdesc_xppen_deco01_frame_size, 0); @@ -1059,7 +1055,7 @@ int uclogic_params_init(struct uclogic_params *params, goto cleanup; } else if (found) { rc = uclogic_params_frame_init_with_desc( - &p.frame, + &p.frame_list[0], uclogic_rdesc_ugee_g5_frame_arr, uclogic_rdesc_ugee_g5_frame_size, UCLOGIC_RDESC_UGEE_G5_FRAME_ID); @@ -1069,9 +1065,9 @@ int uclogic_params_init(struct uclogic_params *params, rc); goto cleanup; } - p.frame.re_lsb = + p.frame_list[0].re_lsb = UCLOGIC_RDESC_UGEE_G5_FRAME_RE_LSB; - p.frame.dev_id_byte = + p.frame_list[0].dev_id_byte = UCLOGIC_RDESC_UGEE_G5_FRAME_DEV_ID_BYTE; } else { hid_warn(hdev, "pen parameters not found"); @@ -1093,7 +1089,7 @@ int uclogic_params_init(struct uclogic_params *params, goto cleanup; } else if (found) { rc = uclogic_params_frame_init_with_desc( - &p.frame, + &p.frame_list[0], uclogic_rdesc_ugee_ex07_frame_arr, uclogic_rdesc_ugee_ex07_frame_size, 0); diff --git a/drivers/hid/hid-uclogic-params.h b/drivers/hid/hid-uclogic-params.h index c18569591b75..86f616dfbb53 100644 --- a/drivers/hid/hid-uclogic-params.h +++ b/drivers/hid/hid-uclogic-params.h @@ -165,10 +165,10 @@ struct uclogic_params { */ struct uclogic_params_pen pen; /* - * Frame control parameters and optional report descriptor part. - * Only valid, if "invalid" is false. + * The list of frame control parameters and optional report descriptor + * parts. Only valid, if "invalid" is false. */ - struct uclogic_params_frame frame; + struct uclogic_params_frame frame_list[1]; }; /* Initialize a tablet interface and discover its parameters */ @@ -187,11 +187,11 @@ extern int uclogic_params_init(struct uclogic_params *params, ".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" + ".frame_list[0].desc_ptr = %p\n" \ + ".frame_list[0].desc_size = %u\n" \ + ".frame_list[0].id = %u\n" \ + ".frame_list[0].re_lsb = %u\n" \ + ".frame_list[0].dev_id_byte = %u\n" /* Tablet interface parameters *printf format arguments */ #define UCLOGIC_PARAMS_FMT_ARGS(_params) \ @@ -206,11 +206,11 @@ extern int uclogic_params_init(struct uclogic_params *params, uclogic_params_pen_inrange_to_str((_params)->pen.inrange), \ ((_params)->pen.fragmented_hires ? "true" : "false"), \ ((_params)->pen.tilt_y_flipped ? "true" : "false"), \ - (_params)->frame.desc_ptr, \ - (_params)->frame.desc_size, \ - (_params)->frame.id, \ - (_params)->frame.re_lsb, \ - (_params)->frame.dev_id_byte + (_params)->frame_list[0].desc_ptr, \ + (_params)->frame_list[0].desc_size, \ + (_params)->frame_list[0].id, \ + (_params)->frame_list[0].re_lsb, \ + (_params)->frame_list[0].dev_id_byte /* Get a replacement report descriptor for a tablet's interface. */ extern int uclogic_params_get_desc(const struct uclogic_params *params,