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-kye.c (40323B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 *  HID driver for Kye/Genius devices not fully compliant with HID standard
      4 *
      5 *  Copyright (c) 2009 Jiri Kosina
      6 *  Copyright (c) 2009 Tomas Hanak
      7 *  Copyright (c) 2012 Nikolai Kondrashov
      8 */
      9
     10/*
     11 */
     12
     13#include <linux/device.h>
     14#include <linux/hid.h>
     15#include <linux/module.h>
     16
     17#include "hid-ids.h"
     18
     19/* Original EasyPen i405X report descriptor size */
     20#define EASYPEN_I405X_RDESC_ORIG_SIZE	476
     21
     22/* Fixed EasyPen i405X report descriptor */
     23static __u8 easypen_i405x_rdesc_fixed[] = {
     24	0x06, 0x00, 0xFF, /*  Usage Page (FF00h),             */
     25	0x09, 0x01,       /*  Usage (01h),                    */
     26	0xA1, 0x01,       /*  Collection (Application),       */
     27	0x85, 0x05,       /*    Report ID (5),                */
     28	0x09, 0x01,       /*    Usage (01h),                  */
     29	0x15, 0x80,       /*    Logical Minimum (-128),       */
     30	0x25, 0x7F,       /*    Logical Maximum (127),        */
     31	0x75, 0x08,       /*    Report Size (8),              */
     32	0x95, 0x07,       /*    Report Count (7),             */
     33	0xB1, 0x02,       /*    Feature (Variable),           */
     34	0xC0,             /*  End Collection,                 */
     35	0x05, 0x0D,       /*  Usage Page (Digitizer),         */
     36	0x09, 0x01,       /*  Usage (Digitizer),              */
     37	0xA1, 0x01,       /*  Collection (Application),       */
     38	0x85, 0x10,       /*    Report ID (16),               */
     39	0x09, 0x20,       /*    Usage (Stylus),               */
     40	0xA0,             /*    Collection (Physical),        */
     41	0x14,             /*      Logical Minimum (0),        */
     42	0x25, 0x01,       /*      Logical Maximum (1),        */
     43	0x75, 0x01,       /*      Report Size (1),            */
     44	0x09, 0x42,       /*      Usage (Tip Switch),         */
     45	0x09, 0x44,       /*      Usage (Barrel Switch),      */
     46	0x09, 0x46,       /*      Usage (Tablet Pick),        */
     47	0x95, 0x03,       /*      Report Count (3),           */
     48	0x81, 0x02,       /*      Input (Variable),           */
     49	0x95, 0x04,       /*      Report Count (4),           */
     50	0x81, 0x03,       /*      Input (Constant, Variable), */
     51	0x09, 0x32,       /*      Usage (In Range),           */
     52	0x95, 0x01,       /*      Report Count (1),           */
     53	0x81, 0x02,       /*      Input (Variable),           */
     54	0x75, 0x10,       /*      Report Size (16),           */
     55	0x95, 0x01,       /*      Report Count (1),           */
     56	0xA4,             /*      Push,                       */
     57	0x05, 0x01,       /*      Usage Page (Desktop),       */
     58	0x55, 0xFD,       /*      Unit Exponent (-3),         */
     59	0x65, 0x13,       /*      Unit (Inch),                */
     60	0x34,             /*      Physical Minimum (0),       */
     61	0x09, 0x30,       /*      Usage (X),                  */
     62	0x46, 0x7C, 0x15, /*      Physical Maximum (5500),    */
     63	0x26, 0x00, 0x37, /*      Logical Maximum (14080),    */
     64	0x81, 0x02,       /*      Input (Variable),           */
     65	0x09, 0x31,       /*      Usage (Y),                  */
     66	0x46, 0xA0, 0x0F, /*      Physical Maximum (4000),    */
     67	0x26, 0x00, 0x28, /*      Logical Maximum (10240),    */
     68	0x81, 0x02,       /*      Input (Variable),           */
     69	0xB4,             /*      Pop,                        */
     70	0x09, 0x30,       /*      Usage (Tip Pressure),       */
     71	0x26, 0xFF, 0x03, /*      Logical Maximum (1023),     */
     72	0x81, 0x02,       /*      Input (Variable),           */
     73	0xC0,             /*    End Collection,               */
     74	0xC0              /*  End Collection                  */
     75};
     76
     77/* Original MousePen i608X report descriptor size */
     78#define MOUSEPEN_I608X_RDESC_ORIG_SIZE	476
     79
     80/* Fixed MousePen i608X report descriptor */
     81static __u8 mousepen_i608x_rdesc_fixed[] = {
     82	0x06, 0x00, 0xFF, /*  Usage Page (FF00h),             */
     83	0x09, 0x01,       /*  Usage (01h),                    */
     84	0xA1, 0x01,       /*  Collection (Application),       */
     85	0x85, 0x05,       /*    Report ID (5),                */
     86	0x09, 0x01,       /*    Usage (01h),                  */
     87	0x15, 0x80,       /*    Logical Minimum (-128),       */
     88	0x25, 0x7F,       /*    Logical Maximum (127),        */
     89	0x75, 0x08,       /*    Report Size (8),              */
     90	0x95, 0x07,       /*    Report Count (7),             */
     91	0xB1, 0x02,       /*    Feature (Variable),           */
     92	0xC0,             /*  End Collection,                 */
     93	0x05, 0x0D,       /*  Usage Page (Digitizer),         */
     94	0x09, 0x01,       /*  Usage (Digitizer),              */
     95	0xA1, 0x01,       /*  Collection (Application),       */
     96	0x85, 0x10,       /*    Report ID (16),               */
     97	0x09, 0x20,       /*    Usage (Stylus),               */
     98	0xA0,             /*    Collection (Physical),        */
     99	0x14,             /*      Logical Minimum (0),        */
    100	0x25, 0x01,       /*      Logical Maximum (1),        */
    101	0x75, 0x01,       /*      Report Size (1),            */
    102	0x09, 0x42,       /*      Usage (Tip Switch),         */
    103	0x09, 0x44,       /*      Usage (Barrel Switch),      */
    104	0x09, 0x46,       /*      Usage (Tablet Pick),        */
    105	0x95, 0x03,       /*      Report Count (3),           */
    106	0x81, 0x02,       /*      Input (Variable),           */
    107	0x95, 0x04,       /*      Report Count (4),           */
    108	0x81, 0x03,       /*      Input (Constant, Variable), */
    109	0x09, 0x32,       /*      Usage (In Range),           */
    110	0x95, 0x01,       /*      Report Count (1),           */
    111	0x81, 0x02,       /*      Input (Variable),           */
    112	0x75, 0x10,       /*      Report Size (16),           */
    113	0x95, 0x01,       /*      Report Count (1),           */
    114	0xA4,             /*      Push,                       */
    115	0x05, 0x01,       /*      Usage Page (Desktop),       */
    116	0x55, 0xFD,       /*      Unit Exponent (-3),         */
    117	0x65, 0x13,       /*      Unit (Inch),                */
    118	0x34,             /*      Physical Minimum (0),       */
    119	0x09, 0x30,       /*      Usage (X),                  */
    120	0x46, 0x40, 0x1F, /*      Physical Maximum (8000),    */
    121	0x26, 0x00, 0x50, /*      Logical Maximum (20480),    */
    122	0x81, 0x02,       /*      Input (Variable),           */
    123	0x09, 0x31,       /*      Usage (Y),                  */
    124	0x46, 0x70, 0x17, /*      Physical Maximum (6000),    */
    125	0x26, 0x00, 0x3C, /*      Logical Maximum (15360),    */
    126	0x81, 0x02,       /*      Input (Variable),           */
    127	0xB4,             /*      Pop,                        */
    128	0x09, 0x30,       /*      Usage (Tip Pressure),       */
    129	0x26, 0xFF, 0x03, /*      Logical Maximum (1023),     */
    130	0x81, 0x02,       /*      Input (Variable),           */
    131	0xC0,             /*    End Collection,               */
    132	0xC0,             /*  End Collection,                 */
    133	0x05, 0x01,       /*  Usage Page (Desktop),           */
    134	0x09, 0x02,       /*  Usage (Mouse),                  */
    135	0xA1, 0x01,       /*  Collection (Application),       */
    136	0x85, 0x11,       /*    Report ID (17),               */
    137	0x09, 0x01,       /*    Usage (Pointer),              */
    138	0xA0,             /*    Collection (Physical),        */
    139	0x14,             /*      Logical Minimum (0),        */
    140	0xA4,             /*      Push,                       */
    141	0x05, 0x09,       /*      Usage Page (Button),        */
    142	0x75, 0x01,       /*      Report Size (1),            */
    143	0x19, 0x01,       /*      Usage Minimum (01h),        */
    144	0x29, 0x03,       /*      Usage Maximum (03h),        */
    145	0x25, 0x01,       /*      Logical Maximum (1),        */
    146	0x95, 0x03,       /*      Report Count (3),           */
    147	0x81, 0x02,       /*      Input (Variable),           */
    148	0x95, 0x05,       /*      Report Count (5),           */
    149	0x81, 0x01,       /*      Input (Constant),           */
    150	0xB4,             /*      Pop,                        */
    151	0x95, 0x01,       /*      Report Count (1),           */
    152	0xA4,             /*      Push,                       */
    153	0x55, 0xFD,       /*      Unit Exponent (-3),         */
    154	0x65, 0x13,       /*      Unit (Inch),                */
    155	0x34,             /*      Physical Minimum (0),       */
    156	0x75, 0x10,       /*      Report Size (16),           */
    157	0x09, 0x30,       /*      Usage (X),                  */
    158	0x46, 0x40, 0x1F, /*      Physical Maximum (8000),    */
    159	0x26, 0x00, 0x50, /*      Logical Maximum (20480),    */
    160	0x81, 0x02,       /*      Input (Variable),           */
    161	0x09, 0x31,       /*      Usage (Y),                  */
    162	0x46, 0x70, 0x17, /*      Physical Maximum (6000),    */
    163	0x26, 0x00, 0x3C, /*      Logical Maximum (15360),    */
    164	0x81, 0x02,       /*      Input (Variable),           */
    165	0xB4,             /*      Pop,                        */
    166	0x75, 0x08,       /*      Report Size (8),            */
    167	0x09, 0x38,       /*      Usage (Wheel),              */
    168	0x15, 0xFF,       /*      Logical Minimum (-1),       */
    169	0x25, 0x01,       /*      Logical Maximum (1),        */
    170	0x81, 0x06,       /*      Input (Variable, Relative), */
    171	0x81, 0x01,       /*      Input (Constant),           */
    172	0xC0,             /*    End Collection,               */
    173	0xC0              /*  End Collection                  */
    174};
    175
    176/* Original MousePen i608X v2 report descriptor size */
    177#define MOUSEPEN_I608X_V2_RDESC_ORIG_SIZE	482
    178
    179/* Fixed MousePen i608X v2 report descriptor */
    180static __u8 mousepen_i608x_v2_rdesc_fixed[] = {
    181	0x06, 0x00, 0xFF,             /*  Usage Page (FF00h),             */
    182	0x09, 0x01,                   /*  Usage (01h),                    */
    183	0xA1, 0x01,                   /*  Collection (Application),       */
    184	0x85, 0x05,                   /*    Report ID (5),                */
    185	0x09, 0x01,                   /*    Usage (01h),                  */
    186	0x15, 0x80,                   /*    Logical Minimum (-128),       */
    187	0x25, 0x7F,                   /*    Logical Maximum (127),        */
    188	0x75, 0x08,                   /*    Report Size (8),              */
    189	0x95, 0x07,                   /*    Report Count (7),             */
    190	0xB1, 0x02,                   /*    Feature (Variable),           */
    191	0xC0,                         /*  End Collection,                 */
    192	0x05, 0x0D,                   /*  Usage Page (Digitizer),         */
    193	0x09, 0x01,                   /*  Usage (Digitizer),              */
    194	0xA1, 0x01,                   /*  Collection (Application),       */
    195	0x85, 0x10,                   /*    Report ID (16),               */
    196	0x09, 0x20,                   /*    Usage (Stylus),               */
    197	0xA0,                         /*    Collection (Physical),        */
    198	0x14,                         /*      Logical Minimum (0),        */
    199	0x25, 0x01,                   /*      Logical Maximum (1),        */
    200	0x75, 0x01,                   /*      Report Size (1),            */
    201	0x09, 0x42,                   /*      Usage (Tip Switch),         */
    202	0x09, 0x44,                   /*      Usage (Barrel Switch),      */
    203	0x09, 0x46,                   /*      Usage (Tablet Pick),        */
    204	0x95, 0x03,                   /*      Report Count (3),           */
    205	0x81, 0x02,                   /*      Input (Variable),           */
    206	0x95, 0x04,                   /*      Report Count (4),           */
    207	0x81, 0x03,                   /*      Input (Constant, Variable), */
    208	0x09, 0x32,                   /*      Usage (In Range),           */
    209	0x95, 0x01,                   /*      Report Count (1),           */
    210	0x81, 0x02,                   /*      Input (Variable),           */
    211	0x75, 0x10,                   /*      Report Size (16),           */
    212	0x95, 0x01,                   /*      Report Count (1),           */
    213	0xA4,                         /*      Push,                       */
    214	0x05, 0x01,                   /*      Usage Page (Desktop),       */
    215	0x55, 0xFD,                   /*      Unit Exponent (-3),         */
    216	0x65, 0x13,                   /*      Unit (Inch),                */
    217	0x34,                         /*      Physical Minimum (0),       */
    218	0x09, 0x30,                   /*      Usage (X),                  */
    219	0x46, 0x40, 0x1F,             /*      Physical Maximum (8000),    */
    220	0x27, 0x00, 0xA0, 0x00, 0x00, /*      Logical Maximum (40960),    */
    221	0x81, 0x02,                   /*      Input (Variable),           */
    222	0x09, 0x31,                   /*      Usage (Y),                  */
    223	0x46, 0x70, 0x17,             /*      Physical Maximum (6000),    */
    224	0x26, 0x00, 0x78,             /*      Logical Maximum (30720),    */
    225	0x81, 0x02,                   /*      Input (Variable),           */
    226	0xB4,                         /*      Pop,                        */
    227	0x09, 0x30,                   /*      Usage (Tip Pressure),       */
    228	0x26, 0xFF, 0x07,             /*      Logical Maximum (2047),     */
    229	0x81, 0x02,                   /*      Input (Variable),           */
    230	0xC0,                         /*    End Collection,               */
    231	0xC0,                         /*  End Collection,                 */
    232	0x05, 0x01,                   /*  Usage Page (Desktop),           */
    233	0x09, 0x02,                   /*  Usage (Mouse),                  */
    234	0xA1, 0x01,                   /*  Collection (Application),       */
    235	0x85, 0x11,                   /*    Report ID (17),               */
    236	0x09, 0x01,                   /*    Usage (Pointer),              */
    237	0xA0,                         /*    Collection (Physical),        */
    238	0x14,                         /*      Logical Minimum (0),        */
    239	0xA4,                         /*      Push,                       */
    240	0x05, 0x09,                   /*      Usage Page (Button),        */
    241	0x75, 0x01,                   /*      Report Size (1),            */
    242	0x19, 0x01,                   /*      Usage Minimum (01h),        */
    243	0x29, 0x03,                   /*      Usage Maximum (03h),        */
    244	0x25, 0x01,                   /*      Logical Maximum (1),        */
    245	0x95, 0x03,                   /*      Report Count (3),           */
    246	0x81, 0x02,                   /*      Input (Variable),           */
    247	0x95, 0x05,                   /*      Report Count (5),           */
    248	0x81, 0x01,                   /*      Input (Constant),           */
    249	0xB4,                         /*      Pop,                        */
    250	0x95, 0x01,                   /*      Report Count (1),           */
    251	0xA4,                         /*      Push,                       */
    252	0x55, 0xFD,                   /*      Unit Exponent (-3),         */
    253	0x65, 0x13,                   /*      Unit (Inch),                */
    254	0x34,                         /*      Physical Minimum (0),       */
    255	0x75, 0x10,                   /*      Report Size (16),           */
    256	0x09, 0x30,                   /*      Usage (X),                  */
    257	0x46, 0x40, 0x1F,             /*      Physical Maximum (8000),    */
    258	0x27, 0x00, 0xA0, 0x00, 0x00, /*      Logical Maximum (40960),    */
    259	0x81, 0x02,                   /*      Input (Variable),           */
    260	0x09, 0x31,                   /*      Usage (Y),                  */
    261	0x46, 0x70, 0x17,             /*      Physical Maximum (6000),    */
    262	0x26, 0x00, 0x78,             /*      Logical Maximum (30720),    */
    263	0x81, 0x02,                   /*      Input (Variable),           */
    264	0xB4,                         /*      Pop,                        */
    265	0x75, 0x08,                   /*      Report Size (8),            */
    266	0x09, 0x38,                   /*      Usage (Wheel),              */
    267	0x15, 0xFF,                   /*      Logical Minimum (-1),       */
    268	0x25, 0x01,                   /*      Logical Maximum (1),        */
    269	0x81, 0x06,                   /*      Input (Variable, Relative), */
    270	0x81, 0x01,                   /*      Input (Constant),           */
    271	0xC0,                         /*    End Collection,               */
    272	0xC0                          /*  End Collection                  */
    273};
    274
    275/* Original EasyPen M610X report descriptor size */
    276#define EASYPEN_M610X_RDESC_ORIG_SIZE	476
    277
    278/* Fixed EasyPen M610X report descriptor */
    279static __u8 easypen_m610x_rdesc_fixed[] = {
    280	0x06, 0x00, 0xFF,             /*  Usage Page (FF00h),             */
    281	0x09, 0x01,                   /*  Usage (01h),                    */
    282	0xA1, 0x01,                   /*  Collection (Application),       */
    283	0x85, 0x05,                   /*    Report ID (5),                */
    284	0x09, 0x01,                   /*    Usage (01h),                  */
    285	0x15, 0x80,                   /*    Logical Minimum (-128),       */
    286	0x25, 0x7F,                   /*    Logical Maximum (127),        */
    287	0x75, 0x08,                   /*    Report Size (8),              */
    288	0x95, 0x07,                   /*    Report Count (7),             */
    289	0xB1, 0x02,                   /*    Feature (Variable),           */
    290	0xC0,                         /*  End Collection,                 */
    291	0x05, 0x0D,                   /*  Usage Page (Digitizer),         */
    292	0x09, 0x01,                   /*  Usage (Digitizer),              */
    293	0xA1, 0x01,                   /*  Collection (Application),       */
    294	0x85, 0x10,                   /*    Report ID (16),               */
    295	0x09, 0x20,                   /*    Usage (Stylus),               */
    296	0xA0,                         /*    Collection (Physical),        */
    297	0x14,                         /*      Logical Minimum (0),        */
    298	0x25, 0x01,                   /*      Logical Maximum (1),        */
    299	0x75, 0x01,                   /*      Report Size (1),            */
    300	0x09, 0x42,                   /*      Usage (Tip Switch),         */
    301	0x09, 0x44,                   /*      Usage (Barrel Switch),      */
    302	0x09, 0x46,                   /*      Usage (Tablet Pick),        */
    303	0x95, 0x03,                   /*      Report Count (3),           */
    304	0x81, 0x02,                   /*      Input (Variable),           */
    305	0x95, 0x04,                   /*      Report Count (4),           */
    306	0x81, 0x03,                   /*      Input (Constant, Variable), */
    307	0x09, 0x32,                   /*      Usage (In Range),           */
    308	0x95, 0x01,                   /*      Report Count (1),           */
    309	0x81, 0x02,                   /*      Input (Variable),           */
    310	0x75, 0x10,                   /*      Report Size (16),           */
    311	0x95, 0x01,                   /*      Report Count (1),           */
    312	0xA4,                         /*      Push,                       */
    313	0x05, 0x01,                   /*      Usage Page (Desktop),       */
    314	0x55, 0xFD,                   /*      Unit Exponent (-3),         */
    315	0x65, 0x13,                   /*      Unit (Inch),                */
    316	0x34,                         /*      Physical Minimum (0),       */
    317	0x09, 0x30,                   /*      Usage (X),                  */
    318	0x46, 0x10, 0x27,             /*      Physical Maximum (10000),   */
    319	0x27, 0x00, 0xA0, 0x00, 0x00, /*      Logical Maximum (40960),    */
    320	0x81, 0x02,                   /*      Input (Variable),           */
    321	0x09, 0x31,                   /*      Usage (Y),                  */
    322	0x46, 0x6A, 0x18,             /*      Physical Maximum (6250),    */
    323	0x26, 0x00, 0x64,             /*      Logical Maximum (25600),    */
    324	0x81, 0x02,                   /*      Input (Variable),           */
    325	0xB4,                         /*      Pop,                        */
    326	0x09, 0x30,                   /*      Usage (Tip Pressure),       */
    327	0x26, 0xFF, 0x03,             /*      Logical Maximum (1023),     */
    328	0x81, 0x02,                   /*      Input (Variable),           */
    329	0xC0,                         /*    End Collection,               */
    330	0xC0,                         /*  End Collection,                 */
    331	0x05, 0x0C,                   /*  Usage Page (Consumer),          */
    332	0x09, 0x01,                   /*  Usage (Consumer Control),       */
    333	0xA1, 0x01,                   /*  Collection (Application),       */
    334	0x85, 0x12,                   /*    Report ID (18),               */
    335	0x14,                         /*    Logical Minimum (0),          */
    336	0x25, 0x01,                   /*    Logical Maximum (1),          */
    337	0x75, 0x01,                   /*    Report Size (1),              */
    338	0x95, 0x04,                   /*    Report Count (4),             */
    339	0x0A, 0x1A, 0x02,             /*    Usage (AC Undo),              */
    340	0x0A, 0x79, 0x02,             /*    Usage (AC Redo Or Repeat),    */
    341	0x0A, 0x2D, 0x02,             /*    Usage (AC Zoom In),           */
    342	0x0A, 0x2E, 0x02,             /*    Usage (AC Zoom Out),          */
    343	0x81, 0x02,                   /*    Input (Variable),             */
    344	0x95, 0x01,                   /*    Report Count (1),             */
    345	0x75, 0x14,                   /*    Report Size (20),             */
    346	0x81, 0x03,                   /*    Input (Constant, Variable),   */
    347	0x75, 0x20,                   /*    Report Size (32),             */
    348	0x81, 0x03,                   /*    Input (Constant, Variable),   */
    349	0xC0                          /*  End Collection                  */
    350};
    351
    352
    353/* Original PenSketch M912 report descriptor size */
    354#define PENSKETCH_M912_RDESC_ORIG_SIZE	482
    355
    356/* Fixed PenSketch M912 report descriptor */
    357static __u8 pensketch_m912_rdesc_fixed[] = {
    358	0x05, 0x01,                   /*  Usage Page (Desktop),           */
    359	0x08,                         /*  Usage (00h),                    */
    360	0xA1, 0x01,                   /*  Collection (Application),       */
    361	0x85, 0x05,                   /*    Report ID (5),                */
    362	0x06, 0x00, 0xFF,             /*    Usage Page (FF00h),           */
    363	0x09, 0x01,                   /*    Usage (01h),                  */
    364	0x15, 0x81,                   /*    Logical Minimum (-127),       */
    365	0x25, 0x7F,                   /*    Logical Maximum (127),        */
    366	0x75, 0x08,                   /*    Report Size (8),              */
    367	0x95, 0x07,                   /*    Report Count (7),             */
    368	0xB1, 0x02,                   /*    Feature (Variable),           */
    369	0xC0,                         /*  End Collection,                 */
    370	0x05, 0x0D,                   /*  Usage Page (Digitizer),         */
    371	0x09, 0x01,                   /*  Usage (Digitizer),              */
    372	0xA1, 0x01,                   /*  Collection (Application),       */
    373	0x85, 0x10,                   /*    Report ID (16),               */
    374	0x09, 0x20,                   /*    Usage (Stylus),               */
    375	0xA0,                         /*    Collection (Physical),        */
    376	0x09, 0x42,                   /*      Usage (Tip Switch),         */
    377	0x09, 0x44,                   /*      Usage (Barrel Switch),      */
    378	0x09, 0x46,                   /*      Usage (Tablet Pick),        */
    379	0x14,                         /*      Logical Minimum (0),        */
    380	0x25, 0x01,                   /*      Logical Maximum (1),        */
    381	0x75, 0x01,                   /*      Report Size (1),            */
    382	0x95, 0x03,                   /*      Report Count (3),           */
    383	0x81, 0x02,                   /*      Input (Variable),           */
    384	0x95, 0x04,                   /*      Report Count (4),           */
    385	0x81, 0x03,                   /*      Input (Constant, Variable), */
    386	0x09, 0x32,                   /*      Usage (In Range),           */
    387	0x95, 0x01,                   /*      Report Count (1),           */
    388	0x81, 0x02,                   /*      Input (Variable),           */
    389	0x75, 0x10,                   /*      Report Size (16),           */
    390	0x95, 0x01,                   /*      Report Count (1),           */
    391	0xA4,                         /*      Push,                       */
    392	0x05, 0x01,                   /*      Usage Page (Desktop),       */
    393	0x55, 0xFD,                   /*      Unit Exponent (-3),         */
    394	0x65, 0x13,                   /*      Unit (Inch),                */
    395	0x14,                         /*      Logical Minimum (0),        */
    396	0x34,                         /*      Physical Minimum (0),       */
    397	0x09, 0x30,                   /*      Usage (X),                  */
    398	0x27, 0x00, 0xF0, 0x00, 0x00, /*      Logical Maximum (61440),    */
    399	0x46, 0xE0, 0x2E,             /*      Physical Maximum (12000),   */
    400	0x81, 0x02,                   /*      Input (Variable),           */
    401	0x09, 0x31,                   /*      Usage (Y),                  */
    402	0x27, 0x00, 0xB4, 0x00, 0x00, /*      Logical Maximum (46080),    */
    403	0x46, 0x28, 0x23,             /*      Physical Maximum (9000),    */
    404	0x81, 0x02,                   /*      Input (Variable),           */
    405	0xB4,                         /*      Pop,                        */
    406	0x09, 0x30,                   /*      Usage (Tip Pressure),       */
    407	0x14,                         /*      Logical Minimum (0),        */
    408	0x26, 0xFF, 0x07,             /*      Logical Maximum (2047),     */
    409	0x81, 0x02,                   /*      Input (Variable),           */
    410	0xC0,                         /*    End Collection,               */
    411	0xC0,                         /*  End Collection,                 */
    412	0x05, 0x0D,                   /*  Usage Page (Digitizer),         */
    413	0x09, 0x21,                   /*  Usage (Puck),                   */
    414	0xA1, 0x01,                   /*  Collection (Application),       */
    415	0x85, 0x11,                   /*    Report ID (17),               */
    416	0x09, 0x21,                   /*    Usage (Puck),                 */
    417	0xA0,                         /*    Collection (Physical),        */
    418	0x05, 0x09,                   /*      Usage Page (Button),        */
    419	0x75, 0x01,                   /*      Report Size (1),            */
    420	0x19, 0x01,                   /*      Usage Minimum (01h),        */
    421	0x29, 0x03,                   /*      Usage Maximum (03h),        */
    422	0x14,                         /*      Logical Minimum (0),        */
    423	0x25, 0x01,                   /*      Logical Maximum (1),        */
    424	0x95, 0x03,                   /*      Report Count (3),           */
    425	0x81, 0x02,                   /*      Input (Variable),           */
    426	0x95, 0x04,                   /*      Report Count (4),           */
    427	0x81, 0x01,                   /*      Input (Constant),           */
    428	0x95, 0x01,                   /*      Report Count (1),           */
    429	0x0B, 0x32, 0x00, 0x0D, 0x00, /*      Usage (Digitizer In Range), */
    430	0x14,                         /*      Logical Minimum (0),        */
    431	0x25, 0x01,                   /*      Logical Maximum (1),        */
    432	0x81, 0x02,                   /*      Input (Variable),           */
    433	0xA4,                         /*      Push,                       */
    434	0x05, 0x01,                   /*      Usage Page (Desktop),       */
    435	0x75, 0x10,                   /*      Report Size (16),           */
    436	0x95, 0x01,                   /*      Report Count (1),           */
    437	0x55, 0xFD,                   /*      Unit Exponent (-3),         */
    438	0x65, 0x13,                   /*      Unit (Inch),                */
    439	0x14,                         /*      Logical Minimum (0),        */
    440	0x34,                         /*      Physical Minimum (0),       */
    441	0x09, 0x30,                   /*      Usage (X),                  */
    442	0x27, 0x00, 0xF0, 0x00, 0x00, /*      Logical Maximum (61440),    */
    443	0x46, 0xE0, 0x2E,             /*      Physical Maximum (12000),   */
    444	0x81, 0x02,                   /*      Input (Variable),           */
    445	0x09, 0x31,                   /*      Usage (Y),                  */
    446	0x27, 0x00, 0xB4, 0x00, 0x00, /*      Logical Maximum (46080),    */
    447	0x46, 0x28, 0x23,             /*      Physical Maximum (9000),    */
    448	0x81, 0x02,                   /*      Input (Variable),           */
    449	0x09, 0x38,                   /*      Usage (Wheel),              */
    450	0x75, 0x08,                   /*      Report Size (8),            */
    451	0x95, 0x01,                   /*      Report Count (1),           */
    452	0x15, 0xFF,                   /*      Logical Minimum (-1),       */
    453	0x25, 0x01,                   /*      Logical Maximum (1),        */
    454	0x34,                         /*      Physical Minimum (0),       */
    455	0x44,                         /*      Physical Maximum (0),       */
    456	0x81, 0x06,                   /*      Input (Variable, Relative), */
    457	0xB4,                         /*      Pop,                        */
    458	0xC0,                         /*    End Collection,               */
    459	0xC0,                         /*  End Collection,                 */
    460	0x05, 0x0C,                   /*  Usage Page (Consumer),          */
    461	0x09, 0x01,                   /*  Usage (Consumer Control),       */
    462	0xA1, 0x01,                   /*  Collection (Application),       */
    463	0x85, 0x12,                   /*    Report ID (18),               */
    464	0x14,                         /*    Logical Minimum (0),          */
    465	0x25, 0x01,                   /*    Logical Maximum (1),          */
    466	0x75, 0x01,                   /*    Report Size (1),              */
    467	0x95, 0x08,                   /*    Report Count (8),             */
    468	0x05, 0x0C,                   /*    Usage Page (Consumer),        */
    469	0x0A, 0x6A, 0x02,             /*    Usage (AC Delete),            */
    470	0x0A, 0x1A, 0x02,             /*    Usage (AC Undo),              */
    471	0x0A, 0x01, 0x02,             /*    Usage (AC New),               */
    472	0x0A, 0x2F, 0x02,             /*    Usage (AC Zoom),              */
    473	0x0A, 0x25, 0x02,             /*    Usage (AC Forward),           */
    474	0x0A, 0x24, 0x02,             /*    Usage (AC Back),              */
    475	0x0A, 0x2D, 0x02,             /*    Usage (AC Zoom In),           */
    476	0x0A, 0x2E, 0x02,             /*    Usage (AC Zoom Out),          */
    477	0x81, 0x02,                   /*    Input (Variable),             */
    478	0x95, 0x30,                   /*    Report Count (48),            */
    479	0x81, 0x03,                   /*    Input (Constant, Variable),   */
    480	0xC0                          /*  End Collection                  */
    481};
    482
    483/* Original EasyPen M406XE report descriptor size */
    484#define EASYPEN_M406XE_RDESC_ORIG_SIZE	476
    485
    486/* Fixed EasyPen M406XE  report descriptor */
    487static __u8 easypen_m406xe_rdesc_fixed[] = {
    488	0x05, 0x01,         /*  Usage Page (Desktop),               */
    489	0x09, 0x01,         /*  Usage (01h),                        */
    490	0xA1, 0x01,         /*  Collection (Application),           */
    491	0x85, 0x05,         /*      Report ID (5),                  */
    492	0x09, 0x01,         /*      Usage (01h),                    */
    493	0x15, 0x80,         /*      Logical Minimum (-128),         */
    494	0x25, 0x7F,         /*      Logical Maximum (127),          */
    495	0x75, 0x08,         /*      Report Size (8),                */
    496	0x95, 0x07,         /*      Report Count (7),               */
    497	0xB1, 0x02,         /*      Feature (Variable),             */
    498	0xC0,               /*  End Collection,                     */
    499	0x05, 0x0D,         /*  Usage Page (Digitizer),             */
    500	0x09, 0x01,         /*  Usage (Digitizer),                  */
    501	0xA1, 0x01,         /*  Collection (Application),           */
    502	0x85, 0x10,         /*      Report ID (16),                 */
    503	0x09, 0x20,         /*      Usage (Stylus),                 */
    504	0xA0,               /*      Collection (Physical),          */
    505	0x14,               /*          Logical Minimum (0),        */
    506	0x25, 0x01,         /*          Logical Maximum (1),        */
    507	0x75, 0x01,         /*          Report Size (1),            */
    508	0x09, 0x42,         /*          Usage (Tip Switch),         */
    509	0x09, 0x44,         /*          Usage (Barrel Switch),      */
    510	0x09, 0x46,         /*          Usage (Tablet Pick),        */
    511	0x95, 0x03,         /*          Report Count (3),           */
    512	0x81, 0x02,         /*          Input (Variable),           */
    513	0x95, 0x04,         /*          Report Count (4),           */
    514	0x81, 0x03,         /*          Input (Constant, Variable), */
    515	0x09, 0x32,         /*          Usage (In Range),           */
    516	0x95, 0x01,         /*          Report Count (1),           */
    517	0x81, 0x02,         /*          Input (Variable),           */
    518	0x75, 0x10,         /*          Report Size (16),           */
    519	0x95, 0x01,         /*          Report Count (1),           */
    520	0xA4,               /*          Push,                       */
    521	0x05, 0x01,         /*          Usage Page (Desktop),       */
    522	0x55, 0xFD,         /*          Unit Exponent (-3),         */
    523	0x65, 0x13,         /*          Unit (Inch),                */
    524	0x34,               /*          Physical Minimum (0),       */
    525	0x09, 0x30,         /*          Usage (X),                  */
    526	0x46, 0x70, 0x17,   /*          Physical Maximum (6000),    */
    527	0x26, 0x00, 0x3C,   /*          Logical Maximum (15360),    */
    528	0x81, 0x02,         /*          Input (Variable),           */
    529	0x09, 0x31,         /*          Usage (Y),                  */
    530	0x46, 0xA0, 0x0F,   /*          Physical Maximum (4000),    */
    531	0x26, 0x00, 0x28,   /*          Logical Maximum (10240),    */
    532	0x81, 0x02,         /*          Input (Variable),           */
    533	0xB4,               /*          Pop,                        */
    534	0x09, 0x30,         /*          Usage (Tip Pressure),       */
    535	0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
    536	0x81, 0x02,         /*          Input (Variable),           */
    537	0xC0,               /*      End Collection,                 */
    538	0xC0,               /*  End Collection                      */
    539	0x05, 0x0C,         /*  Usage Page (Consumer),              */
    540	0x09, 0x01,         /*  Usage (Consumer Control),           */
    541	0xA1, 0x01,         /*  Collection (Application),           */
    542	0x85, 0x12,         /*      Report ID (18),                 */
    543	0x14,               /*      Logical Minimum (0),            */
    544	0x25, 0x01,         /*      Logical Maximum (1),            */
    545	0x75, 0x01,         /*      Report Size (1),                */
    546	0x95, 0x04,         /*      Report Count (4),               */
    547	0x0A, 0x79, 0x02,   /*      Usage (AC Redo Or Repeat),      */
    548	0x0A, 0x1A, 0x02,   /*      Usage (AC Undo),                */
    549	0x0A, 0x2D, 0x02,   /*      Usage (AC Zoom In),             */
    550	0x0A, 0x2E, 0x02,   /*      Usage (AC Zoom Out),            */
    551	0x81, 0x02,         /*      Input (Variable),               */
    552	0x95, 0x34,         /*      Report Count (52),              */
    553	0x81, 0x03,         /*      Input (Constant, Variable),     */
    554	0xC0                /*  End Collection                      */
    555};
    556
    557static __u8 *kye_consumer_control_fixup(struct hid_device *hdev, __u8 *rdesc,
    558		unsigned int *rsize, int offset, const char *device_name) {
    559	/*
    560	 * the fixup that need to be done:
    561	 *   - change Usage Maximum in the Consumer Control
    562	 *     (report ID 3) to a reasonable value
    563	 */
    564	if (*rsize >= offset + 31 &&
    565	    /* Usage Page (Consumer Devices) */
    566	    rdesc[offset] == 0x05 && rdesc[offset + 1] == 0x0c &&
    567	    /* Usage (Consumer Control) */
    568	    rdesc[offset + 2] == 0x09 && rdesc[offset + 3] == 0x01 &&
    569	    /*   Usage Maximum > 12287 */
    570	    rdesc[offset + 10] == 0x2a && rdesc[offset + 12] > 0x2f) {
    571		hid_info(hdev, "fixing up %s report descriptor\n", device_name);
    572		rdesc[offset + 12] = 0x2f;
    573	}
    574	return rdesc;
    575}
    576
    577static __u8 *kye_report_fixup(struct hid_device *hdev, __u8 *rdesc,
    578		unsigned int *rsize)
    579{
    580	switch (hdev->product) {
    581	case USB_DEVICE_ID_KYE_ERGO_525V:
    582		/* the fixups that need to be done:
    583		 *   - change led usage page to button for extra buttons
    584		 *   - report size 8 count 1 must be size 1 count 8 for button
    585		 *     bitfield
    586		 *   - change the button usage range to 4-7 for the extra
    587		 *     buttons
    588		 */
    589		if (*rsize >= 75 &&
    590			rdesc[61] == 0x05 && rdesc[62] == 0x08 &&
    591			rdesc[63] == 0x19 && rdesc[64] == 0x08 &&
    592			rdesc[65] == 0x29 && rdesc[66] == 0x0f &&
    593			rdesc[71] == 0x75 && rdesc[72] == 0x08 &&
    594			rdesc[73] == 0x95 && rdesc[74] == 0x01) {
    595			hid_info(hdev,
    596				 "fixing up Kye/Genius Ergo Mouse "
    597				 "report descriptor\n");
    598			rdesc[62] = 0x09;
    599			rdesc[64] = 0x04;
    600			rdesc[66] = 0x07;
    601			rdesc[72] = 0x01;
    602			rdesc[74] = 0x08;
    603		}
    604		break;
    605	case USB_DEVICE_ID_KYE_EASYPEN_I405X:
    606		if (*rsize == EASYPEN_I405X_RDESC_ORIG_SIZE) {
    607			rdesc = easypen_i405x_rdesc_fixed;
    608			*rsize = sizeof(easypen_i405x_rdesc_fixed);
    609		}
    610		break;
    611	case USB_DEVICE_ID_KYE_MOUSEPEN_I608X:
    612		if (*rsize == MOUSEPEN_I608X_RDESC_ORIG_SIZE) {
    613			rdesc = mousepen_i608x_rdesc_fixed;
    614			*rsize = sizeof(mousepen_i608x_rdesc_fixed);
    615		}
    616		break;
    617	case USB_DEVICE_ID_KYE_MOUSEPEN_I608X_V2:
    618		if (*rsize == MOUSEPEN_I608X_V2_RDESC_ORIG_SIZE) {
    619			rdesc = mousepen_i608x_v2_rdesc_fixed;
    620			*rsize = sizeof(mousepen_i608x_v2_rdesc_fixed);
    621		}
    622		break;
    623	case USB_DEVICE_ID_KYE_EASYPEN_M610X:
    624		if (*rsize == EASYPEN_M610X_RDESC_ORIG_SIZE) {
    625			rdesc = easypen_m610x_rdesc_fixed;
    626			*rsize = sizeof(easypen_m610x_rdesc_fixed);
    627		}
    628		break;
    629	case USB_DEVICE_ID_KYE_EASYPEN_M406XE:
    630		if (*rsize == EASYPEN_M406XE_RDESC_ORIG_SIZE) {
    631			rdesc = easypen_m406xe_rdesc_fixed;
    632			*rsize = sizeof(easypen_m406xe_rdesc_fixed);
    633		}
    634		break;
    635	case USB_DEVICE_ID_KYE_PENSKETCH_M912:
    636		if (*rsize == PENSKETCH_M912_RDESC_ORIG_SIZE) {
    637			rdesc = pensketch_m912_rdesc_fixed;
    638			*rsize = sizeof(pensketch_m912_rdesc_fixed);
    639		}
    640		break;
    641	case USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE:
    642		rdesc = kye_consumer_control_fixup(hdev, rdesc, rsize, 104,
    643					"Genius Gila Gaming Mouse");
    644		break;
    645	case USB_DEVICE_ID_GENIUS_GX_IMPERATOR:
    646		rdesc = kye_consumer_control_fixup(hdev, rdesc, rsize, 83,
    647					"Genius Gx Imperator Keyboard");
    648		break;
    649	case USB_DEVICE_ID_GENIUS_MANTICORE:
    650		rdesc = kye_consumer_control_fixup(hdev, rdesc, rsize, 104,
    651					"Genius Manticore Keyboard");
    652		break;
    653	}
    654	return rdesc;
    655}
    656
    657/**
    658 * kye_tablet_enable() - Enable fully-functional tablet mode by setting a special feature report.
    659 *
    660 * @hdev:	HID device
    661 *
    662 * The specific report ID and data were discovered by sniffing the
    663 * Windows driver traffic.
    664 */
    665static int kye_tablet_enable(struct hid_device *hdev)
    666{
    667	struct list_head *list;
    668	struct list_head *head;
    669	struct hid_report *report;
    670	__s32 *value;
    671
    672	list = &hdev->report_enum[HID_FEATURE_REPORT].report_list;
    673	list_for_each(head, list) {
    674		report = list_entry(head, struct hid_report, list);
    675		if (report->id == 5)
    676			break;
    677	}
    678
    679	if (head == list) {
    680		hid_err(hdev, "tablet-enabling feature report not found\n");
    681		return -ENODEV;
    682	}
    683
    684	if (report->maxfield < 1 || report->field[0]->report_count < 7) {
    685		hid_err(hdev, "invalid tablet-enabling feature report\n");
    686		return -ENODEV;
    687	}
    688
    689	value = report->field[0]->value;
    690
    691	value[0] = 0x12;
    692	value[1] = 0x10;
    693	value[2] = 0x11;
    694	value[3] = 0x12;
    695	value[4] = 0x00;
    696	value[5] = 0x00;
    697	value[6] = 0x00;
    698	hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
    699
    700	return 0;
    701}
    702
    703static int kye_probe(struct hid_device *hdev, const struct hid_device_id *id)
    704{
    705	int ret;
    706
    707	ret = hid_parse(hdev);
    708	if (ret) {
    709		hid_err(hdev, "parse failed\n");
    710		goto err;
    711	}
    712
    713	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
    714	if (ret) {
    715		hid_err(hdev, "hw start failed\n");
    716		goto err;
    717	}
    718
    719	switch (id->product) {
    720	case USB_DEVICE_ID_KYE_EASYPEN_I405X:
    721	case USB_DEVICE_ID_KYE_MOUSEPEN_I608X:
    722	case USB_DEVICE_ID_KYE_MOUSEPEN_I608X_V2:
    723	case USB_DEVICE_ID_KYE_EASYPEN_M610X:
    724	case USB_DEVICE_ID_KYE_EASYPEN_M406XE:
    725	case USB_DEVICE_ID_KYE_PENSKETCH_M912:
    726		ret = kye_tablet_enable(hdev);
    727		if (ret) {
    728			hid_err(hdev, "tablet enabling failed\n");
    729			goto enabling_err;
    730		}
    731		break;
    732	case USB_DEVICE_ID_GENIUS_MANTICORE:
    733		/*
    734		 * The manticore keyboard needs to have all the interfaces
    735		 * opened at least once to be fully functional.
    736		 */
    737		if (hid_hw_open(hdev))
    738			hid_hw_close(hdev);
    739		break;
    740	}
    741
    742	return 0;
    743enabling_err:
    744	hid_hw_stop(hdev);
    745err:
    746	return ret;
    747}
    748
    749static const struct hid_device_id kye_devices[] = {
    750	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) },
    751	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE,
    752				USB_DEVICE_ID_KYE_EASYPEN_I405X) },
    753	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE,
    754				USB_DEVICE_ID_KYE_MOUSEPEN_I608X) },
    755	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE,
    756				USB_DEVICE_ID_KYE_MOUSEPEN_I608X_V2) },
    757	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE,
    758				USB_DEVICE_ID_KYE_EASYPEN_M610X) },
    759	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE,
    760				USB_DEVICE_ID_KYE_EASYPEN_M406XE) },
    761	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE,
    762				USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE) },
    763	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE,
    764				USB_DEVICE_ID_GENIUS_GX_IMPERATOR) },
    765	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE,
    766				USB_DEVICE_ID_GENIUS_MANTICORE) },
    767	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE,
    768				USB_DEVICE_ID_KYE_PENSKETCH_M912) },
    769	{ }
    770};
    771MODULE_DEVICE_TABLE(hid, kye_devices);
    772
    773static struct hid_driver kye_driver = {
    774	.name = "kye",
    775	.id_table = kye_devices,
    776	.probe = kye_probe,
    777	.report_fixup = kye_report_fixup,
    778};
    779module_hid_driver(kye_driver);
    780
    781MODULE_LICENSE("GPL");