Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  HID driver for Kye/Genius devices not fully compliant with HID standard
0004  *
0005  *  Copyright (c) 2009 Jiri Kosina
0006  *  Copyright (c) 2009 Tomas Hanak
0007  *  Copyright (c) 2012 Nikolai Kondrashov
0008  */
0009 
0010 /*
0011  */
0012 
0013 #include <linux/device.h>
0014 #include <linux/hid.h>
0015 #include <linux/module.h>
0016 
0017 #include "hid-ids.h"
0018 
0019 /* Original EasyPen i405X report descriptor size */
0020 #define EASYPEN_I405X_RDESC_ORIG_SIZE   476
0021 
0022 /* Fixed EasyPen i405X report descriptor */
0023 static __u8 easypen_i405x_rdesc_fixed[] = {
0024     0x06, 0x00, 0xFF, /*  Usage Page (FF00h),             */
0025     0x09, 0x01,       /*  Usage (01h),                    */
0026     0xA1, 0x01,       /*  Collection (Application),       */
0027     0x85, 0x05,       /*    Report ID (5),                */
0028     0x09, 0x01,       /*    Usage (01h),                  */
0029     0x15, 0x80,       /*    Logical Minimum (-128),       */
0030     0x25, 0x7F,       /*    Logical Maximum (127),        */
0031     0x75, 0x08,       /*    Report Size (8),              */
0032     0x95, 0x07,       /*    Report Count (7),             */
0033     0xB1, 0x02,       /*    Feature (Variable),           */
0034     0xC0,             /*  End Collection,                 */
0035     0x05, 0x0D,       /*  Usage Page (Digitizer),         */
0036     0x09, 0x01,       /*  Usage (Digitizer),              */
0037     0xA1, 0x01,       /*  Collection (Application),       */
0038     0x85, 0x10,       /*    Report ID (16),               */
0039     0x09, 0x20,       /*    Usage (Stylus),               */
0040     0xA0,             /*    Collection (Physical),        */
0041     0x14,             /*      Logical Minimum (0),        */
0042     0x25, 0x01,       /*      Logical Maximum (1),        */
0043     0x75, 0x01,       /*      Report Size (1),            */
0044     0x09, 0x42,       /*      Usage (Tip Switch),         */
0045     0x09, 0x44,       /*      Usage (Barrel Switch),      */
0046     0x09, 0x46,       /*      Usage (Tablet Pick),        */
0047     0x95, 0x03,       /*      Report Count (3),           */
0048     0x81, 0x02,       /*      Input (Variable),           */
0049     0x95, 0x04,       /*      Report Count (4),           */
0050     0x81, 0x03,       /*      Input (Constant, Variable), */
0051     0x09, 0x32,       /*      Usage (In Range),           */
0052     0x95, 0x01,       /*      Report Count (1),           */
0053     0x81, 0x02,       /*      Input (Variable),           */
0054     0x75, 0x10,       /*      Report Size (16),           */
0055     0x95, 0x01,       /*      Report Count (1),           */
0056     0xA4,             /*      Push,                       */
0057     0x05, 0x01,       /*      Usage Page (Desktop),       */
0058     0x55, 0xFD,       /*      Unit Exponent (-3),         */
0059     0x65, 0x13,       /*      Unit (Inch),                */
0060     0x34,             /*      Physical Minimum (0),       */
0061     0x09, 0x30,       /*      Usage (X),                  */
0062     0x46, 0x7C, 0x15, /*      Physical Maximum (5500),    */
0063     0x26, 0x00, 0x37, /*      Logical Maximum (14080),    */
0064     0x81, 0x02,       /*      Input (Variable),           */
0065     0x09, 0x31,       /*      Usage (Y),                  */
0066     0x46, 0xA0, 0x0F, /*      Physical Maximum (4000),    */
0067     0x26, 0x00, 0x28, /*      Logical Maximum (10240),    */
0068     0x81, 0x02,       /*      Input (Variable),           */
0069     0xB4,             /*      Pop,                        */
0070     0x09, 0x30,       /*      Usage (Tip Pressure),       */
0071     0x26, 0xFF, 0x03, /*      Logical Maximum (1023),     */
0072     0x81, 0x02,       /*      Input (Variable),           */
0073     0xC0,             /*    End Collection,               */
0074     0xC0              /*  End Collection                  */
0075 };
0076 
0077 /* Original MousePen i608X report descriptor size */
0078 #define MOUSEPEN_I608X_RDESC_ORIG_SIZE  476
0079 
0080 /* Fixed MousePen i608X report descriptor */
0081 static __u8 mousepen_i608x_rdesc_fixed[] = {
0082     0x06, 0x00, 0xFF, /*  Usage Page (FF00h),             */
0083     0x09, 0x01,       /*  Usage (01h),                    */
0084     0xA1, 0x01,       /*  Collection (Application),       */
0085     0x85, 0x05,       /*    Report ID (5),                */
0086     0x09, 0x01,       /*    Usage (01h),                  */
0087     0x15, 0x80,       /*    Logical Minimum (-128),       */
0088     0x25, 0x7F,       /*    Logical Maximum (127),        */
0089     0x75, 0x08,       /*    Report Size (8),              */
0090     0x95, 0x07,       /*    Report Count (7),             */
0091     0xB1, 0x02,       /*    Feature (Variable),           */
0092     0xC0,             /*  End Collection,                 */
0093     0x05, 0x0D,       /*  Usage Page (Digitizer),         */
0094     0x09, 0x01,       /*  Usage (Digitizer),              */
0095     0xA1, 0x01,       /*  Collection (Application),       */
0096     0x85, 0x10,       /*    Report ID (16),               */
0097     0x09, 0x20,       /*    Usage (Stylus),               */
0098     0xA0,             /*    Collection (Physical),        */
0099     0x14,             /*      Logical Minimum (0),        */
0100     0x25, 0x01,       /*      Logical Maximum (1),        */
0101     0x75, 0x01,       /*      Report Size (1),            */
0102     0x09, 0x42,       /*      Usage (Tip Switch),         */
0103     0x09, 0x44,       /*      Usage (Barrel Switch),      */
0104     0x09, 0x46,       /*      Usage (Tablet Pick),        */
0105     0x95, 0x03,       /*      Report Count (3),           */
0106     0x81, 0x02,       /*      Input (Variable),           */
0107     0x95, 0x04,       /*      Report Count (4),           */
0108     0x81, 0x03,       /*      Input (Constant, Variable), */
0109     0x09, 0x32,       /*      Usage (In Range),           */
0110     0x95, 0x01,       /*      Report Count (1),           */
0111     0x81, 0x02,       /*      Input (Variable),           */
0112     0x75, 0x10,       /*      Report Size (16),           */
0113     0x95, 0x01,       /*      Report Count (1),           */
0114     0xA4,             /*      Push,                       */
0115     0x05, 0x01,       /*      Usage Page (Desktop),       */
0116     0x55, 0xFD,       /*      Unit Exponent (-3),         */
0117     0x65, 0x13,       /*      Unit (Inch),                */
0118     0x34,             /*      Physical Minimum (0),       */
0119     0x09, 0x30,       /*      Usage (X),                  */
0120     0x46, 0x40, 0x1F, /*      Physical Maximum (8000),    */
0121     0x26, 0x00, 0x50, /*      Logical Maximum (20480),    */
0122     0x81, 0x02,       /*      Input (Variable),           */
0123     0x09, 0x31,       /*      Usage (Y),                  */
0124     0x46, 0x70, 0x17, /*      Physical Maximum (6000),    */
0125     0x26, 0x00, 0x3C, /*      Logical Maximum (15360),    */
0126     0x81, 0x02,       /*      Input (Variable),           */
0127     0xB4,             /*      Pop,                        */
0128     0x09, 0x30,       /*      Usage (Tip Pressure),       */
0129     0x26, 0xFF, 0x03, /*      Logical Maximum (1023),     */
0130     0x81, 0x02,       /*      Input (Variable),           */
0131     0xC0,             /*    End Collection,               */
0132     0xC0,             /*  End Collection,                 */
0133     0x05, 0x01,       /*  Usage Page (Desktop),           */
0134     0x09, 0x02,       /*  Usage (Mouse),                  */
0135     0xA1, 0x01,       /*  Collection (Application),       */
0136     0x85, 0x11,       /*    Report ID (17),               */
0137     0x09, 0x01,       /*    Usage (Pointer),              */
0138     0xA0,             /*    Collection (Physical),        */
0139     0x14,             /*      Logical Minimum (0),        */
0140     0xA4,             /*      Push,                       */
0141     0x05, 0x09,       /*      Usage Page (Button),        */
0142     0x75, 0x01,       /*      Report Size (1),            */
0143     0x19, 0x01,       /*      Usage Minimum (01h),        */
0144     0x29, 0x03,       /*      Usage Maximum (03h),        */
0145     0x25, 0x01,       /*      Logical Maximum (1),        */
0146     0x95, 0x03,       /*      Report Count (3),           */
0147     0x81, 0x02,       /*      Input (Variable),           */
0148     0x95, 0x05,       /*      Report Count (5),           */
0149     0x81, 0x01,       /*      Input (Constant),           */
0150     0xB4,             /*      Pop,                        */
0151     0x95, 0x01,       /*      Report Count (1),           */
0152     0xA4,             /*      Push,                       */
0153     0x55, 0xFD,       /*      Unit Exponent (-3),         */
0154     0x65, 0x13,       /*      Unit (Inch),                */
0155     0x34,             /*      Physical Minimum (0),       */
0156     0x75, 0x10,       /*      Report Size (16),           */
0157     0x09, 0x30,       /*      Usage (X),                  */
0158     0x46, 0x40, 0x1F, /*      Physical Maximum (8000),    */
0159     0x26, 0x00, 0x50, /*      Logical Maximum (20480),    */
0160     0x81, 0x02,       /*      Input (Variable),           */
0161     0x09, 0x31,       /*      Usage (Y),                  */
0162     0x46, 0x70, 0x17, /*      Physical Maximum (6000),    */
0163     0x26, 0x00, 0x3C, /*      Logical Maximum (15360),    */
0164     0x81, 0x02,       /*      Input (Variable),           */
0165     0xB4,             /*      Pop,                        */
0166     0x75, 0x08,       /*      Report Size (8),            */
0167     0x09, 0x38,       /*      Usage (Wheel),              */
0168     0x15, 0xFF,       /*      Logical Minimum (-1),       */
0169     0x25, 0x01,       /*      Logical Maximum (1),        */
0170     0x81, 0x06,       /*      Input (Variable, Relative), */
0171     0x81, 0x01,       /*      Input (Constant),           */
0172     0xC0,             /*    End Collection,               */
0173     0xC0              /*  End Collection                  */
0174 };
0175 
0176 /* Original MousePen i608X v2 report descriptor size */
0177 #define MOUSEPEN_I608X_V2_RDESC_ORIG_SIZE   482
0178 
0179 /* Fixed MousePen i608X v2 report descriptor */
0180 static __u8 mousepen_i608x_v2_rdesc_fixed[] = {
0181     0x06, 0x00, 0xFF,             /*  Usage Page (FF00h),             */
0182     0x09, 0x01,                   /*  Usage (01h),                    */
0183     0xA1, 0x01,                   /*  Collection (Application),       */
0184     0x85, 0x05,                   /*    Report ID (5),                */
0185     0x09, 0x01,                   /*    Usage (01h),                  */
0186     0x15, 0x80,                   /*    Logical Minimum (-128),       */
0187     0x25, 0x7F,                   /*    Logical Maximum (127),        */
0188     0x75, 0x08,                   /*    Report Size (8),              */
0189     0x95, 0x07,                   /*    Report Count (7),             */
0190     0xB1, 0x02,                   /*    Feature (Variable),           */
0191     0xC0,                         /*  End Collection,                 */
0192     0x05, 0x0D,                   /*  Usage Page (Digitizer),         */
0193     0x09, 0x01,                   /*  Usage (Digitizer),              */
0194     0xA1, 0x01,                   /*  Collection (Application),       */
0195     0x85, 0x10,                   /*    Report ID (16),               */
0196     0x09, 0x20,                   /*    Usage (Stylus),               */
0197     0xA0,                         /*    Collection (Physical),        */
0198     0x14,                         /*      Logical Minimum (0),        */
0199     0x25, 0x01,                   /*      Logical Maximum (1),        */
0200     0x75, 0x01,                   /*      Report Size (1),            */
0201     0x09, 0x42,                   /*      Usage (Tip Switch),         */
0202     0x09, 0x44,                   /*      Usage (Barrel Switch),      */
0203     0x09, 0x46,                   /*      Usage (Tablet Pick),        */
0204     0x95, 0x03,                   /*      Report Count (3),           */
0205     0x81, 0x02,                   /*      Input (Variable),           */
0206     0x95, 0x04,                   /*      Report Count (4),           */
0207     0x81, 0x03,                   /*      Input (Constant, Variable), */
0208     0x09, 0x32,                   /*      Usage (In Range),           */
0209     0x95, 0x01,                   /*      Report Count (1),           */
0210     0x81, 0x02,                   /*      Input (Variable),           */
0211     0x75, 0x10,                   /*      Report Size (16),           */
0212     0x95, 0x01,                   /*      Report Count (1),           */
0213     0xA4,                         /*      Push,                       */
0214     0x05, 0x01,                   /*      Usage Page (Desktop),       */
0215     0x55, 0xFD,                   /*      Unit Exponent (-3),         */
0216     0x65, 0x13,                   /*      Unit (Inch),                */
0217     0x34,                         /*      Physical Minimum (0),       */
0218     0x09, 0x30,                   /*      Usage (X),                  */
0219     0x46, 0x40, 0x1F,             /*      Physical Maximum (8000),    */
0220     0x27, 0x00, 0xA0, 0x00, 0x00, /*      Logical Maximum (40960),    */
0221     0x81, 0x02,                   /*      Input (Variable),           */
0222     0x09, 0x31,                   /*      Usage (Y),                  */
0223     0x46, 0x70, 0x17,             /*      Physical Maximum (6000),    */
0224     0x26, 0x00, 0x78,             /*      Logical Maximum (30720),    */
0225     0x81, 0x02,                   /*      Input (Variable),           */
0226     0xB4,                         /*      Pop,                        */
0227     0x09, 0x30,                   /*      Usage (Tip Pressure),       */
0228     0x26, 0xFF, 0x07,             /*      Logical Maximum (2047),     */
0229     0x81, 0x02,                   /*      Input (Variable),           */
0230     0xC0,                         /*    End Collection,               */
0231     0xC0,                         /*  End Collection,                 */
0232     0x05, 0x01,                   /*  Usage Page (Desktop),           */
0233     0x09, 0x02,                   /*  Usage (Mouse),                  */
0234     0xA1, 0x01,                   /*  Collection (Application),       */
0235     0x85, 0x11,                   /*    Report ID (17),               */
0236     0x09, 0x01,                   /*    Usage (Pointer),              */
0237     0xA0,                         /*    Collection (Physical),        */
0238     0x14,                         /*      Logical Minimum (0),        */
0239     0xA4,                         /*      Push,                       */
0240     0x05, 0x09,                   /*      Usage Page (Button),        */
0241     0x75, 0x01,                   /*      Report Size (1),            */
0242     0x19, 0x01,                   /*      Usage Minimum (01h),        */
0243     0x29, 0x03,                   /*      Usage Maximum (03h),        */
0244     0x25, 0x01,                   /*      Logical Maximum (1),        */
0245     0x95, 0x03,                   /*      Report Count (3),           */
0246     0x81, 0x02,                   /*      Input (Variable),           */
0247     0x95, 0x05,                   /*      Report Count (5),           */
0248     0x81, 0x01,                   /*      Input (Constant),           */
0249     0xB4,                         /*      Pop,                        */
0250     0x95, 0x01,                   /*      Report Count (1),           */
0251     0xA4,                         /*      Push,                       */
0252     0x55, 0xFD,                   /*      Unit Exponent (-3),         */
0253     0x65, 0x13,                   /*      Unit (Inch),                */
0254     0x34,                         /*      Physical Minimum (0),       */
0255     0x75, 0x10,                   /*      Report Size (16),           */
0256     0x09, 0x30,                   /*      Usage (X),                  */
0257     0x46, 0x40, 0x1F,             /*      Physical Maximum (8000),    */
0258     0x27, 0x00, 0xA0, 0x00, 0x00, /*      Logical Maximum (40960),    */
0259     0x81, 0x02,                   /*      Input (Variable),           */
0260     0x09, 0x31,                   /*      Usage (Y),                  */
0261     0x46, 0x70, 0x17,             /*      Physical Maximum (6000),    */
0262     0x26, 0x00, 0x78,             /*      Logical Maximum (30720),    */
0263     0x81, 0x02,                   /*      Input (Variable),           */
0264     0xB4,                         /*      Pop,                        */
0265     0x75, 0x08,                   /*      Report Size (8),            */
0266     0x09, 0x38,                   /*      Usage (Wheel),              */
0267     0x15, 0xFF,                   /*      Logical Minimum (-1),       */
0268     0x25, 0x01,                   /*      Logical Maximum (1),        */
0269     0x81, 0x06,                   /*      Input (Variable, Relative), */
0270     0x81, 0x01,                   /*      Input (Constant),           */
0271     0xC0,                         /*    End Collection,               */
0272     0xC0                          /*  End Collection                  */
0273 };
0274 
0275 /* Original EasyPen M610X report descriptor size */
0276 #define EASYPEN_M610X_RDESC_ORIG_SIZE   476
0277 
0278 /* Fixed EasyPen M610X report descriptor */
0279 static __u8 easypen_m610x_rdesc_fixed[] = {
0280     0x06, 0x00, 0xFF,             /*  Usage Page (FF00h),             */
0281     0x09, 0x01,                   /*  Usage (01h),                    */
0282     0xA1, 0x01,                   /*  Collection (Application),       */
0283     0x85, 0x05,                   /*    Report ID (5),                */
0284     0x09, 0x01,                   /*    Usage (01h),                  */
0285     0x15, 0x80,                   /*    Logical Minimum (-128),       */
0286     0x25, 0x7F,                   /*    Logical Maximum (127),        */
0287     0x75, 0x08,                   /*    Report Size (8),              */
0288     0x95, 0x07,                   /*    Report Count (7),             */
0289     0xB1, 0x02,                   /*    Feature (Variable),           */
0290     0xC0,                         /*  End Collection,                 */
0291     0x05, 0x0D,                   /*  Usage Page (Digitizer),         */
0292     0x09, 0x01,                   /*  Usage (Digitizer),              */
0293     0xA1, 0x01,                   /*  Collection (Application),       */
0294     0x85, 0x10,                   /*    Report ID (16),               */
0295     0x09, 0x20,                   /*    Usage (Stylus),               */
0296     0xA0,                         /*    Collection (Physical),        */
0297     0x14,                         /*      Logical Minimum (0),        */
0298     0x25, 0x01,                   /*      Logical Maximum (1),        */
0299     0x75, 0x01,                   /*      Report Size (1),            */
0300     0x09, 0x42,                   /*      Usage (Tip Switch),         */
0301     0x09, 0x44,                   /*      Usage (Barrel Switch),      */
0302     0x09, 0x46,                   /*      Usage (Tablet Pick),        */
0303     0x95, 0x03,                   /*      Report Count (3),           */
0304     0x81, 0x02,                   /*      Input (Variable),           */
0305     0x95, 0x04,                   /*      Report Count (4),           */
0306     0x81, 0x03,                   /*      Input (Constant, Variable), */
0307     0x09, 0x32,                   /*      Usage (In Range),           */
0308     0x95, 0x01,                   /*      Report Count (1),           */
0309     0x81, 0x02,                   /*      Input (Variable),           */
0310     0x75, 0x10,                   /*      Report Size (16),           */
0311     0x95, 0x01,                   /*      Report Count (1),           */
0312     0xA4,                         /*      Push,                       */
0313     0x05, 0x01,                   /*      Usage Page (Desktop),       */
0314     0x55, 0xFD,                   /*      Unit Exponent (-3),         */
0315     0x65, 0x13,                   /*      Unit (Inch),                */
0316     0x34,                         /*      Physical Minimum (0),       */
0317     0x09, 0x30,                   /*      Usage (X),                  */
0318     0x46, 0x10, 0x27,             /*      Physical Maximum (10000),   */
0319     0x27, 0x00, 0xA0, 0x00, 0x00, /*      Logical Maximum (40960),    */
0320     0x81, 0x02,                   /*      Input (Variable),           */
0321     0x09, 0x31,                   /*      Usage (Y),                  */
0322     0x46, 0x6A, 0x18,             /*      Physical Maximum (6250),    */
0323     0x26, 0x00, 0x64,             /*      Logical Maximum (25600),    */
0324     0x81, 0x02,                   /*      Input (Variable),           */
0325     0xB4,                         /*      Pop,                        */
0326     0x09, 0x30,                   /*      Usage (Tip Pressure),       */
0327     0x26, 0xFF, 0x03,             /*      Logical Maximum (1023),     */
0328     0x81, 0x02,                   /*      Input (Variable),           */
0329     0xC0,                         /*    End Collection,               */
0330     0xC0,                         /*  End Collection,                 */
0331     0x05, 0x0C,                   /*  Usage Page (Consumer),          */
0332     0x09, 0x01,                   /*  Usage (Consumer Control),       */
0333     0xA1, 0x01,                   /*  Collection (Application),       */
0334     0x85, 0x12,                   /*    Report ID (18),               */
0335     0x14,                         /*    Logical Minimum (0),          */
0336     0x25, 0x01,                   /*    Logical Maximum (1),          */
0337     0x75, 0x01,                   /*    Report Size (1),              */
0338     0x95, 0x04,                   /*    Report Count (4),             */
0339     0x0A, 0x1A, 0x02,             /*    Usage (AC Undo),              */
0340     0x0A, 0x79, 0x02,             /*    Usage (AC Redo Or Repeat),    */
0341     0x0A, 0x2D, 0x02,             /*    Usage (AC Zoom In),           */
0342     0x0A, 0x2E, 0x02,             /*    Usage (AC Zoom Out),          */
0343     0x81, 0x02,                   /*    Input (Variable),             */
0344     0x95, 0x01,                   /*    Report Count (1),             */
0345     0x75, 0x14,                   /*    Report Size (20),             */
0346     0x81, 0x03,                   /*    Input (Constant, Variable),   */
0347     0x75, 0x20,                   /*    Report Size (32),             */
0348     0x81, 0x03,                   /*    Input (Constant, Variable),   */
0349     0xC0                          /*  End Collection                  */
0350 };
0351 
0352 
0353 /* Original PenSketch M912 report descriptor size */
0354 #define PENSKETCH_M912_RDESC_ORIG_SIZE  482
0355 
0356 /* Fixed PenSketch M912 report descriptor */
0357 static __u8 pensketch_m912_rdesc_fixed[] = {
0358     0x05, 0x01,                   /*  Usage Page (Desktop),           */
0359     0x08,                         /*  Usage (00h),                    */
0360     0xA1, 0x01,                   /*  Collection (Application),       */
0361     0x85, 0x05,                   /*    Report ID (5),                */
0362     0x06, 0x00, 0xFF,             /*    Usage Page (FF00h),           */
0363     0x09, 0x01,                   /*    Usage (01h),                  */
0364     0x15, 0x81,                   /*    Logical Minimum (-127),       */
0365     0x25, 0x7F,                   /*    Logical Maximum (127),        */
0366     0x75, 0x08,                   /*    Report Size (8),              */
0367     0x95, 0x07,                   /*    Report Count (7),             */
0368     0xB1, 0x02,                   /*    Feature (Variable),           */
0369     0xC0,                         /*  End Collection,                 */
0370     0x05, 0x0D,                   /*  Usage Page (Digitizer),         */
0371     0x09, 0x01,                   /*  Usage (Digitizer),              */
0372     0xA1, 0x01,                   /*  Collection (Application),       */
0373     0x85, 0x10,                   /*    Report ID (16),               */
0374     0x09, 0x20,                   /*    Usage (Stylus),               */
0375     0xA0,                         /*    Collection (Physical),        */
0376     0x09, 0x42,                   /*      Usage (Tip Switch),         */
0377     0x09, 0x44,                   /*      Usage (Barrel Switch),      */
0378     0x09, 0x46,                   /*      Usage (Tablet Pick),        */
0379     0x14,                         /*      Logical Minimum (0),        */
0380     0x25, 0x01,                   /*      Logical Maximum (1),        */
0381     0x75, 0x01,                   /*      Report Size (1),            */
0382     0x95, 0x03,                   /*      Report Count (3),           */
0383     0x81, 0x02,                   /*      Input (Variable),           */
0384     0x95, 0x04,                   /*      Report Count (4),           */
0385     0x81, 0x03,                   /*      Input (Constant, Variable), */
0386     0x09, 0x32,                   /*      Usage (In Range),           */
0387     0x95, 0x01,                   /*      Report Count (1),           */
0388     0x81, 0x02,                   /*      Input (Variable),           */
0389     0x75, 0x10,                   /*      Report Size (16),           */
0390     0x95, 0x01,                   /*      Report Count (1),           */
0391     0xA4,                         /*      Push,                       */
0392     0x05, 0x01,                   /*      Usage Page (Desktop),       */
0393     0x55, 0xFD,                   /*      Unit Exponent (-3),         */
0394     0x65, 0x13,                   /*      Unit (Inch),                */
0395     0x14,                         /*      Logical Minimum (0),        */
0396     0x34,                         /*      Physical Minimum (0),       */
0397     0x09, 0x30,                   /*      Usage (X),                  */
0398     0x27, 0x00, 0xF0, 0x00, 0x00, /*      Logical Maximum (61440),    */
0399     0x46, 0xE0, 0x2E,             /*      Physical Maximum (12000),   */
0400     0x81, 0x02,                   /*      Input (Variable),           */
0401     0x09, 0x31,                   /*      Usage (Y),                  */
0402     0x27, 0x00, 0xB4, 0x00, 0x00, /*      Logical Maximum (46080),    */
0403     0x46, 0x28, 0x23,             /*      Physical Maximum (9000),    */
0404     0x81, 0x02,                   /*      Input (Variable),           */
0405     0xB4,                         /*      Pop,                        */
0406     0x09, 0x30,                   /*      Usage (Tip Pressure),       */
0407     0x14,                         /*      Logical Minimum (0),        */
0408     0x26, 0xFF, 0x07,             /*      Logical Maximum (2047),     */
0409     0x81, 0x02,                   /*      Input (Variable),           */
0410     0xC0,                         /*    End Collection,               */
0411     0xC0,                         /*  End Collection,                 */
0412     0x05, 0x0D,                   /*  Usage Page (Digitizer),         */
0413     0x09, 0x21,                   /*  Usage (Puck),                   */
0414     0xA1, 0x01,                   /*  Collection (Application),       */
0415     0x85, 0x11,                   /*    Report ID (17),               */
0416     0x09, 0x21,                   /*    Usage (Puck),                 */
0417     0xA0,                         /*    Collection (Physical),        */
0418     0x05, 0x09,                   /*      Usage Page (Button),        */
0419     0x75, 0x01,                   /*      Report Size (1),            */
0420     0x19, 0x01,                   /*      Usage Minimum (01h),        */
0421     0x29, 0x03,                   /*      Usage Maximum (03h),        */
0422     0x14,                         /*      Logical Minimum (0),        */
0423     0x25, 0x01,                   /*      Logical Maximum (1),        */
0424     0x95, 0x03,                   /*      Report Count (3),           */
0425     0x81, 0x02,                   /*      Input (Variable),           */
0426     0x95, 0x04,                   /*      Report Count (4),           */
0427     0x81, 0x01,                   /*      Input (Constant),           */
0428     0x95, 0x01,                   /*      Report Count (1),           */
0429     0x0B, 0x32, 0x00, 0x0D, 0x00, /*      Usage (Digitizer In Range), */
0430     0x14,                         /*      Logical Minimum (0),        */
0431     0x25, 0x01,                   /*      Logical Maximum (1),        */
0432     0x81, 0x02,                   /*      Input (Variable),           */
0433     0xA4,                         /*      Push,                       */
0434     0x05, 0x01,                   /*      Usage Page (Desktop),       */
0435     0x75, 0x10,                   /*      Report Size (16),           */
0436     0x95, 0x01,                   /*      Report Count (1),           */
0437     0x55, 0xFD,                   /*      Unit Exponent (-3),         */
0438     0x65, 0x13,                   /*      Unit (Inch),                */
0439     0x14,                         /*      Logical Minimum (0),        */
0440     0x34,                         /*      Physical Minimum (0),       */
0441     0x09, 0x30,                   /*      Usage (X),                  */
0442     0x27, 0x00, 0xF0, 0x00, 0x00, /*      Logical Maximum (61440),    */
0443     0x46, 0xE0, 0x2E,             /*      Physical Maximum (12000),   */
0444     0x81, 0x02,                   /*      Input (Variable),           */
0445     0x09, 0x31,                   /*      Usage (Y),                  */
0446     0x27, 0x00, 0xB4, 0x00, 0x00, /*      Logical Maximum (46080),    */
0447     0x46, 0x28, 0x23,             /*      Physical Maximum (9000),    */
0448     0x81, 0x02,                   /*      Input (Variable),           */
0449     0x09, 0x38,                   /*      Usage (Wheel),              */
0450     0x75, 0x08,                   /*      Report Size (8),            */
0451     0x95, 0x01,                   /*      Report Count (1),           */
0452     0x15, 0xFF,                   /*      Logical Minimum (-1),       */
0453     0x25, 0x01,                   /*      Logical Maximum (1),        */
0454     0x34,                         /*      Physical Minimum (0),       */
0455     0x44,                         /*      Physical Maximum (0),       */
0456     0x81, 0x06,                   /*      Input (Variable, Relative), */
0457     0xB4,                         /*      Pop,                        */
0458     0xC0,                         /*    End Collection,               */
0459     0xC0,                         /*  End Collection,                 */
0460     0x05, 0x0C,                   /*  Usage Page (Consumer),          */
0461     0x09, 0x01,                   /*  Usage (Consumer Control),       */
0462     0xA1, 0x01,                   /*  Collection (Application),       */
0463     0x85, 0x12,                   /*    Report ID (18),               */
0464     0x14,                         /*    Logical Minimum (0),          */
0465     0x25, 0x01,                   /*    Logical Maximum (1),          */
0466     0x75, 0x01,                   /*    Report Size (1),              */
0467     0x95, 0x08,                   /*    Report Count (8),             */
0468     0x05, 0x0C,                   /*    Usage Page (Consumer),        */
0469     0x0A, 0x6A, 0x02,             /*    Usage (AC Delete),            */
0470     0x0A, 0x1A, 0x02,             /*    Usage (AC Undo),              */
0471     0x0A, 0x01, 0x02,             /*    Usage (AC New),               */
0472     0x0A, 0x2F, 0x02,             /*    Usage (AC Zoom),              */
0473     0x0A, 0x25, 0x02,             /*    Usage (AC Forward),           */
0474     0x0A, 0x24, 0x02,             /*    Usage (AC Back),              */
0475     0x0A, 0x2D, 0x02,             /*    Usage (AC Zoom In),           */
0476     0x0A, 0x2E, 0x02,             /*    Usage (AC Zoom Out),          */
0477     0x81, 0x02,                   /*    Input (Variable),             */
0478     0x95, 0x30,                   /*    Report Count (48),            */
0479     0x81, 0x03,                   /*    Input (Constant, Variable),   */
0480     0xC0                          /*  End Collection                  */
0481 };
0482 
0483 /* Original EasyPen M406XE report descriptor size */
0484 #define EASYPEN_M406XE_RDESC_ORIG_SIZE  476
0485 
0486 /* Fixed EasyPen M406XE  report descriptor */
0487 static __u8 easypen_m406xe_rdesc_fixed[] = {
0488     0x05, 0x01,         /*  Usage Page (Desktop),               */
0489     0x09, 0x01,         /*  Usage (01h),                        */
0490     0xA1, 0x01,         /*  Collection (Application),           */
0491     0x85, 0x05,         /*      Report ID (5),                  */
0492     0x09, 0x01,         /*      Usage (01h),                    */
0493     0x15, 0x80,         /*      Logical Minimum (-128),         */
0494     0x25, 0x7F,         /*      Logical Maximum (127),          */
0495     0x75, 0x08,         /*      Report Size (8),                */
0496     0x95, 0x07,         /*      Report Count (7),               */
0497     0xB1, 0x02,         /*      Feature (Variable),             */
0498     0xC0,               /*  End Collection,                     */
0499     0x05, 0x0D,         /*  Usage Page (Digitizer),             */
0500     0x09, 0x01,         /*  Usage (Digitizer),                  */
0501     0xA1, 0x01,         /*  Collection (Application),           */
0502     0x85, 0x10,         /*      Report ID (16),                 */
0503     0x09, 0x20,         /*      Usage (Stylus),                 */
0504     0xA0,               /*      Collection (Physical),          */
0505     0x14,               /*          Logical Minimum (0),        */
0506     0x25, 0x01,         /*          Logical Maximum (1),        */
0507     0x75, 0x01,         /*          Report Size (1),            */
0508     0x09, 0x42,         /*          Usage (Tip Switch),         */
0509     0x09, 0x44,         /*          Usage (Barrel Switch),      */
0510     0x09, 0x46,         /*          Usage (Tablet Pick),        */
0511     0x95, 0x03,         /*          Report Count (3),           */
0512     0x81, 0x02,         /*          Input (Variable),           */
0513     0x95, 0x04,         /*          Report Count (4),           */
0514     0x81, 0x03,         /*          Input (Constant, Variable), */
0515     0x09, 0x32,         /*          Usage (In Range),           */
0516     0x95, 0x01,         /*          Report Count (1),           */
0517     0x81, 0x02,         /*          Input (Variable),           */
0518     0x75, 0x10,         /*          Report Size (16),           */
0519     0x95, 0x01,         /*          Report Count (1),           */
0520     0xA4,               /*          Push,                       */
0521     0x05, 0x01,         /*          Usage Page (Desktop),       */
0522     0x55, 0xFD,         /*          Unit Exponent (-3),         */
0523     0x65, 0x13,         /*          Unit (Inch),                */
0524     0x34,               /*          Physical Minimum (0),       */
0525     0x09, 0x30,         /*          Usage (X),                  */
0526     0x46, 0x70, 0x17,   /*          Physical Maximum (6000),    */
0527     0x26, 0x00, 0x3C,   /*          Logical Maximum (15360),    */
0528     0x81, 0x02,         /*          Input (Variable),           */
0529     0x09, 0x31,         /*          Usage (Y),                  */
0530     0x46, 0xA0, 0x0F,   /*          Physical Maximum (4000),    */
0531     0x26, 0x00, 0x28,   /*          Logical Maximum (10240),    */
0532     0x81, 0x02,         /*          Input (Variable),           */
0533     0xB4,               /*          Pop,                        */
0534     0x09, 0x30,         /*          Usage (Tip Pressure),       */
0535     0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
0536     0x81, 0x02,         /*          Input (Variable),           */
0537     0xC0,               /*      End Collection,                 */
0538     0xC0,               /*  End Collection                      */
0539     0x05, 0x0C,         /*  Usage Page (Consumer),              */
0540     0x09, 0x01,         /*  Usage (Consumer Control),           */
0541     0xA1, 0x01,         /*  Collection (Application),           */
0542     0x85, 0x12,         /*      Report ID (18),                 */
0543     0x14,               /*      Logical Minimum (0),            */
0544     0x25, 0x01,         /*      Logical Maximum (1),            */
0545     0x75, 0x01,         /*      Report Size (1),                */
0546     0x95, 0x04,         /*      Report Count (4),               */
0547     0x0A, 0x79, 0x02,   /*      Usage (AC Redo Or Repeat),      */
0548     0x0A, 0x1A, 0x02,   /*      Usage (AC Undo),                */
0549     0x0A, 0x2D, 0x02,   /*      Usage (AC Zoom In),             */
0550     0x0A, 0x2E, 0x02,   /*      Usage (AC Zoom Out),            */
0551     0x81, 0x02,         /*      Input (Variable),               */
0552     0x95, 0x34,         /*      Report Count (52),              */
0553     0x81, 0x03,         /*      Input (Constant, Variable),     */
0554     0xC0                /*  End Collection                      */
0555 };
0556 
0557 static __u8 *kye_consumer_control_fixup(struct hid_device *hdev, __u8 *rdesc,
0558         unsigned int *rsize, int offset, const char *device_name) {
0559     /*
0560      * the fixup that need to be done:
0561      *   - change Usage Maximum in the Consumer Control
0562      *     (report ID 3) to a reasonable value
0563      */
0564     if (*rsize >= offset + 31 &&
0565         /* Usage Page (Consumer Devices) */
0566         rdesc[offset] == 0x05 && rdesc[offset + 1] == 0x0c &&
0567         /* Usage (Consumer Control) */
0568         rdesc[offset + 2] == 0x09 && rdesc[offset + 3] == 0x01 &&
0569         /*   Usage Maximum > 12287 */
0570         rdesc[offset + 10] == 0x2a && rdesc[offset + 12] > 0x2f) {
0571         hid_info(hdev, "fixing up %s report descriptor\n", device_name);
0572         rdesc[offset + 12] = 0x2f;
0573     }
0574     return rdesc;
0575 }
0576 
0577 static __u8 *kye_report_fixup(struct hid_device *hdev, __u8 *rdesc,
0578         unsigned int *rsize)
0579 {
0580     switch (hdev->product) {
0581     case USB_DEVICE_ID_KYE_ERGO_525V:
0582         /* the fixups that need to be done:
0583          *   - change led usage page to button for extra buttons
0584          *   - report size 8 count 1 must be size 1 count 8 for button
0585          *     bitfield
0586          *   - change the button usage range to 4-7 for the extra
0587          *     buttons
0588          */
0589         if (*rsize >= 75 &&
0590             rdesc[61] == 0x05 && rdesc[62] == 0x08 &&
0591             rdesc[63] == 0x19 && rdesc[64] == 0x08 &&
0592             rdesc[65] == 0x29 && rdesc[66] == 0x0f &&
0593             rdesc[71] == 0x75 && rdesc[72] == 0x08 &&
0594             rdesc[73] == 0x95 && rdesc[74] == 0x01) {
0595             hid_info(hdev,
0596                  "fixing up Kye/Genius Ergo Mouse "
0597                  "report descriptor\n");
0598             rdesc[62] = 0x09;
0599             rdesc[64] = 0x04;
0600             rdesc[66] = 0x07;
0601             rdesc[72] = 0x01;
0602             rdesc[74] = 0x08;
0603         }
0604         break;
0605     case USB_DEVICE_ID_KYE_EASYPEN_I405X:
0606         if (*rsize == EASYPEN_I405X_RDESC_ORIG_SIZE) {
0607             rdesc = easypen_i405x_rdesc_fixed;
0608             *rsize = sizeof(easypen_i405x_rdesc_fixed);
0609         }
0610         break;
0611     case USB_DEVICE_ID_KYE_MOUSEPEN_I608X:
0612         if (*rsize == MOUSEPEN_I608X_RDESC_ORIG_SIZE) {
0613             rdesc = mousepen_i608x_rdesc_fixed;
0614             *rsize = sizeof(mousepen_i608x_rdesc_fixed);
0615         }
0616         break;
0617     case USB_DEVICE_ID_KYE_MOUSEPEN_I608X_V2:
0618         if (*rsize == MOUSEPEN_I608X_V2_RDESC_ORIG_SIZE) {
0619             rdesc = mousepen_i608x_v2_rdesc_fixed;
0620             *rsize = sizeof(mousepen_i608x_v2_rdesc_fixed);
0621         }
0622         break;
0623     case USB_DEVICE_ID_KYE_EASYPEN_M610X:
0624         if (*rsize == EASYPEN_M610X_RDESC_ORIG_SIZE) {
0625             rdesc = easypen_m610x_rdesc_fixed;
0626             *rsize = sizeof(easypen_m610x_rdesc_fixed);
0627         }
0628         break;
0629     case USB_DEVICE_ID_KYE_EASYPEN_M406XE:
0630         if (*rsize == EASYPEN_M406XE_RDESC_ORIG_SIZE) {
0631             rdesc = easypen_m406xe_rdesc_fixed;
0632             *rsize = sizeof(easypen_m406xe_rdesc_fixed);
0633         }
0634         break;
0635     case USB_DEVICE_ID_KYE_PENSKETCH_M912:
0636         if (*rsize == PENSKETCH_M912_RDESC_ORIG_SIZE) {
0637             rdesc = pensketch_m912_rdesc_fixed;
0638             *rsize = sizeof(pensketch_m912_rdesc_fixed);
0639         }
0640         break;
0641     case USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE:
0642         rdesc = kye_consumer_control_fixup(hdev, rdesc, rsize, 104,
0643                     "Genius Gila Gaming Mouse");
0644         break;
0645     case USB_DEVICE_ID_GENIUS_GX_IMPERATOR:
0646         rdesc = kye_consumer_control_fixup(hdev, rdesc, rsize, 83,
0647                     "Genius Gx Imperator Keyboard");
0648         break;
0649     case USB_DEVICE_ID_GENIUS_MANTICORE:
0650         rdesc = kye_consumer_control_fixup(hdev, rdesc, rsize, 104,
0651                     "Genius Manticore Keyboard");
0652         break;
0653     }
0654     return rdesc;
0655 }
0656 
0657 /**
0658  * kye_tablet_enable() - Enable fully-functional tablet mode by setting a special feature report.
0659  *
0660  * @hdev:   HID device
0661  *
0662  * The specific report ID and data were discovered by sniffing the
0663  * Windows driver traffic.
0664  */
0665 static int kye_tablet_enable(struct hid_device *hdev)
0666 {
0667     struct list_head *list;
0668     struct list_head *head;
0669     struct hid_report *report;
0670     __s32 *value;
0671 
0672     list = &hdev->report_enum[HID_FEATURE_REPORT].report_list;
0673     list_for_each(head, list) {
0674         report = list_entry(head, struct hid_report, list);
0675         if (report->id == 5)
0676             break;
0677     }
0678 
0679     if (head == list) {
0680         hid_err(hdev, "tablet-enabling feature report not found\n");
0681         return -ENODEV;
0682     }
0683 
0684     if (report->maxfield < 1 || report->field[0]->report_count < 7) {
0685         hid_err(hdev, "invalid tablet-enabling feature report\n");
0686         return -ENODEV;
0687     }
0688 
0689     value = report->field[0]->value;
0690 
0691     value[0] = 0x12;
0692     value[1] = 0x10;
0693     value[2] = 0x11;
0694     value[3] = 0x12;
0695     value[4] = 0x00;
0696     value[5] = 0x00;
0697     value[6] = 0x00;
0698     hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
0699 
0700     return 0;
0701 }
0702 
0703 static int kye_probe(struct hid_device *hdev, const struct hid_device_id *id)
0704 {
0705     int ret;
0706 
0707     ret = hid_parse(hdev);
0708     if (ret) {
0709         hid_err(hdev, "parse failed\n");
0710         goto err;
0711     }
0712 
0713     ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
0714     if (ret) {
0715         hid_err(hdev, "hw start failed\n");
0716         goto err;
0717     }
0718 
0719     switch (id->product) {
0720     case USB_DEVICE_ID_KYE_EASYPEN_I405X:
0721     case USB_DEVICE_ID_KYE_MOUSEPEN_I608X:
0722     case USB_DEVICE_ID_KYE_MOUSEPEN_I608X_V2:
0723     case USB_DEVICE_ID_KYE_EASYPEN_M610X:
0724     case USB_DEVICE_ID_KYE_EASYPEN_M406XE:
0725     case USB_DEVICE_ID_KYE_PENSKETCH_M912:
0726         ret = kye_tablet_enable(hdev);
0727         if (ret) {
0728             hid_err(hdev, "tablet enabling failed\n");
0729             goto enabling_err;
0730         }
0731         break;
0732     case USB_DEVICE_ID_GENIUS_MANTICORE:
0733         /*
0734          * The manticore keyboard needs to have all the interfaces
0735          * opened at least once to be fully functional.
0736          */
0737         if (hid_hw_open(hdev))
0738             hid_hw_close(hdev);
0739         break;
0740     }
0741 
0742     return 0;
0743 enabling_err:
0744     hid_hw_stop(hdev);
0745 err:
0746     return ret;
0747 }
0748 
0749 static const struct hid_device_id kye_devices[] = {
0750     { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) },
0751     { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
0752                 USB_DEVICE_ID_KYE_EASYPEN_I405X) },
0753     { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
0754                 USB_DEVICE_ID_KYE_MOUSEPEN_I608X) },
0755     { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
0756                 USB_DEVICE_ID_KYE_MOUSEPEN_I608X_V2) },
0757     { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
0758                 USB_DEVICE_ID_KYE_EASYPEN_M610X) },
0759     { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
0760                 USB_DEVICE_ID_KYE_EASYPEN_M406XE) },
0761     { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
0762                 USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE) },
0763     { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
0764                 USB_DEVICE_ID_GENIUS_GX_IMPERATOR) },
0765     { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
0766                 USB_DEVICE_ID_GENIUS_MANTICORE) },
0767     { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
0768                 USB_DEVICE_ID_KYE_PENSKETCH_M912) },
0769     { }
0770 };
0771 MODULE_DEVICE_TABLE(hid, kye_devices);
0772 
0773 static struct hid_driver kye_driver = {
0774     .name = "kye",
0775     .id_table = kye_devices,
0776     .probe = kye_probe,
0777     .report_fixup = kye_report_fixup,
0778 };
0779 module_hid_driver(kye_driver);
0780 
0781 MODULE_LICENSE("GPL");