HID: uclogic: Add support for Ugee G5

Add support for Ugee G5 to hid-uclogic.

Signed-off-by: Nikolai Kondrashov <spbnick@gmail.com>
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index b38be58..895b79d 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -1144,6 +1144,7 @@
 #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_G540	0x0075
 #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_G640	0x0094
 #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01	0x0042
+#define USB_DEVICE_ID_UGEE_TABLET_G5		0x0074
 #define USB_DEVICE_ID_UGEE_TABLET_EX07S		0x0071
 
 #define USB_VENDOR_ID_UNITEC	0x227d
diff --git a/drivers/hid/hid-uclogic-core.c b/drivers/hid/hid-uclogic-core.c
index dfacb04..8fe02d8 100644
--- a/drivers/hid/hid-uclogic-core.c
+++ b/drivers/hid/hid-uclogic-core.c
@@ -384,6 +384,8 @@ static const struct hid_device_id uclogic_devices[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_UGTIZER,
 				USB_DEVICE_ID_UGTIZER_TABLET_GP0610) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_UGEE,
+				USB_DEVICE_ID_UGEE_TABLET_G5) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_UGEE,
 				USB_DEVICE_ID_UGEE_TABLET_EX07S) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_UGEE,
 				USB_DEVICE_ID_UGEE_XPPEN_TABLET_G540) },
diff --git a/drivers/hid/hid-uclogic-params.c b/drivers/hid/hid-uclogic-params.c
index 9b0fc4d..b582739 100644
--- a/drivers/hid/hid-uclogic-params.c
+++ b/drivers/hid/hid-uclogic-params.c
@@ -1042,6 +1042,40 @@ int uclogic_params_init(struct uclogic_params *params,
 		}
 		break;
 	case VID_PID(USB_VENDOR_ID_UGEE,
+		     USB_DEVICE_ID_UGEE_TABLET_G5):
+		/* Ignore non-pen interfaces */
+		if (bInterfaceNumber != 1) {
+			uclogic_params_init_invalid(&p);
+			break;
+		}
+
+		rc = uclogic_params_pen_init_v1(&p.pen, &found, hdev);
+		if (rc != 0) {
+			hid_err(hdev, "pen probing failed: %d\n", rc);
+			goto cleanup;
+		} else if (found) {
+			rc = uclogic_params_frame_init_with_desc(
+				&p.frame,
+				uclogic_rdesc_ugee_g5_frame_arr,
+				uclogic_rdesc_ugee_g5_frame_size,
+				UCLOGIC_RDESC_UGEE_G5_FRAME_ID);
+			if (rc != 0) {
+				hid_err(hdev,
+					"failed creating buttonpad parameters: %d\n",
+					rc);
+				goto cleanup;
+			}
+			p.frame.re_lsb =
+				UCLOGIC_RDESC_UGEE_G5_FRAME_RE_LSB;
+			p.frame.dev_id_byte =
+				UCLOGIC_RDESC_UGEE_G5_FRAME_DEV_ID_BYTE;
+		} else {
+			hid_warn(hdev, "pen parameters not found");
+			uclogic_params_init_invalid(&p);
+		}
+
+		break;
+	case VID_PID(USB_VENDOR_ID_UGEE,
 		     USB_DEVICE_ID_UGEE_TABLET_EX07S):
 		/* Ignore non-pen interfaces */
 		if (bInterfaceNumber != 1) {
diff --git a/drivers/hid/hid-uclogic-rdesc.c b/drivers/hid/hid-uclogic-rdesc.c
index 7399658..bf5da6d 100644
--- a/drivers/hid/hid-uclogic-rdesc.c
+++ b/drivers/hid/hid-uclogic-rdesc.c
@@ -728,6 +728,60 @@ const __u8 uclogic_rdesc_ugee_ex07_buttonpad_arr[] = {
 const size_t uclogic_rdesc_ugee_ex07_buttonpad_size =
 			sizeof(uclogic_rdesc_ugee_ex07_buttonpad_arr);
 
+/* Fixed report descriptor for Ugee G5 frame controls */
+const __u8 uclogic_rdesc_ugee_g5_frame_arr[] = {
+	0x05, 0x01,         /*  Usage Page (Desktop),               */
+	0x09, 0x07,         /*  Usage (Keypad),                     */
+	0xA1, 0x01,         /*  Collection (Application),           */
+	0x85, 0x06,         /*      Report ID (6),                  */
+	0x05, 0x0D,         /*      Usage Page (Digitizer),         */
+	0x09, 0x39,         /*      Usage (Tablet Function Keys),   */
+	0xA0,               /*      Collection (Physical),          */
+	0x14,               /*          Logical Minimum (0),        */
+	0x25, 0x01,         /*          Logical Maximum (1),        */
+	0x05, 0x01,         /*          Usage Page (Desktop),       */
+	0x05, 0x09,         /*          Usage Page (Button),        */
+	0x19, 0x01,         /*          Usage Minimum (01h),        */
+	0x29, 0x05,         /*          Usage Maximum (05h),        */
+	0x75, 0x01,         /*          Report Size (1),            */
+	0x95, 0x05,         /*          Report Count (5),           */
+	0x81, 0x02,         /*          Input (Variable),           */
+	0x75, 0x01,         /*          Report Size (1),            */
+	0x95, 0x03,         /*          Report Count (3),           */
+	0x81, 0x01,         /*          Input (Constant),           */
+	0x05, 0x0D,         /*          Usage Page (Digitizer),     */
+	0x0A, 0xFF, 0xFF,   /*          Usage (FFFFh),              */
+	0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
+	0x75, 0x08,         /*          Report Size (8),            */
+	0x95, 0x01,         /*          Report Count (1),           */
+	0x81, 0x02,         /*          Input (Variable),           */
+	0x25, 0x01,         /*          Logical Maximum (1),        */
+	0x09, 0x44,         /*          Usage (Barrel Switch),      */
+	0x75, 0x01,         /*          Report Size (1),            */
+	0x95, 0x01,         /*          Report Count (1),           */
+	0x81, 0x02,         /*          Input (Variable),           */
+	0x05, 0x01,         /*          Usage Page (Desktop),       */
+	0x09, 0x30,         /*          Usage (X),                  */
+	0x09, 0x31,         /*          Usage (Y),                  */
+	0x75, 0x01,         /*          Report Size (1),            */
+	0x95, 0x02,         /*          Report Count (2),           */
+	0x81, 0x02,         /*          Input (Variable),           */
+	0x75, 0x01,         /*          Report Size (1),            */
+	0x95, 0x0B,         /*          Report Count (11),          */
+	0x81, 0x01,         /*          Input (Constant),           */
+	0x05, 0x01,         /*          Usage Page (Desktop),       */
+	0x09, 0x38,         /*          Usage (Wheel),              */
+	0x15, 0xFF,         /*          Logical Minimum (-1),       */
+	0x25, 0x01,         /*          Logical Maximum (1),        */
+	0x75, 0x02,         /*          Report Size (2),            */
+	0x95, 0x01,         /*          Report Count (1),           */
+	0x81, 0x06,         /*          Input (Variable, Relative), */
+	0xC0,               /*      End Collection,                 */
+	0xC0                /*  End Collection                      */
+};
+const size_t uclogic_rdesc_ugee_g5_frame_size =
+			sizeof(uclogic_rdesc_ugee_g5_frame_arr);
+
 /* Fixed report descriptor for XP-Pen Deco 01 frame controls */
 const __u8 uclogic_rdesc_xppen_deco01_frame_arr[] = {
 	0x05, 0x01, /*  Usage Page (Desktop),               */
diff --git a/drivers/hid/hid-uclogic-rdesc.h b/drivers/hid/hid-uclogic-rdesc.h
index 0c5bd02..c5da510 100644
--- a/drivers/hid/hid-uclogic-rdesc.h
+++ b/drivers/hid/hid-uclogic-rdesc.h
@@ -139,4 +139,17 @@ extern const size_t uclogic_rdesc_ugee_ex07_buttonpad_size;
 extern const __u8 uclogic_rdesc_xppen_deco01_frame_arr[];
 extern const size_t uclogic_rdesc_xppen_deco01_frame_size;
 
+/* Fixed report descriptor for Ugee G5 frame controls */
+extern const __u8 uclogic_rdesc_ugee_g5_frame_arr[];
+extern const size_t uclogic_rdesc_ugee_g5_frame_size;
+
+/* Report ID of Ugee G5 frame control reports */
+#define UCLOGIC_RDESC_UGEE_G5_FRAME_ID 0x06
+
+/* Device ID byte offset in Ugee G5 frame report */
+#define UCLOGIC_RDESC_UGEE_G5_FRAME_DEV_ID_BYTE	0x2
+
+/* Least-significant bit of Ugee G5 frame rotary encoder state */
+#define UCLOGIC_RDESC_UGEE_G5_FRAME_RE_LSB 38
+
 #endif /* _HID_UCLOGIC_RDESC_H */