cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

hid-waltop.c (39539B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 *  HID driver for Waltop devices not fully compliant with HID standard
      4 *
      5 *  Copyright (c) 2010 Nikolai Kondrashov
      6 */
      7
      8/*
      9 */
     10
     11#include <linux/device.h>
     12#include <linux/hid.h>
     13#include <linux/module.h>
     14
     15#include "hid-ids.h"
     16
     17/*
     18 * There exists an official driver on the manufacturer's website, which
     19 * wasn't submitted to the kernel, for some reason. The official driver
     20 * doesn't seem to support extra features of some tablets, like wheels.
     21 *
     22 * It shows that the feature report ID 2 could be used to control any waltop
     23 * tablet input mode, switching it between "default", "tablet" and "ink".
     24 *
     25 * This driver only uses "default" mode for all the supported tablets. This
     26 * mode tries to be HID-compatible (not very successfully), but cripples the
     27 * resolution of some tablets.
     28 *
     29 * The "tablet" mode uses some proprietary, yet decipherable protocol, which
     30 * represents the correct resolution, but is possibly HID-incompatible (i.e.
     31 * indescribable by a report descriptor).
     32 *
     33 * The purpose of the "ink" mode is unknown.
     34 *
     35 * The feature reports needed for switching to each mode are these:
     36 *
     37 * 02 16 00     default
     38 * 02 16 01     tablet
     39 * 02 16 02     ink
     40 */
     41
     42/* Size of the original report descriptor of Slim Tablet 5.8 inch */
     43#define SLIM_TABLET_5_8_INCH_RDESC_ORIG_SIZE	222
     44
     45/* Fixed Slim Tablet 5.8 inch descriptor */
     46static __u8 slim_tablet_5_8_inch_rdesc_fixed[] = {
     47	0x05, 0x0D,         /*  Usage Page (Digitizer),             */
     48	0x09, 0x02,         /*  Usage (Pen),                        */
     49	0xA1, 0x01,         /*  Collection (Application),           */
     50	0x85, 0x10,         /*      Report ID (16),                 */
     51	0x09, 0x20,         /*      Usage (Stylus),                 */
     52	0xA0,               /*      Collection (Physical),          */
     53	0x09, 0x42,         /*          Usage (Tip Switch),         */
     54	0x09, 0x44,         /*          Usage (Barrel Switch),      */
     55	0x09, 0x46,         /*          Usage (Tablet Pick),        */
     56	0x15, 0x01,         /*          Logical Minimum (1),        */
     57	0x25, 0x03,         /*          Logical Maximum (3),        */
     58	0x75, 0x04,         /*          Report Size (4),            */
     59	0x95, 0x01,         /*          Report Count (1),           */
     60	0x80,               /*          Input,                      */
     61	0x09, 0x32,         /*          Usage (In Range),           */
     62	0x14,               /*          Logical Minimum (0),        */
     63	0x25, 0x01,         /*          Logical Maximum (1),        */
     64	0x75, 0x01,         /*          Report Size (1),            */
     65	0x95, 0x01,         /*          Report Count (1),           */
     66	0x81, 0x02,         /*          Input (Variable),           */
     67	0x95, 0x03,         /*          Report Count (3),           */
     68	0x81, 0x03,         /*          Input (Constant, Variable), */
     69	0x75, 0x10,         /*          Report Size (16),           */
     70	0x95, 0x01,         /*          Report Count (1),           */
     71	0x14,               /*          Logical Minimum (0),        */
     72	0xA4,               /*          Push,                       */
     73	0x05, 0x01,         /*          Usage Page (Desktop),       */
     74	0x65, 0x13,         /*          Unit (Inch),                */
     75	0x55, 0xFD,         /*          Unit Exponent (-3),         */
     76	0x34,               /*          Physical Minimum (0),       */
     77	0x09, 0x30,         /*          Usage (X),                  */
     78	0x46, 0x88, 0x13,   /*          Physical Maximum (5000),    */
     79	0x26, 0x10, 0x27,   /*          Logical Maximum (10000),    */
     80	0x81, 0x02,         /*          Input (Variable),           */
     81	0x09, 0x31,         /*          Usage (Y),                  */
     82	0x46, 0xB8, 0x0B,   /*          Physical Maximum (3000),    */
     83	0x26, 0x70, 0x17,   /*          Logical Maximum (6000),     */
     84	0x81, 0x02,         /*          Input (Variable),           */
     85	0xB4,               /*          Pop,                        */
     86	0x09, 0x30,         /*          Usage (Tip Pressure),       */
     87	0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
     88	0x81, 0x02,         /*          Input (Variable),           */
     89	0xC0,               /*      End Collection,                 */
     90	0xC0                /*  End Collection                      */
     91};
     92
     93/* Size of the original report descriptor of Slim Tablet 12.1 inch */
     94#define SLIM_TABLET_12_1_INCH_RDESC_ORIG_SIZE	269
     95
     96/* Fixed Slim Tablet 12.1 inch descriptor */
     97static __u8 slim_tablet_12_1_inch_rdesc_fixed[] = {
     98	0x05, 0x0D,         /*  Usage Page (Digitizer),             */
     99	0x09, 0x02,         /*  Usage (Pen),                        */
    100	0xA1, 0x01,         /*  Collection (Application),           */
    101	0x85, 0x10,         /*      Report ID (16),                 */
    102	0x09, 0x20,         /*      Usage (Stylus),                 */
    103	0xA0,               /*      Collection (Physical),          */
    104	0x09, 0x42,         /*          Usage (Tip Switch),         */
    105	0x09, 0x44,         /*          Usage (Barrel Switch),      */
    106	0x09, 0x46,         /*          Usage (Tablet Pick),        */
    107	0x15, 0x01,         /*          Logical Minimum (1),        */
    108	0x25, 0x03,         /*          Logical Maximum (3),        */
    109	0x75, 0x04,         /*          Report Size (4),            */
    110	0x95, 0x01,         /*          Report Count (1),           */
    111	0x80,               /*          Input,                      */
    112	0x09, 0x32,         /*          Usage (In Range),           */
    113	0x14,               /*          Logical Minimum (0),        */
    114	0x25, 0x01,         /*          Logical Maximum (1),        */
    115	0x75, 0x01,         /*          Report Size (1),            */
    116	0x95, 0x01,         /*          Report Count (1),           */
    117	0x81, 0x02,         /*          Input (Variable),           */
    118	0x95, 0x03,         /*          Report Count (3),           */
    119	0x81, 0x03,         /*          Input (Constant, Variable), */
    120	0x75, 0x10,         /*          Report Size (16),           */
    121	0x95, 0x01,         /*          Report Count (1),           */
    122	0x14,               /*          Logical Minimum (0),        */
    123	0xA4,               /*          Push,                       */
    124	0x05, 0x01,         /*          Usage Page (Desktop),       */
    125	0x65, 0x13,         /*          Unit (Inch),                */
    126	0x55, 0xFD,         /*          Unit Exponent (-3),         */
    127	0x34,               /*          Physical Minimum (0),       */
    128	0x09, 0x30,         /*          Usage (X),                  */
    129	0x46, 0x10, 0x27,   /*          Physical Maximum (10000),   */
    130	0x26, 0x20, 0x4E,   /*          Logical Maximum (20000),    */
    131	0x81, 0x02,         /*          Input (Variable),           */
    132	0x09, 0x31,         /*          Usage (Y),                  */
    133	0x46, 0x6A, 0x18,   /*          Physical Maximum (6250),    */
    134	0x26, 0xD4, 0x30,   /*          Logical Maximum (12500),    */
    135	0x81, 0x02,         /*          Input (Variable),           */
    136	0xB4,               /*          Pop,                        */
    137	0x09, 0x30,         /*          Usage (Tip Pressure),       */
    138	0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
    139	0x81, 0x02,         /*          Input (Variable),           */
    140	0xC0,               /*      End Collection,                 */
    141	0xC0                /*  End Collection                      */
    142};
    143
    144/* Size of the original report descriptor of Q Pad */
    145#define Q_PAD_RDESC_ORIG_SIZE	241
    146
    147/* Fixed Q Pad descriptor */
    148static __u8 q_pad_rdesc_fixed[] = {
    149	0x05, 0x0D,         /*  Usage Page (Digitizer),             */
    150	0x09, 0x02,         /*  Usage (Pen),                        */
    151	0xA1, 0x01,         /*  Collection (Application),           */
    152	0x85, 0x10,         /*      Report ID (16),                 */
    153	0x09, 0x20,         /*      Usage (Stylus),                 */
    154	0xA0,               /*      Collection (Physical),          */
    155	0x09, 0x42,         /*          Usage (Tip Switch),         */
    156	0x09, 0x44,         /*          Usage (Barrel Switch),      */
    157	0x09, 0x46,         /*          Usage (Tablet Pick),        */
    158	0x15, 0x01,         /*          Logical Minimum (1),        */
    159	0x25, 0x03,         /*          Logical Maximum (3),        */
    160	0x75, 0x04,         /*          Report Size (4),            */
    161	0x95, 0x01,         /*          Report Count (1),           */
    162	0x80,               /*          Input,                      */
    163	0x09, 0x32,         /*          Usage (In Range),           */
    164	0x14,               /*          Logical Minimum (0),        */
    165	0x25, 0x01,         /*          Logical Maximum (1),        */
    166	0x75, 0x01,         /*          Report Size (1),            */
    167	0x95, 0x01,         /*          Report Count (1),           */
    168	0x81, 0x02,         /*          Input (Variable),           */
    169	0x95, 0x03,         /*          Report Count (3),           */
    170	0x81, 0x03,         /*          Input (Constant, Variable), */
    171	0x75, 0x10,         /*          Report Size (16),           */
    172	0x95, 0x01,         /*          Report Count (1),           */
    173	0x14,               /*          Logical Minimum (0),        */
    174	0xA4,               /*          Push,                       */
    175	0x05, 0x01,         /*          Usage Page (Desktop),       */
    176	0x65, 0x13,         /*          Unit (Inch),                */
    177	0x55, 0xFD,         /*          Unit Exponent (-3),         */
    178	0x34,               /*          Physical Minimum (0),       */
    179	0x09, 0x30,         /*          Usage (X),                  */
    180	0x46, 0x70, 0x17,   /*          Physical Maximum (6000),    */
    181	0x26, 0x00, 0x30,   /*          Logical Maximum (12288),    */
    182	0x81, 0x02,         /*          Input (Variable),           */
    183	0x09, 0x31,         /*          Usage (Y),                  */
    184	0x46, 0x94, 0x11,   /*          Physical Maximum (4500),    */
    185	0x26, 0x00, 0x24,   /*          Logical Maximum (9216),     */
    186	0x81, 0x02,         /*          Input (Variable),           */
    187	0xB4,               /*          Pop,                        */
    188	0x09, 0x30,         /*          Usage (Tip Pressure),       */
    189	0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
    190	0x81, 0x02,         /*          Input (Variable),           */
    191	0xC0,               /*      End Collection,                 */
    192	0xC0                /*  End Collection                      */
    193};
    194
    195/* Size of the original report descriptor of tablet with PID 0038 */
    196#define PID_0038_RDESC_ORIG_SIZE	241
    197
    198/*
    199 * Fixed report descriptor for tablet with PID 0038.
    200 */
    201static __u8 pid_0038_rdesc_fixed[] = {
    202	0x05, 0x0D,         /*  Usage Page (Digitizer),             */
    203	0x09, 0x02,         /*  Usage (Pen),                        */
    204	0xA1, 0x01,         /*  Collection (Application),           */
    205	0x85, 0x10,         /*      Report ID (16),                 */
    206	0x09, 0x20,         /*      Usage (Stylus),                 */
    207	0xA0,               /*      Collection (Physical),          */
    208	0x09, 0x42,         /*          Usage (Tip Switch),         */
    209	0x09, 0x44,         /*          Usage (Barrel Switch),      */
    210	0x09, 0x46,         /*          Usage (Tablet Pick),        */
    211	0x15, 0x01,         /*          Logical Minimum (1),        */
    212	0x25, 0x03,         /*          Logical Maximum (3),        */
    213	0x75, 0x04,         /*          Report Size (4),            */
    214	0x95, 0x01,         /*          Report Count (1),           */
    215	0x80,               /*          Input,                      */
    216	0x09, 0x32,         /*          Usage (In Range),           */
    217	0x14,               /*          Logical Minimum (0),        */
    218	0x25, 0x01,         /*          Logical Maximum (1),        */
    219	0x75, 0x01,         /*          Report Size (1),            */
    220	0x95, 0x01,         /*          Report Count (1),           */
    221	0x81, 0x02,         /*          Input (Variable),           */
    222	0x95, 0x03,         /*          Report Count (3),           */
    223	0x81, 0x03,         /*          Input (Constant, Variable), */
    224	0x75, 0x10,         /*          Report Size (16),           */
    225	0x95, 0x01,         /*          Report Count (1),           */
    226	0x14,               /*          Logical Minimum (0),        */
    227	0xA4,               /*          Push,                       */
    228	0x05, 0x01,         /*          Usage Page (Desktop),       */
    229	0x65, 0x13,         /*          Unit (Inch),                */
    230	0x55, 0xFD,         /*          Unit Exponent (-3),         */
    231	0x34,               /*          Physical Minimum (0),       */
    232	0x09, 0x30,         /*          Usage (X),                  */
    233	0x46, 0x2E, 0x22,   /*          Physical Maximum (8750),    */
    234	0x26, 0x00, 0x46,   /*          Logical Maximum (17920),    */
    235	0x81, 0x02,         /*          Input (Variable),           */
    236	0x09, 0x31,         /*          Usage (Y),                  */
    237	0x46, 0x82, 0x14,   /*          Physical Maximum (5250),    */
    238	0x26, 0x00, 0x2A,   /*          Logical Maximum (10752),    */
    239	0x81, 0x02,         /*          Input (Variable),           */
    240	0xB4,               /*          Pop,                        */
    241	0x09, 0x30,         /*          Usage (Tip Pressure),       */
    242	0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
    243	0x81, 0x02,         /*          Input (Variable),           */
    244	0xC0,               /*      End Collection,                 */
    245	0xC0                /*  End Collection                      */
    246};
    247
    248/* Size of the original report descriptor of Media Tablet 10.6 inch */
    249#define MEDIA_TABLET_10_6_INCH_RDESC_ORIG_SIZE	300
    250
    251/* Fixed Media Tablet 10.6 inch descriptor */
    252static __u8 media_tablet_10_6_inch_rdesc_fixed[] = {
    253	0x05, 0x0D,         /*  Usage Page (Digitizer),             */
    254	0x09, 0x02,         /*  Usage (Pen),                        */
    255	0xA1, 0x01,         /*  Collection (Application),           */
    256	0x85, 0x10,         /*      Report ID (16),                 */
    257	0x09, 0x20,         /*      Usage (Stylus),                 */
    258	0xA0,               /*      Collection (Physical),          */
    259	0x09, 0x42,         /*          Usage (Tip Switch),         */
    260	0x09, 0x44,         /*          Usage (Barrel Switch),      */
    261	0x09, 0x46,         /*          Usage (Tablet Pick),        */
    262	0x15, 0x01,         /*          Logical Minimum (1),        */
    263	0x25, 0x03,         /*          Logical Maximum (3),        */
    264	0x75, 0x04,         /*          Report Size (4),            */
    265	0x95, 0x01,         /*          Report Count (1),           */
    266	0x80,               /*          Input,                      */
    267	0x75, 0x01,         /*          Report Size (1),            */
    268	0x09, 0x32,         /*          Usage (In Range),           */
    269	0x14,               /*          Logical Minimum (0),        */
    270	0x25, 0x01,         /*          Logical Maximum (1),        */
    271	0x95, 0x01,         /*          Report Count (1),           */
    272	0x81, 0x02,         /*          Input (Variable),           */
    273	0x95, 0x03,         /*          Report Count (3),           */
    274	0x81, 0x03,         /*          Input (Constant, Variable), */
    275	0x75, 0x10,         /*          Report Size (16),           */
    276	0x95, 0x01,         /*          Report Count (1),           */
    277	0x14,               /*          Logical Minimum (0),        */
    278	0xA4,               /*          Push,                       */
    279	0x05, 0x01,         /*          Usage Page (Desktop),       */
    280	0x65, 0x13,         /*          Unit (Inch),                */
    281	0x55, 0xFD,         /*          Unit Exponent (-3),         */
    282	0x34,               /*          Physical Minimum (0),       */
    283	0x09, 0x30,         /*          Usage (X),                  */
    284	0x46, 0x28, 0x23,   /*          Physical Maximum (9000),    */
    285	0x26, 0x50, 0x46,   /*          Logical Maximum (18000),    */
    286	0x81, 0x02,         /*          Input (Variable),           */
    287	0x09, 0x31,         /*          Usage (Y),                  */
    288	0x46, 0x7C, 0x15,   /*          Physical Maximum (5500),    */
    289	0x26, 0xF8, 0x2A,   /*          Logical Maximum (11000),    */
    290	0x81, 0x02,         /*          Input (Variable),           */
    291	0xB4,               /*          Pop,                        */
    292	0x09, 0x30,         /*          Usage (Tip Pressure),       */
    293	0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
    294	0x81, 0x02,         /*          Input (Variable),           */
    295	0xC0,               /*      End Collection,                 */
    296	0xC0,               /*  End Collection,                     */
    297	0x05, 0x01,         /*  Usage Page (Desktop),               */
    298	0x09, 0x02,         /*  Usage (Mouse),                      */
    299	0xA1, 0x01,         /*  Collection (Application),           */
    300	0x85, 0x01,         /*      Report ID (1),                  */
    301	0x09, 0x01,         /*      Usage (Pointer),                */
    302	0xA0,               /*      Collection (Physical),          */
    303	0x75, 0x08,         /*          Report Size (8),            */
    304	0x95, 0x03,         /*          Report Count (3),           */
    305	0x81, 0x03,         /*          Input (Constant, Variable), */
    306	0x95, 0x02,         /*          Report Count (2),           */
    307	0x15, 0xFF,         /*          Logical Minimum (-1),       */
    308	0x25, 0x01,         /*          Logical Maximum (1),        */
    309	0x09, 0x38,         /*          Usage (Wheel),              */
    310	0x0B, 0x38, 0x02,   /*          Usage (Consumer AC Pan),    */
    311		0x0C, 0x00,
    312	0x81, 0x06,         /*          Input (Variable, Relative), */
    313	0x95, 0x02,         /*          Report Count (2),           */
    314	0x81, 0x03,         /*          Input (Constant, Variable), */
    315	0xC0,               /*      End Collection,                 */
    316	0xC0,               /*  End Collection,                     */
    317	0x05, 0x0C,         /*  Usage Page (Consumer),              */
    318	0x09, 0x01,         /*  Usage (Consumer Control),           */
    319	0xA1, 0x01,         /*  Collection (Application),           */
    320	0x85, 0x0D,         /*      Report ID (13),                 */
    321	0x95, 0x01,         /*      Report Count (1),               */
    322	0x75, 0x10,         /*      Report Size (16),               */
    323	0x81, 0x03,         /*      Input (Constant, Variable),     */
    324	0x0A, 0x2F, 0x02,   /*      Usage (AC Zoom),                */
    325	0x0A, 0x2E, 0x02,   /*      Usage (AC Zoom Out),            */
    326	0x0A, 0x2D, 0x02,   /*      Usage (AC Zoom In),             */
    327	0x09, 0xB6,         /*      Usage (Scan Previous Track),    */
    328	0x09, 0xB5,         /*      Usage (Scan Next Track),        */
    329	0x08,               /*      Usage (00h),                    */
    330	0x08,               /*      Usage (00h),                    */
    331	0x08,               /*      Usage (00h),                    */
    332	0x08,               /*      Usage (00h),                    */
    333	0x08,               /*      Usage (00h),                    */
    334	0x0A, 0x2E, 0x02,   /*      Usage (AC Zoom Out),            */
    335	0x0A, 0x2D, 0x02,   /*      Usage (AC Zoom In),             */
    336	0x15, 0x0C,         /*      Logical Minimum (12),           */
    337	0x25, 0x17,         /*      Logical Maximum (23),           */
    338	0x75, 0x05,         /*      Report Size (5),                */
    339	0x80,               /*      Input,                          */
    340	0x75, 0x03,         /*      Report Size (3),                */
    341	0x81, 0x03,         /*      Input (Constant, Variable),     */
    342	0x75, 0x20,         /*      Report Size (32),               */
    343	0x81, 0x03,         /*      Input (Constant, Variable),     */
    344	0xC0,               /*  End Collection,                     */
    345	0x09, 0x01,         /*  Usage (Consumer Control),           */
    346	0xA1, 0x01,         /*  Collection (Application),           */
    347	0x85, 0x0C,         /*      Report ID (12),                 */
    348	0x75, 0x01,         /*      Report Size (1),                */
    349	0x09, 0xE9,         /*      Usage (Volume Inc),             */
    350	0x09, 0xEA,         /*      Usage (Volume Dec),             */
    351	0x09, 0xE2,         /*      Usage (Mute),                   */
    352	0x14,               /*      Logical Minimum (0),            */
    353	0x25, 0x01,         /*      Logical Maximum (1),            */
    354	0x95, 0x03,         /*      Report Count (3),               */
    355	0x81, 0x06,         /*      Input (Variable, Relative),     */
    356	0x95, 0x35,         /*      Report Count (53),              */
    357	0x81, 0x03,         /*      Input (Constant, Variable),     */
    358	0xC0                /*  End Collection                      */
    359};
    360
    361/* Size of the original report descriptor of Media Tablet 14.1 inch */
    362#define MEDIA_TABLET_14_1_INCH_RDESC_ORIG_SIZE	309
    363
    364/* Fixed Media Tablet 14.1 inch descriptor */
    365static __u8 media_tablet_14_1_inch_rdesc_fixed[] = {
    366	0x05, 0x0D,         /*  Usage Page (Digitizer),             */
    367	0x09, 0x02,         /*  Usage (Pen),                        */
    368	0xA1, 0x01,         /*  Collection (Application),           */
    369	0x85, 0x10,         /*      Report ID (16),                 */
    370	0x09, 0x20,         /*      Usage (Stylus),                 */
    371	0xA0,               /*      Collection (Physical),          */
    372	0x09, 0x42,         /*          Usage (Tip Switch),         */
    373	0x09, 0x44,         /*          Usage (Barrel Switch),      */
    374	0x09, 0x46,         /*          Usage (Tablet Pick),        */
    375	0x15, 0x01,         /*          Logical Minimum (1),        */
    376	0x25, 0x03,         /*          Logical Maximum (3),        */
    377	0x75, 0x04,         /*          Report Size (4),            */
    378	0x95, 0x01,         /*          Report Count (1),           */
    379	0x80,               /*          Input,                      */
    380	0x75, 0x01,         /*          Report Size (1),            */
    381	0x09, 0x32,         /*          Usage (In Range),           */
    382	0x14,               /*          Logical Minimum (0),        */
    383	0x25, 0x01,         /*          Logical Maximum (1),        */
    384	0x95, 0x01,         /*          Report Count (1),           */
    385	0x81, 0x02,         /*          Input (Variable),           */
    386	0x95, 0x03,         /*          Report Count (3),           */
    387	0x81, 0x03,         /*          Input (Constant, Variable), */
    388	0x75, 0x10,         /*          Report Size (16),           */
    389	0x95, 0x01,         /*          Report Count (1),           */
    390	0x14,               /*          Logical Minimum (0),        */
    391	0xA4,               /*          Push,                       */
    392	0x05, 0x01,         /*          Usage Page (Desktop),       */
    393	0x65, 0x13,         /*          Unit (Inch),                */
    394	0x55, 0xFD,         /*          Unit Exponent (-3),         */
    395	0x34,               /*          Physical Minimum (0),       */
    396	0x09, 0x30,         /*          Usage (X),                  */
    397	0x46, 0xE0, 0x2E,   /*          Physical Maximum (12000),   */
    398	0x26, 0xFF, 0x3F,   /*          Logical Maximum (16383),    */
    399	0x81, 0x02,         /*          Input (Variable),           */
    400	0x09, 0x31,         /*          Usage (Y),                  */
    401	0x46, 0x52, 0x1C,   /*          Physical Maximum (7250),    */
    402	0x26, 0xFF, 0x3F,   /*          Logical Maximum (16383),    */
    403	0x81, 0x02,         /*          Input (Variable),           */
    404	0xB4,               /*          Pop,                        */
    405	0x09, 0x30,         /*          Usage (Tip Pressure),       */
    406	0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
    407	0x81, 0x02,         /*          Input (Variable),           */
    408	0xC0,               /*      End Collection,                 */
    409	0xC0,               /*  End Collection,                     */
    410	0x05, 0x01,         /*  Usage Page (Desktop),               */
    411	0x09, 0x02,         /*  Usage (Mouse),                      */
    412	0xA1, 0x01,         /*  Collection (Application),           */
    413	0x85, 0x01,         /*      Report ID (1),                  */
    414	0x09, 0x01,         /*      Usage (Pointer),                */
    415	0xA0,               /*      Collection (Physical),          */
    416	0x75, 0x08,         /*          Report Size (8),            */
    417	0x95, 0x03,         /*          Report Count (3),           */
    418	0x81, 0x03,         /*          Input (Constant, Variable), */
    419	0x95, 0x02,         /*          Report Count (2),           */
    420	0x15, 0xFF,         /*          Logical Minimum (-1),       */
    421	0x25, 0x01,         /*          Logical Maximum (1),        */
    422	0x09, 0x38,         /*          Usage (Wheel),              */
    423	0x0B, 0x38, 0x02,   /*          Usage (Consumer AC Pan),    */
    424		0x0C, 0x00,
    425	0x81, 0x06,         /*          Input (Variable, Relative), */
    426	0xC0,               /*      End Collection,                 */
    427	0xC0,               /*  End Collection,                     */
    428	0x05, 0x0C,         /*  Usage Page (Consumer),              */
    429	0x09, 0x01,         /*  Usage (Consumer Control),           */
    430	0xA1, 0x01,         /*  Collection (Application),           */
    431	0x85, 0x0D,         /*      Report ID (13),                 */
    432	0x95, 0x01,         /*      Report Count (1),               */
    433	0x75, 0x10,         /*      Report Size (16),               */
    434	0x81, 0x03,         /*      Input (Constant, Variable),     */
    435	0x0A, 0x2F, 0x02,   /*      Usage (AC Zoom),                */
    436	0x0A, 0x2E, 0x02,   /*      Usage (AC Zoom Out),            */
    437	0x0A, 0x2D, 0x02,   /*      Usage (AC Zoom In),             */
    438	0x09, 0xB6,         /*      Usage (Scan Previous Track),    */
    439	0x09, 0xB5,         /*      Usage (Scan Next Track),        */
    440	0x08,               /*      Usage (00h),                    */
    441	0x08,               /*      Usage (00h),                    */
    442	0x08,               /*      Usage (00h),                    */
    443	0x08,               /*      Usage (00h),                    */
    444	0x08,               /*      Usage (00h),                    */
    445	0x0A, 0x2E, 0x02,   /*      Usage (AC Zoom Out),            */
    446	0x0A, 0x2D, 0x02,   /*      Usage (AC Zoom In),             */
    447	0x15, 0x0C,         /*      Logical Minimum (12),           */
    448	0x25, 0x17,         /*      Logical Maximum (23),           */
    449	0x75, 0x05,         /*      Report Size (5),                */
    450	0x80,               /*      Input,                          */
    451	0x75, 0x03,         /*      Report Size (3),                */
    452	0x81, 0x03,         /*      Input (Constant, Variable),     */
    453	0x75, 0x20,         /*      Report Size (32),               */
    454	0x81, 0x03,         /*      Input (Constant, Variable),     */
    455	0xC0,               /*  End Collection,                     */
    456	0x09, 0x01,         /*  Usage (Consumer Control),           */
    457	0xA1, 0x01,         /*  Collection (Application),           */
    458	0x85, 0x0C,         /*      Report ID (12),                 */
    459	0x75, 0x01,         /*      Report Size (1),                */
    460	0x09, 0xE9,         /*      Usage (Volume Inc),             */
    461	0x09, 0xEA,         /*      Usage (Volume Dec),             */
    462	0x09, 0xE2,         /*      Usage (Mute),                   */
    463	0x14,               /*      Logical Minimum (0),            */
    464	0x25, 0x01,         /*      Logical Maximum (1),            */
    465	0x95, 0x03,         /*      Report Count (3),               */
    466	0x81, 0x06,         /*      Input (Variable, Relative),     */
    467	0x75, 0x05,         /*      Report Size (5),                */
    468	0x81, 0x03,         /*      Input (Constant, Variable),     */
    469	0xC0                /*  End Collection                      */
    470};
    471
    472/* Size of the original report descriptor of Sirius Battery Free Tablet */
    473#define SIRIUS_BATTERY_FREE_TABLET_RDESC_ORIG_SIZE	335
    474
    475/* Fixed Sirius Battery Free Tablet descriptor */
    476static __u8 sirius_battery_free_tablet_rdesc_fixed[] = {
    477	0x05, 0x0D,         /*  Usage Page (Digitizer),             */
    478	0x09, 0x02,         /*  Usage (Pen),                        */
    479	0xA1, 0x01,         /*  Collection (Application),           */
    480	0x85, 0x10,         /*      Report ID (16),                 */
    481	0x09, 0x20,         /*      Usage (Stylus),                 */
    482	0xA0,               /*      Collection (Physical),          */
    483	0x95, 0x01,         /*          Report Count (1),           */
    484	0x15, 0x01,         /*          Logical Minimum (1),        */
    485	0x25, 0x03,         /*          Logical Maximum (3),        */
    486	0x75, 0x02,         /*          Report Size (2),            */
    487	0x09, 0x42,         /*          Usage (Tip Switch),         */
    488	0x09, 0x44,         /*          Usage (Barrel Switch),      */
    489	0x09, 0x46,         /*          Usage (Tablet Pick),        */
    490	0x80,               /*          Input,                      */
    491	0x14,               /*          Logical Minimum (0),        */
    492	0x25, 0x01,         /*          Logical Maximum (1),        */
    493	0x75, 0x01,         /*          Report Size (1),            */
    494	0x09, 0x3C,         /*          Usage (Invert),             */
    495	0x81, 0x02,         /*          Input (Variable),           */
    496	0x81, 0x03,         /*          Input (Constant, Variable), */
    497	0x09, 0x32,         /*          Usage (In Range),           */
    498	0x81, 0x02,         /*          Input (Variable),           */
    499	0x95, 0x03,         /*          Report Count (3),           */
    500	0x81, 0x03,         /*          Input (Constant, Variable), */
    501	0xA4,               /*          Push,                       */
    502	0x05, 0x01,         /*          Usage Page (Desktop),       */
    503	0x55, 0xFD,         /*          Unit Exponent (-3),         */
    504	0x65, 0x13,         /*          Unit (Inch),                */
    505	0x34,               /*          Physical Minimum (0),       */
    506	0x14,               /*          Logical Minimum (0),        */
    507	0x75, 0x10,         /*          Report Size (16),           */
    508	0x95, 0x01,         /*          Report Count (1),           */
    509	0x46, 0x10, 0x27,   /*          Physical Maximum (10000),   */
    510	0x26, 0x20, 0x4E,   /*          Logical Maximum (20000),    */
    511	0x09, 0x30,         /*          Usage (X),                  */
    512	0x81, 0x02,         /*          Input (Variable),           */
    513	0x46, 0x70, 0x17,   /*          Physical Maximum (6000),    */
    514	0x26, 0xE0, 0x2E,   /*          Logical Maximum (12000),    */
    515	0x09, 0x31,         /*          Usage (Y),                  */
    516	0x81, 0x02,         /*          Input (Variable),           */
    517	0xB4,               /*          Pop,                        */
    518	0x75, 0x10,         /*          Report Size (16),           */
    519	0x95, 0x01,         /*          Report Count (1),           */
    520	0x14,               /*          Logical Minimum (0),        */
    521	0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
    522	0x09, 0x30,         /*          Usage (Tip Pressure),       */
    523	0x81, 0x02,         /*          Input (Variable),           */
    524	0xA4,               /*          Push,                       */
    525	0x55, 0xFE,         /*          Unit Exponent (-2),         */
    526	0x65, 0x12,         /*          Unit (Radians),             */
    527	0x35, 0x97,         /*          Physical Minimum (-105),    */
    528	0x45, 0x69,         /*          Physical Maximum (105),     */
    529	0x15, 0x97,         /*          Logical Minimum (-105),     */
    530	0x25, 0x69,         /*          Logical Maximum (105),      */
    531	0x75, 0x08,         /*          Report Size (8),            */
    532	0x95, 0x02,         /*          Report Count (2),           */
    533	0x09, 0x3D,         /*          Usage (X Tilt),             */
    534	0x09, 0x3E,         /*          Usage (Y Tilt),             */
    535	0x81, 0x02,         /*          Input (Variable),           */
    536	0xB4,               /*          Pop,                        */
    537	0xC0,               /*      End Collection,                 */
    538	0xC0,               /*  End Collection,                     */
    539	0x05, 0x01,         /*  Usage Page (Desktop),               */
    540	0x09, 0x02,         /*  Usage (Mouse),                      */
    541	0xA1, 0x01,         /*  Collection (Application),           */
    542	0x85, 0x01,         /*      Report ID (1),                  */
    543	0x09, 0x01,         /*      Usage (Pointer),                */
    544	0xA0,               /*      Collection (Physical),          */
    545	0x75, 0x08,         /*          Report Size (8),            */
    546	0x95, 0x03,         /*          Report Count (3),           */
    547	0x81, 0x03,         /*          Input (Constant, Variable), */
    548	0x09, 0x38,         /*          Usage (Wheel),              */
    549	0x15, 0xFF,         /*          Logical Minimum (-1),       */
    550	0x25, 0x01,         /*          Logical Maximum (1),        */
    551	0x75, 0x08,         /*          Report Size (8),            */
    552	0x95, 0x01,         /*          Report Count (1),           */
    553	0x81, 0x06,         /*          Input (Variable, Relative), */
    554	0x75, 0x08,         /*          Report Size (8),            */
    555	0x95, 0x03,         /*          Report Count (3),           */
    556	0x81, 0x03,         /*          Input (Constant, Variable), */
    557	0xC0,               /*      End Collection,                 */
    558	0xC0,               /*  End Collection,                     */
    559	0x05, 0x01,         /*  Usage Page (Desktop),               */
    560	0x09, 0x06,         /*  Usage (Keyboard),                   */
    561	0xA1, 0x01,         /*  Collection (Application),           */
    562	0x85, 0x0D,         /*      Report ID (13),                 */
    563	0x05, 0x07,         /*      Usage Page (Keyboard),          */
    564	0x19, 0xE0,         /*      Usage Minimum (KB Leftcontrol), */
    565	0x29, 0xE7,         /*      Usage Maximum (KB Right GUI),   */
    566	0x14,               /*      Logical Minimum (0),            */
    567	0x25, 0x01,         /*      Logical Maximum (1),            */
    568	0x75, 0x01,         /*      Report Size (1),                */
    569	0x95, 0x08,         /*      Report Count (8),               */
    570	0x81, 0x02,         /*      Input (Variable),               */
    571	0x75, 0x08,         /*      Report Size (8),                */
    572	0x95, 0x01,         /*      Report Count (1),               */
    573	0x81, 0x01,         /*      Input (Constant),               */
    574	0x18,               /*      Usage Minimum (None),           */
    575	0x29, 0x65,         /*      Usage Maximum (KB Application), */
    576	0x14,               /*      Logical Minimum (0),            */
    577	0x25, 0x65,         /*      Logical Maximum (101),          */
    578	0x75, 0x08,         /*      Report Size (8),                */
    579	0x95, 0x05,         /*      Report Count (5),               */
    580	0x80,               /*      Input,                          */
    581	0xC0,               /*  End Collection,                     */
    582	0x05, 0x0C,         /*  Usage Page (Consumer),              */
    583	0x09, 0x01,         /*  Usage (Consumer Control),           */
    584	0xA1, 0x01,         /*  Collection (Application),           */
    585	0x85, 0x0C,         /*      Report ID (12),                 */
    586	0x09, 0xE9,         /*      Usage (Volume Inc),             */
    587	0x09, 0xEA,         /*      Usage (Volume Dec),             */
    588	0x14,               /*      Logical Minimum (0),            */
    589	0x25, 0x01,         /*      Logical Maximum (1),            */
    590	0x75, 0x01,         /*      Report Size (1),                */
    591	0x95, 0x02,         /*      Report Count (2),               */
    592	0x81, 0x02,         /*      Input (Variable),               */
    593	0x75, 0x06,         /*      Report Size (6),                */
    594	0x95, 0x01,         /*      Report Count (1),               */
    595	0x81, 0x03,         /*      Input (Constant, Variable),     */
    596	0x75, 0x10,         /*      Report Size (16),               */
    597	0x95, 0x03,         /*      Report Count (3),               */
    598	0x81, 0x03,         /*      Input (Constant, Variable),     */
    599	0xC0                /*  End Collection                      */
    600};
    601
    602static __u8 *waltop_report_fixup(struct hid_device *hdev, __u8 *rdesc,
    603		unsigned int *rsize)
    604{
    605	switch (hdev->product) {
    606	case USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH:
    607		if (*rsize == SLIM_TABLET_5_8_INCH_RDESC_ORIG_SIZE) {
    608			rdesc = slim_tablet_5_8_inch_rdesc_fixed;
    609			*rsize = sizeof(slim_tablet_5_8_inch_rdesc_fixed);
    610		}
    611		break;
    612	case USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH:
    613		if (*rsize == SLIM_TABLET_12_1_INCH_RDESC_ORIG_SIZE) {
    614			rdesc = slim_tablet_12_1_inch_rdesc_fixed;
    615			*rsize = sizeof(slim_tablet_12_1_inch_rdesc_fixed);
    616		}
    617		break;
    618	case USB_DEVICE_ID_WALTOP_Q_PAD:
    619		if (*rsize == Q_PAD_RDESC_ORIG_SIZE) {
    620			rdesc = q_pad_rdesc_fixed;
    621			*rsize = sizeof(q_pad_rdesc_fixed);
    622		}
    623		break;
    624	case USB_DEVICE_ID_WALTOP_PID_0038:
    625		if (*rsize == PID_0038_RDESC_ORIG_SIZE) {
    626			rdesc = pid_0038_rdesc_fixed;
    627			*rsize = sizeof(pid_0038_rdesc_fixed);
    628		}
    629		break;
    630	case USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH:
    631		if (*rsize == MEDIA_TABLET_10_6_INCH_RDESC_ORIG_SIZE) {
    632			rdesc = media_tablet_10_6_inch_rdesc_fixed;
    633			*rsize = sizeof(media_tablet_10_6_inch_rdesc_fixed);
    634		}
    635		break;
    636	case USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH:
    637		if (*rsize == MEDIA_TABLET_14_1_INCH_RDESC_ORIG_SIZE) {
    638			rdesc = media_tablet_14_1_inch_rdesc_fixed;
    639			*rsize = sizeof(media_tablet_14_1_inch_rdesc_fixed);
    640		}
    641		break;
    642	case USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET:
    643		if (*rsize == SIRIUS_BATTERY_FREE_TABLET_RDESC_ORIG_SIZE) {
    644			rdesc = sirius_battery_free_tablet_rdesc_fixed;
    645			*rsize = sizeof(sirius_battery_free_tablet_rdesc_fixed);
    646		}
    647		break;
    648	}
    649	return rdesc;
    650}
    651
    652static int waltop_raw_event(struct hid_device *hdev, struct hid_report *report,
    653		     u8 *data, int size)
    654{
    655	/* If this is a pen input report */
    656	if (report->type == HID_INPUT_REPORT && report->id == 16 && size >= 8) {
    657		/*
    658		 * Ignore reported pressure when a barrel button is pressed,
    659		 * because it is rarely correct.
    660		 */
    661
    662		/* If a barrel button is pressed */
    663		if ((data[1] & 0xF) > 1) {
    664			/* Report zero pressure */
    665			data[6] = 0;
    666			data[7] = 0;
    667		}
    668	}
    669
    670	/* If this is a pen input report of Sirius Battery Free Tablet */
    671	if (hdev->product == USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET &&
    672	    report->type == HID_INPUT_REPORT &&
    673	    report->id == 16 &&
    674	    size == 10) {
    675		/*
    676		 * The tablet reports tilt as roughly sin(a)*21 (18 means 60
    677		 * degrees).
    678		 *
    679		 * This array stores angles as radians * 100, corresponding to
    680		 * reported values up to 60 degrees, as expected by userspace.
    681		 */
    682		static const s8 tilt_to_radians[] = {
    683			0, 5, 10, 14, 19, 24, 29, 34, 40, 45,
    684			50, 56, 62, 68, 74, 81, 88, 96, 105
    685		};
    686
    687		s8 tilt_x = (s8)data[8];
    688		s8 tilt_y = (s8)data[9];
    689		s8 sign_x = tilt_x >= 0 ? 1 : -1;
    690		s8 sign_y = tilt_y >= 0 ? 1 : -1;
    691
    692		tilt_x *= sign_x;
    693		tilt_y *= sign_y;
    694
    695		/*
    696		 * Reverse the Y Tilt direction to match the HID standard and
    697		 * userspace expectations. See HID Usage Tables v1.12 16.3.2
    698		 * Tilt Orientation.
    699		 */
    700		sign_y *= -1;
    701
    702		/*
    703		 * This effectively clamps reported tilt to 60 degrees - the
    704		 * range expected by userspace
    705		 */
    706		if (tilt_x > ARRAY_SIZE(tilt_to_radians) - 1)
    707			tilt_x = ARRAY_SIZE(tilt_to_radians) - 1;
    708		if (tilt_y > ARRAY_SIZE(tilt_to_radians) - 1)
    709			tilt_y = ARRAY_SIZE(tilt_to_radians) - 1;
    710
    711		data[8] = tilt_to_radians[tilt_x] * sign_x;
    712		data[9] = tilt_to_radians[tilt_y] * sign_y;
    713	}
    714
    715	return 0;
    716}
    717
    718static const struct hid_device_id waltop_devices[] = {
    719	{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP,
    720				USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH) },
    721	{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP,
    722				USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH) },
    723	{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP,
    724				USB_DEVICE_ID_WALTOP_Q_PAD) },
    725	{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP,
    726				USB_DEVICE_ID_WALTOP_PID_0038) },
    727	{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP,
    728				USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH) },
    729	{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP,
    730				USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH) },
    731	{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP,
    732			 USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET) },
    733	{ }
    734};
    735MODULE_DEVICE_TABLE(hid, waltop_devices);
    736
    737static struct hid_driver waltop_driver = {
    738	.name = "waltop",
    739	.id_table = waltop_devices,
    740	.report_fixup = waltop_report_fixup,
    741	.raw_event = waltop_raw_event,
    742};
    743module_hid_driver(waltop_driver);
    744
    745MODULE_LICENSE("GPL");