HID: waltop: add Media Tablet 14.1 inch support

Add support for Waltop Media Tablet 14.1 inch by fixing report descriptor.

This tablet is also sold as Genius G-Pen M712 (older version) and M712X
(newer version). Both are supported.

Trust Wide Screen Design Tablet (TB-7300, item no 15358) seems to be the
older version of this tablet (similar to Genius G-Pen M712), and could be
supported as well.

Signed-off-by: Nikolai Kondrashov <spbnick@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 7bd5365..d0240d5 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1390,6 +1390,7 @@
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ZYDACRON, USB_DEVICE_ID_ZYDACRON_REMOTE_CONTROL) },
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 5be6293..c6b2f7b 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -522,6 +522,7 @@
 #define USB_VENDOR_ID_WALTOP				0x172f
 #define USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH	0x0032
 #define USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH	0x0501
+#define USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH	0x0500
 
 #define USB_VENDOR_ID_WISEGROUP		0x0925
 #define USB_DEVICE_ID_SMARTJOY_PLUS	0x0005
diff --git a/drivers/hid/hid-waltop.c b/drivers/hid/hid-waltop.c
index b9d49e4..7d4b318 100644
--- a/drivers/hid/hid-waltop.c
+++ b/drivers/hid/hid-waltop.c
@@ -510,6 +510,295 @@
 	0xC0                /*  End Collection                      */
 };
 
+/*
+ * Original Media Tablet 14.1 inch report descriptor.
+ *
+ * There are at least two versions of this model in the wild. They are
+ * represented by Genius G-Pen M712 (older version) and Genius G-Pen M712X
+ * (newer version). The hardware difference between these versions is the same
+ * as between older and newer versions of Media Tablet 10.6 inch. The report
+ * descriptors are identical for both versions.
+ *
+ * The function, behavior and report descriptor of this tablet is similar to
+ * that of Media Tablet 10.6 inch. However, there is one more field (with
+ * Consumer AC Pan usage) in the mouse description. Then the tablet X and Y
+ * logical extents both get scaled to 0..16383 range (a hardware limit?),
+ * which kind of defeats the advertised 4000 LPI resolution, considering the
+ * physical extents of 12x7.25 inches. Plus, reports 5, 10 and 255 are used
+ * sometimes (while moving the pen) with unknown purpose. Also, the key codes
+ * generated for zoom in/out are different.
+ *
+ *  Usage Page (Desktop),
+ *  Usage (Mouse),
+ *  Collection (Application),
+ *    Report ID (1),
+ *    Usage (Pointer),
+ *    Collection (Physical),
+ *      Usage Page (Button),
+ *      Usage Minimum (01h),
+ *      Usage Maximum (05h),
+ *      Logical Minimum (0),
+ *      Logical Maximum (1),
+ *      Report Size (1),
+ *      Report Count (5),
+ *      Input (Variable),
+ *      Report Size (3),
+ *      Report Count (1),
+ *      Input (Constant, Variable),
+ *      Usage Page (Desktop),
+ *      Usage (X),
+ *      Usage (Y),
+ *      Usage (Wheel),
+ *      Logical Minimum (-127),
+ *      Logical Maximum (127),
+ *      Report Size (8),
+ *      Report Count (3),
+ *      Input (Variable, Relative),
+ *      Usage Page (Consumer),
+ *      Logical Minimum (-127),
+ *      Logical Maximum (127),
+ *      Report Size (8),
+ *      Report Count (1),
+ *      Usage (AC Pan),
+ *      Input (Variable, Relative),
+ *    End Collection,
+ *  End Collection,
+ *  Usage Page (Digitizer),
+ *  Usage (Pen),
+ *  Collection (Application),
+ *    Report ID (2),
+ *    Usage (Stylus),
+ *    Collection (Physical),
+ *      Usage (00h),
+ *      Logical Minimum (0),
+ *      Logical Maximum (255),
+ *      Report Size (8),
+ *      Report Count (7),
+ *      Input (Variable),
+ *      Usage (Azimuth),
+ *      Usage (Altitude),
+ *      Logical Minimum (0),
+ *      Logical Maximum (255),
+ *      Report Size (8),
+ *      Report Count (2),
+ *      Feature (Variable),
+ *    End Collection,
+ *    Report ID (5),
+ *    Usage Page (Digitizer),
+ *    Usage (Stylus),
+ *    Collection (Physical),
+ *      Usage (00h),
+ *      Logical Minimum (0),
+ *      Logical Maximum (255),
+ *      Report Size (8),
+ *      Report Count (7),
+ *      Input (Variable),
+ *    End Collection,
+ *    Report ID (10),
+ *    Usage Page (Digitizer),
+ *    Usage (Stylus),
+ *    Collection (Physical),
+ *      Usage (00h),
+ *      Logical Minimum (0),
+ *      Logical Maximum (255),
+ *      Report Size (8),
+ *      Report Count (7),
+ *      Input (Variable),
+ *    End Collection,
+ *    Report ID (16),
+ *    Usage (Stylus),
+ *    Collection (Physical),
+ *      Usage (Tip Switch),
+ *      Usage (Barrel Switch),
+ *      Usage (Invert),
+ *      Usage (Eraser),
+ *      Usage (In Range),
+ *      Logical Minimum (0),
+ *      Logical Maximum (1),
+ *      Report Size (1),
+ *      Report Count (5),
+ *      Input (Variable),
+ *      Report Count (3),
+ *      Input (Constant, Variable),
+ *      Usage Page (Desktop),
+ *      Usage (X),
+ *      Report Size (16),
+ *      Report Count (1),
+ *      Push,
+ *      Unit Exponent (13),
+ *      Unit (Inch^3),
+ *      Logical Minimum (0),
+ *      Logical Maximum (16383),
+ *      Physical Minimum (0),
+ *      Physical Maximum (16383),
+ *      Input (Variable),
+ *      Usage (Y),
+ *      Input (Variable),
+ *      Usage Page (Digitizer),
+ *      Usage (Tip Pressure),
+ *      Logical Minimum (0),
+ *      Logical Maximum (1023),
+ *      Physical Minimum (0),
+ *      Physical Maximum (1023),
+ *      Input (Variable),
+ *    End Collection,
+ *  End Collection,
+ *  Usage Page (Desktop),
+ *  Usage (Keyboard),
+ *  Collection (Application),
+ *    Report ID (13),
+ *    Usage Page (Keyboard),
+ *    Usage Minimum (KB Leftcontrol),
+ *    Usage Maximum (KB Right GUI),
+ *    Logical Minimum (0),
+ *    Logical Maximum (1),
+ *    Report Size (1),
+ *    Report Count (8),
+ *    Input (Variable),
+ *    Report Size (8),
+ *    Report Count (1),
+ *    Input (Constant),
+ *    Usage Page (Keyboard),
+ *    Usage Minimum (None),
+ *    Usage Maximum (KB Application),
+ *    Logical Minimum (0),
+ *    Logical Maximum (101),
+ *    Report Size (8),
+ *    Report Count (5),
+ *    Input,
+ *  End Collection,
+ *  Usage Page (Consumer),
+ *  Usage (Consumer Control),
+ *  Collection (Application),
+ *    Report ID (12),
+ *    Usage (Volume Inc),
+ *    Usage (Volume Dec),
+ *    Usage (Mute),
+ *    Logical Minimum (0),
+ *    Logical Maximum (1),
+ *    Report Size (1),
+ *    Report Count (3),
+ *    Input (Variable, Relative),
+ *    Report Size (5),
+ *    Report Count (1),
+ *    Input (Constant, Variable, Relative),
+ *  End Collection
+ */
+
+/* Size of the original report descriptor of Media Tablet 14.1 inch */
+#define MEDIA_TABLET_14_1_INCH_RDESC_ORIG_SIZE	309
+
+/*
+ * Fixed Media Tablet 14.1 inch descriptor.
+ * It is fixed similarly to the Media Tablet 10.6 inch descriptor.
+ */
+static __u8 media_tablet_14_1_inch_rdesc_fixed[] = {
+	0x05, 0x0D,         /*  Usage Page (Digitizer),             */
+	0x09, 0x02,         /*  Usage (Pen),                        */
+	0xA1, 0x01,         /*  Collection (Application),           */
+	0x85, 0x10,         /*      Report ID (16),                 */
+	0x09, 0x20,         /*      Usage (Stylus),                 */
+	0xA0,               /*      Collection (Physical),          */
+	0x09, 0x42,         /*          Usage (Tip Switch),         */
+	0x09, 0x44,         /*          Usage (Barrel Switch),      */
+	0x09, 0x46,         /*          Usage (Tablet Pick),        */
+	0x15, 0x01,         /*          Logical Minimum (1),        */
+	0x25, 0x03,         /*          Logical Maximum (3),        */
+	0x75, 0x04,         /*          Report Size (4),            */
+	0x95, 0x01,         /*          Report Count (1),           */
+	0x80,               /*          Input,                      */
+	0x75, 0x01,         /*          Report Size (1),            */
+	0x09, 0x32,         /*          Usage (In Range),           */
+	0x14,               /*          Logical Minimum (0),        */
+	0x25, 0x01,         /*          Logical Maximum (1),        */
+	0x95, 0x01,         /*          Report Count (1),           */
+	0x81, 0x02,         /*          Input (Variable),           */
+	0x95, 0x03,         /*          Report Count (3),           */
+	0x81, 0x03,         /*          Input (Constant, Variable), */
+	0x75, 0x10,         /*          Report Size (16),           */
+	0x95, 0x01,         /*          Report Count (1),           */
+	0x14,               /*          Logical Minimum (0),        */
+	0xA4,               /*          Push,                       */
+	0x05, 0x01,         /*          Usage Page (Desktop),       */
+	0x65, 0x13,         /*          Unit (Inch),                */
+	0x55, 0xFD,         /*          Unit Exponent (-3),         */
+	0x34,               /*          Physical Minimum (0),       */
+	0x09, 0x30,         /*          Usage (X),                  */
+	0x46, 0xE0, 0x2E,   /*          Physical Maximum (12000),   */
+	0x26, 0xFF, 0x3F,   /*          Logical Maximum (16383),    */
+	0x81, 0x02,         /*          Input (Variable),           */
+	0x09, 0x31,         /*          Usage (Y),                  */
+	0x46, 0x52, 0x1C,   /*          Physical Maximum (7250),    */
+	0x26, 0xFF, 0x3F,   /*          Logical Maximum (16383),    */
+	0x81, 0x02,         /*          Input (Variable),           */
+	0xB4,               /*          Pop,                        */
+	0x09, 0x30,         /*          Usage (Tip Pressure),       */
+	0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
+	0x81, 0x02,         /*          Input (Variable),           */
+	0xC0,               /*      End Collection,                 */
+	0xC0,               /*  End Collection,                     */
+	0x05, 0x01,         /*  Usage Page (Desktop),               */
+	0x09, 0x02,         /*  Usage (Mouse),                      */
+	0xA1, 0x01,         /*  Collection (Application),           */
+	0x85, 0x01,         /*      Report ID (1),                  */
+	0x09, 0x01,         /*      Usage (Pointer),                */
+	0xA0,               /*      Collection (Physical),          */
+	0x75, 0x08,         /*          Report Size (8),            */
+	0x95, 0x03,         /*          Report Count (3),           */
+	0x81, 0x03,         /*          Input (Constant, Variable), */
+	0x95, 0x02,         /*          Report Count (2),           */
+	0x15, 0xFF,         /*          Logical Minimum (-1),       */
+	0x25, 0x01,         /*          Logical Maximum (1),        */
+	0x09, 0x38,         /*          Usage (Wheel),              */
+	0x0B, 0x38, 0x02,   /*          Usage (Consumer AC Pan),    */
+		0x0C, 0x00,
+	0x81, 0x06,         /*          Input (Variable, Relative), */
+	0xC0,               /*      End Collection,                 */
+	0xC0,               /*  End Collection,                     */
+	0x05, 0x0C,         /*  Usage Page (Consumer),              */
+	0x09, 0x01,         /*  Usage (Consumer Control),           */
+	0xA1, 0x01,         /*  Collection (Application),           */
+	0x85, 0x0D,         /*      Report ID (13),                 */
+	0x95, 0x01,         /*      Report Count (1),               */
+	0x75, 0x10,         /*      Report Size (16),               */
+	0x81, 0x03,         /*      Input (Constant, Variable),     */
+	0x0A, 0x2F, 0x02,   /*      Usage (AC Zoom),                */
+	0x0A, 0x2E, 0x02,   /*      Usage (AC Zoom Out),            */
+	0x0A, 0x2D, 0x02,   /*      Usage (AC Zoom In),             */
+	0x09, 0xB6,         /*      Usage (Scan Previous Track),    */
+	0x09, 0xB5,         /*      Usage (Scan Next Track),        */
+	0x08,               /*      Usage (00h),                    */
+	0x08,               /*      Usage (00h),                    */
+	0x08,               /*      Usage (00h),                    */
+	0x08,               /*      Usage (00h),                    */
+	0x08,               /*      Usage (00h),                    */
+	0x0A, 0x2E, 0x02,   /*      Usage (AC Zoom Out),            */
+	0x0A, 0x2D, 0x02,   /*      Usage (AC Zoom In),             */
+	0x15, 0x0C,         /*      Logical Minimum (12),           */
+	0x25, 0x17,         /*      Logical Maximum (23),           */
+	0x75, 0x05,         /*      Report Size (5),                */
+	0x80,               /*      Input,                          */
+	0x75, 0x03,         /*      Report Size (3),                */
+	0x81, 0x03,         /*      Input (Constant, Variable),     */
+	0x75, 0x20,         /*      Report Size (32),               */
+	0x81, 0x03,         /*      Input (Constant, Variable),     */
+	0xC0,               /*  End Collection,                     */
+	0x09, 0x01,         /*  Usage (Consumer Control),           */
+	0xA1, 0x01,         /*  Collection (Application),           */
+	0x85, 0x0C,         /*      Report ID (12),                 */
+	0x75, 0x01,         /*      Report Size (1),                */
+	0x09, 0xE9,         /*      Usage (Volume Inc),             */
+	0x09, 0xEA,         /*      Usage (Volume Dec),             */
+	0x09, 0xE2,         /*      Usage (Mute),                   */
+	0x14,               /*      Logical Minimum (0),            */
+	0x25, 0x01,         /*      Logical Maximum (1),            */
+	0x95, 0x03,         /*      Report Count (3),               */
+	0x81, 0x06,         /*      Input (Variable, Relative),     */
+	0x75, 0x05,         /*      Report Size (5),                */
+	0x81, 0x03,         /*      Input (Constant, Variable),     */
+	0xC0                /*  End Collection                      */
+};
+
 static __u8 *waltop_report_fixup(struct hid_device *hdev, __u8 *rdesc,
 		unsigned int *rsize)
 {
@@ -526,6 +815,12 @@
 			*rsize = sizeof(media_tablet_10_6_inch_rdesc_fixed);
 		}
 		break;
+	case USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH:
+		if (*rsize == MEDIA_TABLET_14_1_INCH_RDESC_ORIG_SIZE) {
+			rdesc = media_tablet_14_1_inch_rdesc_fixed;
+			*rsize = sizeof(media_tablet_14_1_inch_rdesc_fixed);
+		}
+		break;
 	}
 	return rdesc;
 }
@@ -535,6 +830,8 @@
 				USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP,
 				USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP,
+				USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH) },
 	{ }
 };
 MODULE_DEVICE_TABLE(hid, waltop_devices);
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index 1b45fb7..9cc3dd1 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -71,6 +71,7 @@
 	{ USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U, HID_QUIRK_MULTI_INPUT },
 	{ USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U, HID_QUIRK_MULTI_INPUT },
 	{ USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH, HID_QUIRK_MULTI_INPUT },
+	{ USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH, HID_QUIRK_MULTI_INPUT },
 	{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS },
 	{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },