162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *  HID driver for Kye/Genius devices not fully compliant with HID standard
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci *  Copyright (c) 2009 Jiri Kosina
662306a36Sopenharmony_ci *  Copyright (c) 2009 Tomas Hanak
762306a36Sopenharmony_ci *  Copyright (c) 2012 Nikolai Kondrashov
862306a36Sopenharmony_ci *  Copyright (c) 2023 David Yang
962306a36Sopenharmony_ci */
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#include <asm-generic/unaligned.h>
1262306a36Sopenharmony_ci#include <linux/device.h>
1362306a36Sopenharmony_ci#include <linux/hid.h>
1462306a36Sopenharmony_ci#include <linux/module.h>
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#include "hid-ids.h"
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci/* Data gathered from Database/VID0458_PID????/Vista/TBoard/default.xml in ioTablet driver
1962306a36Sopenharmony_ci *
2062306a36Sopenharmony_ci * TODO:
2162306a36Sopenharmony_ci *   - Add battery and sleep support for EasyPen M406W and MousePen M508WX
2262306a36Sopenharmony_ci *   - Investigate ScrollZ.MiceFMT buttons of EasyPen M406
2362306a36Sopenharmony_ci */
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_cistatic const __u8 easypen_m406_control_rdesc[] = {
2662306a36Sopenharmony_ci	0x05, 0x0C,        /*  Usage Page (Consumer),    */
2762306a36Sopenharmony_ci	0x09, 0x01,        /*  Usage (Consumer Control), */
2862306a36Sopenharmony_ci	0xA1, 0x01,        /*  Collection (Application), */
2962306a36Sopenharmony_ci	0x85, 0x12,        /*    Report ID (18),         */
3062306a36Sopenharmony_ci	0x0A, 0x45, 0x02,  /*    Usage (AC Rotate),      */
3162306a36Sopenharmony_ci	0x09, 0x40,        /*    Usage (Menu),           */
3262306a36Sopenharmony_ci	0x0A, 0x2F, 0x02,  /*    Usage (AC Zoom),        */
3362306a36Sopenharmony_ci	0x0A, 0x46, 0x02,  /*    Usage (AC Resize),      */
3462306a36Sopenharmony_ci	0x0A, 0x1A, 0x02,  /*    Usage (AC Undo),        */
3562306a36Sopenharmony_ci	0x0A, 0x6A, 0x02,  /*    Usage (AC Delete),      */
3662306a36Sopenharmony_ci	0x0A, 0x24, 0x02,  /*    Usage (AC Back),        */
3762306a36Sopenharmony_ci	0x0A, 0x25, 0x02,  /*    Usage (AC Forward),     */
3862306a36Sopenharmony_ci	0x14,              /*    Logical Minimum (0),    */
3962306a36Sopenharmony_ci	0x25, 0x01,        /*    Logical Maximum (1),    */
4062306a36Sopenharmony_ci	0x75, 0x01,        /*    Report Size (1),        */
4162306a36Sopenharmony_ci	0x95, 0x08,        /*    Report Count (8),       */
4262306a36Sopenharmony_ci	0x81, 0x02,        /*    Input (Variable),       */
4362306a36Sopenharmony_ci	0x95, 0x30,        /*    Report Count (48),      */
4462306a36Sopenharmony_ci	0x81, 0x01,        /*    Input (Constant),       */
4562306a36Sopenharmony_ci	0xC0               /*  End Collection            */
4662306a36Sopenharmony_ci};
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_cistatic const __u8 easypen_m506_control_rdesc[] = {
4962306a36Sopenharmony_ci	0x05, 0x0C,        /*  Usage Page (Consumer),    */
5062306a36Sopenharmony_ci	0x09, 0x01,        /*  Usage (Consumer Control), */
5162306a36Sopenharmony_ci	0xA1, 0x01,        /*  Collection (Application), */
5262306a36Sopenharmony_ci	0x85, 0x12,        /*    Report ID (18),         */
5362306a36Sopenharmony_ci	0x0A, 0x6A, 0x02,  /*    Usage (AC Delete),      */
5462306a36Sopenharmony_ci	0x0A, 0x1A, 0x02,  /*    Usage (AC Undo),        */
5562306a36Sopenharmony_ci	0x0A, 0x2D, 0x02,  /*    Usage (AC Zoom In),     */
5662306a36Sopenharmony_ci	0x0A, 0x2E, 0x02,  /*    Usage (AC Zoom Out),    */
5762306a36Sopenharmony_ci	0x14,              /*    Logical Minimum (0),    */
5862306a36Sopenharmony_ci	0x25, 0x01,        /*    Logical Maximum (1),    */
5962306a36Sopenharmony_ci	0x75, 0x01,        /*    Report Size (1),        */
6062306a36Sopenharmony_ci	0x95, 0x04,        /*    Report Count (4),       */
6162306a36Sopenharmony_ci	0x81, 0x02,        /*    Input (Variable),       */
6262306a36Sopenharmony_ci	0x95, 0x34,        /*    Report Count (52),      */
6362306a36Sopenharmony_ci	0x81, 0x01,        /*    Input (Constant),       */
6462306a36Sopenharmony_ci	0xC0               /*  End Collection            */
6562306a36Sopenharmony_ci};
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_cistatic const __u8 easypen_m406w_control_rdesc[] = {
6862306a36Sopenharmony_ci	0x05, 0x0C,        /*  Usage Page (Consumer),    */
6962306a36Sopenharmony_ci	0x09, 0x01,        /*  Usage (Consumer Control), */
7062306a36Sopenharmony_ci	0xA1, 0x01,        /*  Collection (Application), */
7162306a36Sopenharmony_ci	0x85, 0x12,        /*    Report ID (18),         */
7262306a36Sopenharmony_ci	0x0A, 0x6A, 0x02,  /*    Usage (AC Delete),      */
7362306a36Sopenharmony_ci	0x0A, 0x1A, 0x02,  /*    Usage (AC Undo),        */
7462306a36Sopenharmony_ci	0x0A, 0x01, 0x02,  /*    Usage (AC New),         */
7562306a36Sopenharmony_ci	0x09, 0x40,        /*    Usage (Menu),           */
7662306a36Sopenharmony_ci	0x14,              /*    Logical Minimum (0),    */
7762306a36Sopenharmony_ci	0x25, 0x01,        /*    Logical Maximum (1),    */
7862306a36Sopenharmony_ci	0x75, 0x01,        /*    Report Size (1),        */
7962306a36Sopenharmony_ci	0x95, 0x04,        /*    Report Count (4),       */
8062306a36Sopenharmony_ci	0x81, 0x02,        /*    Input (Variable),       */
8162306a36Sopenharmony_ci	0x95, 0x34,        /*    Report Count (52),      */
8262306a36Sopenharmony_ci	0x81, 0x01,        /*    Input (Constant),       */
8362306a36Sopenharmony_ci	0xC0               /*  End Collection            */
8462306a36Sopenharmony_ci};
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_cistatic const __u8 easypen_m610x_control_rdesc[] = {
8762306a36Sopenharmony_ci	0x05, 0x0C,        /*  Usage Page (Consumer),       */
8862306a36Sopenharmony_ci	0x09, 0x01,        /*  Usage (Consumer Control),    */
8962306a36Sopenharmony_ci	0xA1, 0x01,        /*  Collection (Application),    */
9062306a36Sopenharmony_ci	0x85, 0x12,        /*    Report ID (18),            */
9162306a36Sopenharmony_ci	0x0A, 0x1A, 0x02,  /*    Usage (AC Undo),           */
9262306a36Sopenharmony_ci	0x0A, 0x79, 0x02,  /*    Usage (AC Redo Or Repeat), */
9362306a36Sopenharmony_ci	0x0A, 0x2D, 0x02,  /*    Usage (AC Zoom In),        */
9462306a36Sopenharmony_ci	0x0A, 0x2E, 0x02,  /*    Usage (AC Zoom Out),       */
9562306a36Sopenharmony_ci	0x14,              /*    Logical Minimum (0),       */
9662306a36Sopenharmony_ci	0x25, 0x01,        /*    Logical Maximum (1),       */
9762306a36Sopenharmony_ci	0x75, 0x01,        /*    Report Size (1),           */
9862306a36Sopenharmony_ci	0x95, 0x04,        /*    Report Count (4),          */
9962306a36Sopenharmony_ci	0x81, 0x02,        /*    Input (Variable),          */
10062306a36Sopenharmony_ci	0x95, 0x34,        /*    Report Count (52),         */
10162306a36Sopenharmony_ci	0x81, 0x01,        /*    Input (Constant),          */
10262306a36Sopenharmony_ci	0xC0               /*  End Collection               */
10362306a36Sopenharmony_ci};
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_cistatic const __u8 pensketch_m912_control_rdesc[] = {
10662306a36Sopenharmony_ci	0x05, 0x0C,        /*  Usage Page (Consumer),        */
10762306a36Sopenharmony_ci	0x09, 0x01,        /*  Usage (Consumer Control),     */
10862306a36Sopenharmony_ci	0xA1, 0x01,        /*  Collection (Application),     */
10962306a36Sopenharmony_ci	0x85, 0x12,        /*    Report ID (18),             */
11062306a36Sopenharmony_ci	0x14,              /*    Logical Minimum (0),        */
11162306a36Sopenharmony_ci	0x25, 0x01,        /*    Logical Maximum (1),        */
11262306a36Sopenharmony_ci	0x75, 0x01,        /*    Report Size (1),            */
11362306a36Sopenharmony_ci	0x95, 0x08,        /*    Report Count (8),           */
11462306a36Sopenharmony_ci	0x05, 0x0C,        /*    Usage Page (Consumer),      */
11562306a36Sopenharmony_ci	0x0A, 0x6A, 0x02,  /*    Usage (AC Delete),          */
11662306a36Sopenharmony_ci	0x0A, 0x1A, 0x02,  /*    Usage (AC Undo),            */
11762306a36Sopenharmony_ci	0x0A, 0x01, 0x02,  /*    Usage (AC New),             */
11862306a36Sopenharmony_ci	0x0A, 0x2F, 0x02,  /*    Usage (AC Zoom),            */
11962306a36Sopenharmony_ci	0x0A, 0x25, 0x02,  /*    Usage (AC Forward),         */
12062306a36Sopenharmony_ci	0x0A, 0x24, 0x02,  /*    Usage (AC Back),            */
12162306a36Sopenharmony_ci	0x0A, 0x2D, 0x02,  /*    Usage (AC Zoom In),         */
12262306a36Sopenharmony_ci	0x0A, 0x2E, 0x02,  /*    Usage (AC Zoom Out),        */
12362306a36Sopenharmony_ci	0x81, 0x02,        /*    Input (Variable),           */
12462306a36Sopenharmony_ci	0x95, 0x30,        /*    Report Count (48),          */
12562306a36Sopenharmony_ci	0x81, 0x03,        /*    Input (Constant, Variable), */
12662306a36Sopenharmony_ci	0xC0               /*  End Collection                */
12762306a36Sopenharmony_ci};
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_cistatic const __u8 mousepen_m508wx_control_rdesc[] = {
13062306a36Sopenharmony_ci	0x05, 0x0C,        /*  Usage Page (Consumer),    */
13162306a36Sopenharmony_ci	0x09, 0x01,        /*  Usage (Consumer Control), */
13262306a36Sopenharmony_ci	0xA1, 0x01,        /*  Collection (Application), */
13362306a36Sopenharmony_ci	0x85, 0x12,        /*    Report ID (18),         */
13462306a36Sopenharmony_ci	0x0A, 0x1A, 0x02,  /*    Usage (AC Undo),        */
13562306a36Sopenharmony_ci	0x0A, 0x6A, 0x02,  /*    Usage (AC Delete),      */
13662306a36Sopenharmony_ci	0x0A, 0x2D, 0x02,  /*    Usage (AC Zoom In),     */
13762306a36Sopenharmony_ci	0x0A, 0x2E, 0x02,  /*    Usage (AC Zoom Out),    */
13862306a36Sopenharmony_ci	0x14,              /*    Logical Minimum (0),    */
13962306a36Sopenharmony_ci	0x25, 0x01,        /*    Logical Maximum (1),    */
14062306a36Sopenharmony_ci	0x75, 0x01,        /*    Report Size (1),        */
14162306a36Sopenharmony_ci	0x95, 0x04,        /*    Report Count (4),       */
14262306a36Sopenharmony_ci	0x81, 0x02,        /*    Input (Variable),       */
14362306a36Sopenharmony_ci	0x95, 0x34,        /*    Report Count (52),      */
14462306a36Sopenharmony_ci	0x81, 0x01,        /*    Input (Constant),       */
14562306a36Sopenharmony_ci	0xC0               /*  End Collection            */
14662306a36Sopenharmony_ci};
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_cistatic const __u8 mousepen_m508x_control_rdesc[] = {
14962306a36Sopenharmony_ci	0x05, 0x0C,        /*  Usage Page (Consumer),        */
15062306a36Sopenharmony_ci	0x09, 0x01,        /*  Usage (Consumer Control),     */
15162306a36Sopenharmony_ci	0xA1, 0x01,        /*  Collection (Application),     */
15262306a36Sopenharmony_ci	0x85, 0x12,        /*    Report ID (18),             */
15362306a36Sopenharmony_ci	0x0A, 0x01, 0x02,  /*    Usage (AC New),             */
15462306a36Sopenharmony_ci	0x09, 0x40,        /*    Usage (Menu),               */
15562306a36Sopenharmony_ci	0x0A, 0x6A, 0x02,  /*    Usage (AC Delete),          */
15662306a36Sopenharmony_ci	0x0A, 0x1A, 0x02,  /*    Usage (AC Undo),            */
15762306a36Sopenharmony_ci	0x14,              /*    Logical Minimum (0),        */
15862306a36Sopenharmony_ci	0x25, 0x01,        /*    Logical Maximum (1),        */
15962306a36Sopenharmony_ci	0x75, 0x01,        /*    Report Size (1),            */
16062306a36Sopenharmony_ci	0x95, 0x04,        /*    Report Count (4),           */
16162306a36Sopenharmony_ci	0x81, 0x02,        /*    Input (Variable),           */
16262306a36Sopenharmony_ci	0x81, 0x01,        /*    Input (Constant),           */
16362306a36Sopenharmony_ci	0x15, 0xFF,        /*    Logical Minimum (-1),       */
16462306a36Sopenharmony_ci	0x95, 0x10,        /*    Report Count (16),          */
16562306a36Sopenharmony_ci	0x81, 0x01,        /*    Input (Constant),           */
16662306a36Sopenharmony_ci	0x0A, 0x35, 0x02,  /*    Usage (AC Scroll),          */
16762306a36Sopenharmony_ci	0x0A, 0x2F, 0x02,  /*    Usage (AC Zoom),            */
16862306a36Sopenharmony_ci	0x0A, 0x38, 0x02,  /*    Usage (AC Pan),             */
16962306a36Sopenharmony_ci	0x75, 0x08,        /*    Report Size (8),            */
17062306a36Sopenharmony_ci	0x95, 0x03,        /*    Report Count (3),           */
17162306a36Sopenharmony_ci	0x81, 0x06,        /*    Input (Variable, Relative), */
17262306a36Sopenharmony_ci	0x95, 0x01,        /*    Report Count (1),           */
17362306a36Sopenharmony_ci	0x81, 0x01,        /*    Input (Constant),           */
17462306a36Sopenharmony_ci	0xC0               /*  End Collection                */
17562306a36Sopenharmony_ci};
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_cistatic const __u8 easypen_m406xe_control_rdesc[] = {
17862306a36Sopenharmony_ci	0x05, 0x0C,        /*  Usage Page (Consumer),          */
17962306a36Sopenharmony_ci	0x09, 0x01,        /*  Usage (Consumer Control),       */
18062306a36Sopenharmony_ci	0xA1, 0x01,        /*  Collection (Application),       */
18162306a36Sopenharmony_ci	0x85, 0x12,        /*      Report ID (18),             */
18262306a36Sopenharmony_ci	0x14,              /*      Logical Minimum (0),        */
18362306a36Sopenharmony_ci	0x25, 0x01,        /*      Logical Maximum (1),        */
18462306a36Sopenharmony_ci	0x75, 0x01,        /*      Report Size (1),            */
18562306a36Sopenharmony_ci	0x95, 0x04,        /*      Report Count (4),           */
18662306a36Sopenharmony_ci	0x0A, 0x79, 0x02,  /*      Usage (AC Redo Or Repeat),  */
18762306a36Sopenharmony_ci	0x0A, 0x1A, 0x02,  /*      Usage (AC Undo),            */
18862306a36Sopenharmony_ci	0x0A, 0x2D, 0x02,  /*      Usage (AC Zoom In),         */
18962306a36Sopenharmony_ci	0x0A, 0x2E, 0x02,  /*      Usage (AC Zoom Out),        */
19062306a36Sopenharmony_ci	0x81, 0x02,        /*      Input (Variable),           */
19162306a36Sopenharmony_ci	0x95, 0x34,        /*      Report Count (52),          */
19262306a36Sopenharmony_ci	0x81, 0x03,        /*      Input (Constant, Variable), */
19362306a36Sopenharmony_ci	0xC0               /*  End Collection                  */
19462306a36Sopenharmony_ci};
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_cistatic const __u8 pensketch_t609a_control_rdesc[] = {
19762306a36Sopenharmony_ci	0x05, 0x0C,        /*  Usage Page (Consumer),    */
19862306a36Sopenharmony_ci	0x09, 0x01,        /*  Usage (Consumer Control), */
19962306a36Sopenharmony_ci	0xA1, 0x01,        /*  Collection (Application), */
20062306a36Sopenharmony_ci	0x85, 0x12,        /*    Report ID (18),         */
20162306a36Sopenharmony_ci	0x0A, 0x6A, 0x02,  /*    Usage (AC Delete),      */
20262306a36Sopenharmony_ci	0x14,              /*    Logical Minimum (0),    */
20362306a36Sopenharmony_ci	0x25, 0x01,        /*    Logical Maximum (1),    */
20462306a36Sopenharmony_ci	0x75, 0x01,        /*    Report Size (1),        */
20562306a36Sopenharmony_ci	0x95, 0x08,        /*    Report Count (8),       */
20662306a36Sopenharmony_ci	0x81, 0x02,        /*    Input (Variable),       */
20762306a36Sopenharmony_ci	0x95, 0x37,        /*    Report Count (55),      */
20862306a36Sopenharmony_ci	0x81, 0x01,        /*    Input (Constant),       */
20962306a36Sopenharmony_ci	0xC0               /*  End Collection            */
21062306a36Sopenharmony_ci};
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci/* Fix indexes in kye_tablet_fixup if you change this */
21362306a36Sopenharmony_cistatic const __u8 kye_tablet_rdesc[] = {
21462306a36Sopenharmony_ci	0x06, 0x00, 0xFF,             /*  Usage Page (FF00h),             */
21562306a36Sopenharmony_ci	0x09, 0x01,                   /*  Usage (01h),                    */
21662306a36Sopenharmony_ci	0xA1, 0x01,                   /*  Collection (Application),       */
21762306a36Sopenharmony_ci	0x85, 0x05,                   /*    Report ID (5),                */
21862306a36Sopenharmony_ci	0x09, 0x01,                   /*    Usage (01h),                  */
21962306a36Sopenharmony_ci	0x15, 0x81,                   /*    Logical Minimum (-127),       */
22062306a36Sopenharmony_ci	0x25, 0x7F,                   /*    Logical Maximum (127),        */
22162306a36Sopenharmony_ci	0x75, 0x08,                   /*    Report Size (8),              */
22262306a36Sopenharmony_ci	0x95, 0x07,                   /*    Report Count (7),             */
22362306a36Sopenharmony_ci	0xB1, 0x02,                   /*    Feature (Variable),           */
22462306a36Sopenharmony_ci	0xC0,                         /*  End Collection,                 */
22562306a36Sopenharmony_ci	0x05, 0x0D,                   /*  Usage Page (Digitizer),         */
22662306a36Sopenharmony_ci	0x09, 0x01,                   /*  Usage (Digitizer),              */
22762306a36Sopenharmony_ci	0xA1, 0x01,                   /*  Collection (Application),       */
22862306a36Sopenharmony_ci	0x85, 0x10,                   /*    Report ID (16),               */
22962306a36Sopenharmony_ci	0x09, 0x20,                   /*    Usage (Stylus),               */
23062306a36Sopenharmony_ci	0xA0,                         /*    Collection (Physical),        */
23162306a36Sopenharmony_ci	0x09, 0x42,                   /*      Usage (Tip Switch),         */
23262306a36Sopenharmony_ci	0x09, 0x44,                   /*      Usage (Barrel Switch),      */
23362306a36Sopenharmony_ci	0x09, 0x46,                   /*      Usage (Tablet Pick),        */
23462306a36Sopenharmony_ci	0x14,                         /*      Logical Minimum (0),        */
23562306a36Sopenharmony_ci	0x25, 0x01,                   /*      Logical Maximum (1),        */
23662306a36Sopenharmony_ci	0x75, 0x01,                   /*      Report Size (1),            */
23762306a36Sopenharmony_ci	0x95, 0x03,                   /*      Report Count (3),           */
23862306a36Sopenharmony_ci	0x81, 0x02,                   /*      Input (Variable),           */
23962306a36Sopenharmony_ci	0x95, 0x04,                   /*      Report Count (4),           */
24062306a36Sopenharmony_ci	0x81, 0x01,                   /*      Input (Constant),           */
24162306a36Sopenharmony_ci	0x09, 0x32,                   /*      Usage (In Range),           */
24262306a36Sopenharmony_ci	0x95, 0x01,                   /*      Report Count (1),           */
24362306a36Sopenharmony_ci	0x81, 0x02,                   /*      Input (Variable),           */
24462306a36Sopenharmony_ci	0x75, 0x10,                   /*      Report Size (16),           */
24562306a36Sopenharmony_ci	0xA4,                         /*      Push,                       */
24662306a36Sopenharmony_ci	0x05, 0x01,                   /*      Usage Page (Desktop),       */
24762306a36Sopenharmony_ci	0x09, 0x30,                   /*      Usage (X),                  */
24862306a36Sopenharmony_ci	0x27, 0xFF, 0x7F, 0x00, 0x00, /*      Logical Maximum (32767),    */
24962306a36Sopenharmony_ci	0x34,                         /*      Physical Minimum (0),       */
25062306a36Sopenharmony_ci	0x47, 0x00, 0x00, 0x00, 0x00, /*      Physical Maximum (0),       */
25162306a36Sopenharmony_ci	0x65, 0x11,                   /*      Unit (Centimeter),          */
25262306a36Sopenharmony_ci	0x55, 0x00,                   /*      Unit Exponent (0),          */
25362306a36Sopenharmony_ci	0x75, 0x10,                   /*      Report Size (16),           */
25462306a36Sopenharmony_ci	0x81, 0x02,                   /*      Input (Variable),           */
25562306a36Sopenharmony_ci	0x09, 0x31,                   /*      Usage (Y),                  */
25662306a36Sopenharmony_ci	0x27, 0xFF, 0x7F, 0x00, 0x00, /*      Logical Maximum (32767),    */
25762306a36Sopenharmony_ci	0x47, 0x00, 0x00, 0x00, 0x00, /*      Physical Maximum (0),       */
25862306a36Sopenharmony_ci	0x81, 0x02,                   /*      Input (Variable),           */
25962306a36Sopenharmony_ci	0xB4,                         /*      Pop,                        */
26062306a36Sopenharmony_ci	0x05, 0x0D,                   /*      Usage Page (Digitizer),     */
26162306a36Sopenharmony_ci	0x09, 0x30,                   /*      Usage (Tip Pressure),       */
26262306a36Sopenharmony_ci	0x27, 0xFF, 0x07, 0x00, 0x00, /*      Logical Maximum (2047),     */
26362306a36Sopenharmony_ci	0x81, 0x02,                   /*      Input (Variable),           */
26462306a36Sopenharmony_ci	0xC0,                         /*    End Collection,               */
26562306a36Sopenharmony_ci	0xC0,                         /*  End Collection,                 */
26662306a36Sopenharmony_ci	0x05, 0x0D,                   /*  Usage Page (Digitizer),         */
26762306a36Sopenharmony_ci	0x09, 0x21,                   /*  Usage (Puck),                   */
26862306a36Sopenharmony_ci	0xA1, 0x01,                   /*  Collection (Application),       */
26962306a36Sopenharmony_ci	0x85, 0x11,                   /*    Report ID (17),               */
27062306a36Sopenharmony_ci	0x09, 0x21,                   /*    Usage (Puck),                 */
27162306a36Sopenharmony_ci	0xA0,                         /*    Collection (Physical),        */
27262306a36Sopenharmony_ci	0x05, 0x09,                   /*      Usage Page (Button),        */
27362306a36Sopenharmony_ci	0x19, 0x01,                   /*      Usage Minimum (01h),        */
27462306a36Sopenharmony_ci	0x29, 0x03,                   /*      Usage Maximum (03h),        */
27562306a36Sopenharmony_ci	0x14,                         /*      Logical Minimum (0),        */
27662306a36Sopenharmony_ci	0x25, 0x01,                   /*      Logical Maximum (1),        */
27762306a36Sopenharmony_ci	0x75, 0x01,                   /*      Report Size (1),            */
27862306a36Sopenharmony_ci	0x95, 0x03,                   /*      Report Count (3),           */
27962306a36Sopenharmony_ci	0x81, 0x02,                   /*      Input (Variable),           */
28062306a36Sopenharmony_ci	0x95, 0x04,                   /*      Report Count (4),           */
28162306a36Sopenharmony_ci	0x81, 0x01,                   /*      Input (Constant),           */
28262306a36Sopenharmony_ci	0x05, 0x0D,                   /*      Usage Page (Digitizer),     */
28362306a36Sopenharmony_ci	0x09, 0x32,                   /*      Usage (In Range),           */
28462306a36Sopenharmony_ci	0x95, 0x01,                   /*      Report Count (1),           */
28562306a36Sopenharmony_ci	0x81, 0x02,                   /*      Input (Variable),           */
28662306a36Sopenharmony_ci	0x05, 0x01,                   /*      Usage Page (Desktop),       */
28762306a36Sopenharmony_ci	0xA4,                         /*      Push,                       */
28862306a36Sopenharmony_ci	0x09, 0x30,                   /*      Usage (X),                  */
28962306a36Sopenharmony_ci	0x27, 0xFF, 0x7F, 0x00, 0x00, /*      Logical Maximum (32767),    */
29062306a36Sopenharmony_ci	0x34,                         /*      Physical Minimum (0),       */
29162306a36Sopenharmony_ci	0x47, 0x00, 0x00, 0x00, 0x00, /*      Physical Maximum (0),       */
29262306a36Sopenharmony_ci	0x65, 0x11,                   /*      Unit (Centimeter),          */
29362306a36Sopenharmony_ci	0x55, 0x00,                   /*      Unit Exponent (0),          */
29462306a36Sopenharmony_ci	0x75, 0x10,                   /*      Report Size (16),           */
29562306a36Sopenharmony_ci	0x81, 0x02,                   /*      Input (Variable),           */
29662306a36Sopenharmony_ci	0x09, 0x31,                   /*      Usage (Y),                  */
29762306a36Sopenharmony_ci	0x27, 0xFF, 0x7F, 0x00, 0x00, /*      Logical Maximum (32767),    */
29862306a36Sopenharmony_ci	0x47, 0x00, 0x00, 0x00, 0x00, /*      Physical Maximum (0),       */
29962306a36Sopenharmony_ci	0x81, 0x02,                   /*      Input (Variable),           */
30062306a36Sopenharmony_ci	0xB4,                         /*      Pop,                        */
30162306a36Sopenharmony_ci	0x09, 0x38,                   /*      Usage (Wheel),              */
30262306a36Sopenharmony_ci	0x15, 0xFF,                   /*      Logical Minimum (-1),       */
30362306a36Sopenharmony_ci	0x75, 0x08,                   /*      Report Size (8),            */
30462306a36Sopenharmony_ci	0x95, 0x01,                   /*      Report Count (1),           */
30562306a36Sopenharmony_ci	0x81, 0x06,                   /*      Input (Variable, Relative), */
30662306a36Sopenharmony_ci	0x81, 0x01,                   /*      Input (Constant),           */
30762306a36Sopenharmony_ci	0xC0,                         /*    End Collection,               */
30862306a36Sopenharmony_ci	0xC0                          /*  End Collection                  */
30962306a36Sopenharmony_ci};
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_cistatic const struct kye_tablet_info {
31262306a36Sopenharmony_ci	__u32 product;
31362306a36Sopenharmony_ci	__s32 x_logical_maximum;
31462306a36Sopenharmony_ci	__s32 y_logical_maximum;
31562306a36Sopenharmony_ci	__s32 pressure_logical_maximum;
31662306a36Sopenharmony_ci	__s32 x_physical_maximum;
31762306a36Sopenharmony_ci	__s32 y_physical_maximum;
31862306a36Sopenharmony_ci	__s8 unit_exponent;
31962306a36Sopenharmony_ci	__s8 unit;
32062306a36Sopenharmony_ci	bool has_punk;
32162306a36Sopenharmony_ci	unsigned int control_rsize;
32262306a36Sopenharmony_ci	const __u8 *control_rdesc;
32362306a36Sopenharmony_ci} kye_tablets_info[] = {
32462306a36Sopenharmony_ci	{USB_DEVICE_ID_KYE_EASYPEN_M406,  /* 0x5005 */
32562306a36Sopenharmony_ci		15360, 10240, 1023,    6,   4,  0, 0x13, false,
32662306a36Sopenharmony_ci		sizeof(easypen_m406_control_rdesc), easypen_m406_control_rdesc},
32762306a36Sopenharmony_ci	{USB_DEVICE_ID_KYE_EASYPEN_M506,  /* 0x500F */
32862306a36Sopenharmony_ci		24576, 20480, 1023,    6,   5,  0, 0x13, false,
32962306a36Sopenharmony_ci		sizeof(easypen_m506_control_rdesc), easypen_m506_control_rdesc},
33062306a36Sopenharmony_ci	{USB_DEVICE_ID_KYE_EASYPEN_I405X,  /* 0x5010 */
33162306a36Sopenharmony_ci		14080, 10240, 1023,   55,  40, -1, 0x13, false},
33262306a36Sopenharmony_ci	{USB_DEVICE_ID_KYE_MOUSEPEN_I608X,  /* 0x5011 */
33362306a36Sopenharmony_ci		20480, 15360, 2047,    8,   6,  0, 0x13,  true},
33462306a36Sopenharmony_ci	{USB_DEVICE_ID_KYE_EASYPEN_M406W,  /* 0x5012 */
33562306a36Sopenharmony_ci		15360, 10240, 1023,    6,   4,  0, 0x13, false,
33662306a36Sopenharmony_ci		sizeof(easypen_m406w_control_rdesc), easypen_m406w_control_rdesc},
33762306a36Sopenharmony_ci	{USB_DEVICE_ID_KYE_EASYPEN_M610X,  /* 0x5013 */
33862306a36Sopenharmony_ci		40960, 25600, 1023, 1000, 625, -2, 0x13, false,
33962306a36Sopenharmony_ci		sizeof(easypen_m610x_control_rdesc), easypen_m610x_control_rdesc},
34062306a36Sopenharmony_ci	{USB_DEVICE_ID_KYE_EASYPEN_340,  /* 0x5014 */
34162306a36Sopenharmony_ci		10240,  7680, 1023,    4,   3,  0, 0x13, false},
34262306a36Sopenharmony_ci	{USB_DEVICE_ID_KYE_PENSKETCH_M912,  /* 0x5015 */
34362306a36Sopenharmony_ci		61440, 46080, 2047,   12,   9,  0, 0x13,  true,
34462306a36Sopenharmony_ci		sizeof(pensketch_m912_control_rdesc), pensketch_m912_control_rdesc},
34562306a36Sopenharmony_ci	{USB_DEVICE_ID_KYE_MOUSEPEN_M508WX,  /* 0x5016 */
34662306a36Sopenharmony_ci		40960, 25600, 2047,    8,   5,  0, 0x13,  true,
34762306a36Sopenharmony_ci		sizeof(mousepen_m508wx_control_rdesc), mousepen_m508wx_control_rdesc},
34862306a36Sopenharmony_ci	{USB_DEVICE_ID_KYE_MOUSEPEN_M508X,  /* 0x5017 */
34962306a36Sopenharmony_ci		40960, 25600, 2047,    8,   5,  0, 0x13,  true,
35062306a36Sopenharmony_ci		sizeof(mousepen_m508x_control_rdesc), mousepen_m508x_control_rdesc},
35162306a36Sopenharmony_ci	{USB_DEVICE_ID_KYE_EASYPEN_M406XE,  /* 0x5019 */
35262306a36Sopenharmony_ci		15360, 10240, 1023,    6,   4,  0, 0x13, false,
35362306a36Sopenharmony_ci		sizeof(easypen_m406xe_control_rdesc), easypen_m406xe_control_rdesc},
35462306a36Sopenharmony_ci	{USB_DEVICE_ID_KYE_MOUSEPEN_I608X_V2,  /* 0x501A */
35562306a36Sopenharmony_ci		40960, 30720, 2047,    8,   6,  0, 0x13,  true},
35662306a36Sopenharmony_ci	{USB_DEVICE_ID_KYE_PENSKETCH_T609A,  /* 0x501B */
35762306a36Sopenharmony_ci		43520, 28160, 1023,   85,  55, -1, 0x13, false,
35862306a36Sopenharmony_ci		sizeof(pensketch_t609a_control_rdesc), pensketch_t609a_control_rdesc},
35962306a36Sopenharmony_ci	{}
36062306a36Sopenharmony_ci};
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_cistatic __u8 *kye_consumer_control_fixup(struct hid_device *hdev, __u8 *rdesc,
36362306a36Sopenharmony_ci		unsigned int *rsize, int offset, const char *device_name)
36462306a36Sopenharmony_ci{
36562306a36Sopenharmony_ci	/*
36662306a36Sopenharmony_ci	 * the fixup that need to be done:
36762306a36Sopenharmony_ci	 *   - change Usage Maximum in the Consumer Control
36862306a36Sopenharmony_ci	 *     (report ID 3) to a reasonable value
36962306a36Sopenharmony_ci	 */
37062306a36Sopenharmony_ci	if (*rsize >= offset + 31 &&
37162306a36Sopenharmony_ci	    /* Usage Page (Consumer Devices) */
37262306a36Sopenharmony_ci	    rdesc[offset] == 0x05 && rdesc[offset + 1] == 0x0c &&
37362306a36Sopenharmony_ci	    /* Usage (Consumer Control) */
37462306a36Sopenharmony_ci	    rdesc[offset + 2] == 0x09 && rdesc[offset + 3] == 0x01 &&
37562306a36Sopenharmony_ci	    /*   Usage Maximum > 12287 */
37662306a36Sopenharmony_ci	    rdesc[offset + 10] == 0x2a && rdesc[offset + 12] > 0x2f) {
37762306a36Sopenharmony_ci		hid_info(hdev, "fixing up %s report descriptor\n", device_name);
37862306a36Sopenharmony_ci		rdesc[offset + 12] = 0x2f;
37962306a36Sopenharmony_ci	}
38062306a36Sopenharmony_ci	return rdesc;
38162306a36Sopenharmony_ci}
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci/*
38462306a36Sopenharmony_ci * Fix tablet descriptor of so-called "DataFormat 2".
38562306a36Sopenharmony_ci *
38662306a36Sopenharmony_ci * Though we may achieve a usable descriptor from original vendor-defined one,
38762306a36Sopenharmony_ci * some problems exist:
38862306a36Sopenharmony_ci *  - Their Logical Maximum never exceed 32767 (7F FF), though device do report
38962306a36Sopenharmony_ci *    values greater than that;
39062306a36Sopenharmony_ci *  - Physical Maximums are arbitrarily filled (always equal to Logical
39162306a36Sopenharmony_ci *    Maximum);
39262306a36Sopenharmony_ci *  - Detail for control buttons are not provided (a vendor-defined Usage Page
39362306a36Sopenharmony_ci *    with fixed content).
39462306a36Sopenharmony_ci *
39562306a36Sopenharmony_ci * Thus we use a pre-defined parameter table rather than digging it from
39662306a36Sopenharmony_ci * original descriptor.
39762306a36Sopenharmony_ci *
39862306a36Sopenharmony_ci * We may as well write a fallback routine for unrecognized kye tablet, but it's
39962306a36Sopenharmony_ci * clear kye are unlikely to produce new models in the foreseeable future, so we
40062306a36Sopenharmony_ci * simply enumerate all possible models.
40162306a36Sopenharmony_ci */
40262306a36Sopenharmony_cistatic __u8 *kye_tablet_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize)
40362306a36Sopenharmony_ci{
40462306a36Sopenharmony_ci	const struct kye_tablet_info *info;
40562306a36Sopenharmony_ci	unsigned int newsize;
40662306a36Sopenharmony_ci
40762306a36Sopenharmony_ci	if (*rsize < sizeof(kye_tablet_rdesc)) {
40862306a36Sopenharmony_ci		hid_warn(hdev,
40962306a36Sopenharmony_ci			 "tablet report size too small, or kye_tablet_rdesc unexpectedly large\n");
41062306a36Sopenharmony_ci		return rdesc;
41162306a36Sopenharmony_ci	}
41262306a36Sopenharmony_ci
41362306a36Sopenharmony_ci	for (info = kye_tablets_info; info->product; info++) {
41462306a36Sopenharmony_ci		if (hdev->product == info->product)
41562306a36Sopenharmony_ci			break;
41662306a36Sopenharmony_ci	}
41762306a36Sopenharmony_ci
41862306a36Sopenharmony_ci	if (!info->product) {
41962306a36Sopenharmony_ci		hid_err(hdev, "tablet unknown, someone forget to add kye_tablet_info entry?\n");
42062306a36Sopenharmony_ci		return rdesc;
42162306a36Sopenharmony_ci	}
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_ci	newsize = info->has_punk ? sizeof(kye_tablet_rdesc) : 112;
42462306a36Sopenharmony_ci	memcpy(rdesc, kye_tablet_rdesc, newsize);
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_ci	put_unaligned_le32(info->x_logical_maximum, rdesc + 66);
42762306a36Sopenharmony_ci	put_unaligned_le32(info->x_physical_maximum, rdesc + 72);
42862306a36Sopenharmony_ci	rdesc[77] = info->unit;
42962306a36Sopenharmony_ci	rdesc[79] = info->unit_exponent;
43062306a36Sopenharmony_ci	put_unaligned_le32(info->y_logical_maximum, rdesc + 87);
43162306a36Sopenharmony_ci	put_unaligned_le32(info->y_physical_maximum, rdesc + 92);
43262306a36Sopenharmony_ci	put_unaligned_le32(info->pressure_logical_maximum, rdesc + 104);
43362306a36Sopenharmony_ci
43462306a36Sopenharmony_ci	if (info->has_punk) {
43562306a36Sopenharmony_ci		put_unaligned_le32(info->x_logical_maximum, rdesc + 156);
43662306a36Sopenharmony_ci		put_unaligned_le32(info->x_physical_maximum, rdesc + 162);
43762306a36Sopenharmony_ci		rdesc[167] = info->unit;
43862306a36Sopenharmony_ci		rdesc[169] = info->unit_exponent;
43962306a36Sopenharmony_ci		put_unaligned_le32(info->y_logical_maximum, rdesc + 177);
44062306a36Sopenharmony_ci		put_unaligned_le32(info->y_physical_maximum, rdesc + 182);
44162306a36Sopenharmony_ci	}
44262306a36Sopenharmony_ci
44362306a36Sopenharmony_ci	if (info->control_rsize) {
44462306a36Sopenharmony_ci		if (newsize + info->control_rsize > *rsize)
44562306a36Sopenharmony_ci			hid_err(hdev, "control rdesc unexpectedly large");
44662306a36Sopenharmony_ci		else {
44762306a36Sopenharmony_ci			memcpy(rdesc + newsize, info->control_rdesc, info->control_rsize);
44862306a36Sopenharmony_ci			newsize += info->control_rsize;
44962306a36Sopenharmony_ci		}
45062306a36Sopenharmony_ci	}
45162306a36Sopenharmony_ci
45262306a36Sopenharmony_ci	*rsize = newsize;
45362306a36Sopenharmony_ci	return rdesc;
45462306a36Sopenharmony_ci}
45562306a36Sopenharmony_ci
45662306a36Sopenharmony_cistatic __u8 *kye_report_fixup(struct hid_device *hdev, __u8 *rdesc,
45762306a36Sopenharmony_ci		unsigned int *rsize)
45862306a36Sopenharmony_ci{
45962306a36Sopenharmony_ci	switch (hdev->product) {
46062306a36Sopenharmony_ci	case USB_DEVICE_ID_KYE_ERGO_525V:
46162306a36Sopenharmony_ci		/* the fixups that need to be done:
46262306a36Sopenharmony_ci		 *   - change led usage page to button for extra buttons
46362306a36Sopenharmony_ci		 *   - report size 8 count 1 must be size 1 count 8 for button
46462306a36Sopenharmony_ci		 *     bitfield
46562306a36Sopenharmony_ci		 *   - change the button usage range to 4-7 for the extra
46662306a36Sopenharmony_ci		 *     buttons
46762306a36Sopenharmony_ci		 */
46862306a36Sopenharmony_ci		if (*rsize >= 75 &&
46962306a36Sopenharmony_ci			rdesc[61] == 0x05 && rdesc[62] == 0x08 &&
47062306a36Sopenharmony_ci			rdesc[63] == 0x19 && rdesc[64] == 0x08 &&
47162306a36Sopenharmony_ci			rdesc[65] == 0x29 && rdesc[66] == 0x0f &&
47262306a36Sopenharmony_ci			rdesc[71] == 0x75 && rdesc[72] == 0x08 &&
47362306a36Sopenharmony_ci			rdesc[73] == 0x95 && rdesc[74] == 0x01) {
47462306a36Sopenharmony_ci			hid_info(hdev,
47562306a36Sopenharmony_ci				 "fixing up Kye/Genius Ergo Mouse "
47662306a36Sopenharmony_ci				 "report descriptor\n");
47762306a36Sopenharmony_ci			rdesc[62] = 0x09;
47862306a36Sopenharmony_ci			rdesc[64] = 0x04;
47962306a36Sopenharmony_ci			rdesc[66] = 0x07;
48062306a36Sopenharmony_ci			rdesc[72] = 0x01;
48162306a36Sopenharmony_ci			rdesc[74] = 0x08;
48262306a36Sopenharmony_ci		}
48362306a36Sopenharmony_ci		break;
48462306a36Sopenharmony_ci	case USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE:
48562306a36Sopenharmony_ci		rdesc = kye_consumer_control_fixup(hdev, rdesc, rsize, 104,
48662306a36Sopenharmony_ci					"Genius Gila Gaming Mouse");
48762306a36Sopenharmony_ci		break;
48862306a36Sopenharmony_ci	case USB_DEVICE_ID_GENIUS_MANTICORE:
48962306a36Sopenharmony_ci		rdesc = kye_consumer_control_fixup(hdev, rdesc, rsize, 104,
49062306a36Sopenharmony_ci					"Genius Manticore Keyboard");
49162306a36Sopenharmony_ci		break;
49262306a36Sopenharmony_ci	case USB_DEVICE_ID_GENIUS_GX_IMPERATOR:
49362306a36Sopenharmony_ci		rdesc = kye_consumer_control_fixup(hdev, rdesc, rsize, 83,
49462306a36Sopenharmony_ci					"Genius Gx Imperator Keyboard");
49562306a36Sopenharmony_ci		break;
49662306a36Sopenharmony_ci	case USB_DEVICE_ID_KYE_EASYPEN_M406:
49762306a36Sopenharmony_ci	case USB_DEVICE_ID_KYE_EASYPEN_M506:
49862306a36Sopenharmony_ci	case USB_DEVICE_ID_KYE_EASYPEN_I405X:
49962306a36Sopenharmony_ci	case USB_DEVICE_ID_KYE_MOUSEPEN_I608X:
50062306a36Sopenharmony_ci	case USB_DEVICE_ID_KYE_EASYPEN_M406W:
50162306a36Sopenharmony_ci	case USB_DEVICE_ID_KYE_EASYPEN_M610X:
50262306a36Sopenharmony_ci	case USB_DEVICE_ID_KYE_EASYPEN_340:
50362306a36Sopenharmony_ci	case USB_DEVICE_ID_KYE_PENSKETCH_M912:
50462306a36Sopenharmony_ci	case USB_DEVICE_ID_KYE_MOUSEPEN_M508WX:
50562306a36Sopenharmony_ci	case USB_DEVICE_ID_KYE_MOUSEPEN_M508X:
50662306a36Sopenharmony_ci	case USB_DEVICE_ID_KYE_EASYPEN_M406XE:
50762306a36Sopenharmony_ci	case USB_DEVICE_ID_KYE_MOUSEPEN_I608X_V2:
50862306a36Sopenharmony_ci	case USB_DEVICE_ID_KYE_PENSKETCH_T609A:
50962306a36Sopenharmony_ci		rdesc = kye_tablet_fixup(hdev, rdesc, rsize);
51062306a36Sopenharmony_ci		break;
51162306a36Sopenharmony_ci	}
51262306a36Sopenharmony_ci	return rdesc;
51362306a36Sopenharmony_ci}
51462306a36Sopenharmony_ci
51562306a36Sopenharmony_cistatic int kye_tablet_enable(struct hid_device *hdev)
51662306a36Sopenharmony_ci{
51762306a36Sopenharmony_ci	struct list_head *list;
51862306a36Sopenharmony_ci	struct list_head *head;
51962306a36Sopenharmony_ci	struct hid_report *report;
52062306a36Sopenharmony_ci	__s32 *value;
52162306a36Sopenharmony_ci
52262306a36Sopenharmony_ci	list = &hdev->report_enum[HID_FEATURE_REPORT].report_list;
52362306a36Sopenharmony_ci	list_for_each(head, list) {
52462306a36Sopenharmony_ci		report = list_entry(head, struct hid_report, list);
52562306a36Sopenharmony_ci		if (report->id == 5)
52662306a36Sopenharmony_ci			break;
52762306a36Sopenharmony_ci	}
52862306a36Sopenharmony_ci
52962306a36Sopenharmony_ci	if (head == list) {
53062306a36Sopenharmony_ci		hid_err(hdev, "tablet-enabling feature report not found\n");
53162306a36Sopenharmony_ci		return -ENODEV;
53262306a36Sopenharmony_ci	}
53362306a36Sopenharmony_ci
53462306a36Sopenharmony_ci	if (report->maxfield < 1 || report->field[0]->report_count < 7) {
53562306a36Sopenharmony_ci		hid_err(hdev, "invalid tablet-enabling feature report\n");
53662306a36Sopenharmony_ci		return -ENODEV;
53762306a36Sopenharmony_ci	}
53862306a36Sopenharmony_ci
53962306a36Sopenharmony_ci	value = report->field[0]->value;
54062306a36Sopenharmony_ci
54162306a36Sopenharmony_ci	/*
54262306a36Sopenharmony_ci	 * The code is for DataFormat 2 of config xml. They have no obvious
54362306a36Sopenharmony_ci	 * meaning (at least not configurable in Windows driver) except enabling
54462306a36Sopenharmony_ci	 * fully-functional tablet mode (absolute positioning). Otherwise, the
54562306a36Sopenharmony_ci	 * tablet acts like a relative mouse.
54662306a36Sopenharmony_ci	 *
54762306a36Sopenharmony_ci	 * Though there're magic codes for DataFormat 3 and 4, no devices use
54862306a36Sopenharmony_ci	 * these DataFormats.
54962306a36Sopenharmony_ci	 */
55062306a36Sopenharmony_ci	value[0] = 0x12;
55162306a36Sopenharmony_ci	value[1] = 0x10;
55262306a36Sopenharmony_ci	value[2] = 0x11;
55362306a36Sopenharmony_ci	value[3] = 0x12;
55462306a36Sopenharmony_ci	value[4] = 0x00;
55562306a36Sopenharmony_ci	value[5] = 0x00;
55662306a36Sopenharmony_ci	value[6] = 0x00;
55762306a36Sopenharmony_ci	hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
55862306a36Sopenharmony_ci
55962306a36Sopenharmony_ci	return 0;
56062306a36Sopenharmony_ci}
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_cistatic int kye_probe(struct hid_device *hdev, const struct hid_device_id *id)
56362306a36Sopenharmony_ci{
56462306a36Sopenharmony_ci	int ret;
56562306a36Sopenharmony_ci
56662306a36Sopenharmony_ci	ret = hid_parse(hdev);
56762306a36Sopenharmony_ci	if (ret) {
56862306a36Sopenharmony_ci		hid_err(hdev, "parse failed\n");
56962306a36Sopenharmony_ci		goto err;
57062306a36Sopenharmony_ci	}
57162306a36Sopenharmony_ci
57262306a36Sopenharmony_ci	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
57362306a36Sopenharmony_ci	if (ret) {
57462306a36Sopenharmony_ci		hid_err(hdev, "hw start failed\n");
57562306a36Sopenharmony_ci		goto err;
57662306a36Sopenharmony_ci	}
57762306a36Sopenharmony_ci
57862306a36Sopenharmony_ci	switch (id->product) {
57962306a36Sopenharmony_ci	case USB_DEVICE_ID_GENIUS_MANTICORE:
58062306a36Sopenharmony_ci		/*
58162306a36Sopenharmony_ci		 * The manticore keyboard needs to have all the interfaces
58262306a36Sopenharmony_ci		 * opened at least once to be fully functional.
58362306a36Sopenharmony_ci		 */
58462306a36Sopenharmony_ci		if (hid_hw_open(hdev))
58562306a36Sopenharmony_ci			hid_hw_close(hdev);
58662306a36Sopenharmony_ci		break;
58762306a36Sopenharmony_ci	case USB_DEVICE_ID_KYE_EASYPEN_M406:
58862306a36Sopenharmony_ci	case USB_DEVICE_ID_KYE_EASYPEN_M506:
58962306a36Sopenharmony_ci	case USB_DEVICE_ID_KYE_EASYPEN_I405X:
59062306a36Sopenharmony_ci	case USB_DEVICE_ID_KYE_MOUSEPEN_I608X:
59162306a36Sopenharmony_ci	case USB_DEVICE_ID_KYE_EASYPEN_M406W:
59262306a36Sopenharmony_ci	case USB_DEVICE_ID_KYE_EASYPEN_M610X:
59362306a36Sopenharmony_ci	case USB_DEVICE_ID_KYE_EASYPEN_340:
59462306a36Sopenharmony_ci	case USB_DEVICE_ID_KYE_PENSKETCH_M912:
59562306a36Sopenharmony_ci	case USB_DEVICE_ID_KYE_MOUSEPEN_M508WX:
59662306a36Sopenharmony_ci	case USB_DEVICE_ID_KYE_MOUSEPEN_M508X:
59762306a36Sopenharmony_ci	case USB_DEVICE_ID_KYE_EASYPEN_M406XE:
59862306a36Sopenharmony_ci	case USB_DEVICE_ID_KYE_MOUSEPEN_I608X_V2:
59962306a36Sopenharmony_ci	case USB_DEVICE_ID_KYE_PENSKETCH_T609A:
60062306a36Sopenharmony_ci		ret = kye_tablet_enable(hdev);
60162306a36Sopenharmony_ci		if (ret) {
60262306a36Sopenharmony_ci			hid_err(hdev, "tablet enabling failed\n");
60362306a36Sopenharmony_ci			goto enabling_err;
60462306a36Sopenharmony_ci		}
60562306a36Sopenharmony_ci		break;
60662306a36Sopenharmony_ci	}
60762306a36Sopenharmony_ci
60862306a36Sopenharmony_ci	return 0;
60962306a36Sopenharmony_cienabling_err:
61062306a36Sopenharmony_ci	hid_hw_stop(hdev);
61162306a36Sopenharmony_cierr:
61262306a36Sopenharmony_ci	return ret;
61362306a36Sopenharmony_ci}
61462306a36Sopenharmony_ci
61562306a36Sopenharmony_cistatic const struct hid_device_id kye_devices[] = {
61662306a36Sopenharmony_ci	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) },
61762306a36Sopenharmony_ci	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE,
61862306a36Sopenharmony_ci				USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE) },
61962306a36Sopenharmony_ci	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE,
62062306a36Sopenharmony_ci				USB_DEVICE_ID_GENIUS_MANTICORE) },
62162306a36Sopenharmony_ci	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE,
62262306a36Sopenharmony_ci				USB_DEVICE_ID_GENIUS_GX_IMPERATOR) },
62362306a36Sopenharmony_ci	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE,
62462306a36Sopenharmony_ci				USB_DEVICE_ID_KYE_EASYPEN_M406) },
62562306a36Sopenharmony_ci	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE,
62662306a36Sopenharmony_ci				USB_DEVICE_ID_KYE_EASYPEN_M506) },
62762306a36Sopenharmony_ci	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE,
62862306a36Sopenharmony_ci				USB_DEVICE_ID_KYE_EASYPEN_I405X) },
62962306a36Sopenharmony_ci	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE,
63062306a36Sopenharmony_ci				USB_DEVICE_ID_KYE_MOUSEPEN_I608X) },
63162306a36Sopenharmony_ci	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE,
63262306a36Sopenharmony_ci				USB_DEVICE_ID_KYE_EASYPEN_M406W) },
63362306a36Sopenharmony_ci	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE,
63462306a36Sopenharmony_ci				USB_DEVICE_ID_KYE_EASYPEN_M610X) },
63562306a36Sopenharmony_ci	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE,
63662306a36Sopenharmony_ci				USB_DEVICE_ID_KYE_EASYPEN_340) },
63762306a36Sopenharmony_ci	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE,
63862306a36Sopenharmony_ci				USB_DEVICE_ID_KYE_PENSKETCH_M912) },
63962306a36Sopenharmony_ci	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE,
64062306a36Sopenharmony_ci				USB_DEVICE_ID_KYE_MOUSEPEN_M508WX) },
64162306a36Sopenharmony_ci	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE,
64262306a36Sopenharmony_ci				USB_DEVICE_ID_KYE_MOUSEPEN_M508X) },
64362306a36Sopenharmony_ci	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE,
64462306a36Sopenharmony_ci				USB_DEVICE_ID_KYE_EASYPEN_M406XE) },
64562306a36Sopenharmony_ci	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE,
64662306a36Sopenharmony_ci				USB_DEVICE_ID_KYE_MOUSEPEN_I608X_V2) },
64762306a36Sopenharmony_ci	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE,
64862306a36Sopenharmony_ci				USB_DEVICE_ID_KYE_PENSKETCH_T609A) },
64962306a36Sopenharmony_ci	{ }
65062306a36Sopenharmony_ci};
65162306a36Sopenharmony_ciMODULE_DEVICE_TABLE(hid, kye_devices);
65262306a36Sopenharmony_ci
65362306a36Sopenharmony_cistatic struct hid_driver kye_driver = {
65462306a36Sopenharmony_ci	.name = "kye",
65562306a36Sopenharmony_ci	.id_table = kye_devices,
65662306a36Sopenharmony_ci	.probe = kye_probe,
65762306a36Sopenharmony_ci	.report_fixup = kye_report_fixup,
65862306a36Sopenharmony_ci};
65962306a36Sopenharmony_cimodule_hid_driver(kye_driver);
66062306a36Sopenharmony_ci
66162306a36Sopenharmony_ciMODULE_LICENSE("GPL");
662