12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
279422741SJiri Kosina /*
379422741SJiri Kosina * HID driver for Kye/Genius devices not fully compliant with HID standard
479422741SJiri Kosina *
579422741SJiri Kosina * Copyright (c) 2009 Jiri Kosina
679422741SJiri Kosina * Copyright (c) 2009 Tomas Hanak
722ca20b2SNikolai Kondrashov * Copyright (c) 2012 Nikolai Kondrashov
8b8cd2d96SDavid Yang * Copyright (c) 2023 David Yang
979422741SJiri Kosina */
1079422741SJiri Kosina
11b8cd2d96SDavid Yang #include <asm-generic/unaligned.h>
1279422741SJiri Kosina #include <linux/device.h>
1379422741SJiri Kosina #include <linux/hid.h>
1479422741SJiri Kosina #include <linux/module.h>
1579422741SJiri Kosina
1679422741SJiri Kosina #include "hid-ids.h"
1779422741SJiri Kosina
182dd438cdSDavid Yang /* Data gathered from Database/VID0458_PID????/Vista/TBoard/default.xml in ioTablet driver
192dd438cdSDavid Yang *
202dd438cdSDavid Yang * TODO:
212dd438cdSDavid Yang * - Add battery and sleep support for EasyPen M406W and MousePen M508WX
222dd438cdSDavid Yang * - Investigate ScrollZ.MiceFMT buttons of EasyPen M406
232dd438cdSDavid Yang */
242dd438cdSDavid Yang
252dd438cdSDavid Yang static const __u8 easypen_m406_control_rdesc[] = {
262dd438cdSDavid Yang 0x05, 0x0C, /* Usage Page (Consumer), */
272dd438cdSDavid Yang 0x09, 0x01, /* Usage (Consumer Control), */
282dd438cdSDavid Yang 0xA1, 0x01, /* Collection (Application), */
292dd438cdSDavid Yang 0x85, 0x12, /* Report ID (18), */
302dd438cdSDavid Yang 0x0A, 0x45, 0x02, /* Usage (AC Rotate), */
312dd438cdSDavid Yang 0x09, 0x40, /* Usage (Menu), */
322dd438cdSDavid Yang 0x0A, 0x2F, 0x02, /* Usage (AC Zoom), */
332dd438cdSDavid Yang 0x0A, 0x46, 0x02, /* Usage (AC Resize), */
342dd438cdSDavid Yang 0x0A, 0x1A, 0x02, /* Usage (AC Undo), */
352dd438cdSDavid Yang 0x0A, 0x6A, 0x02, /* Usage (AC Delete), */
362dd438cdSDavid Yang 0x0A, 0x24, 0x02, /* Usage (AC Back), */
372dd438cdSDavid Yang 0x0A, 0x25, 0x02, /* Usage (AC Forward), */
382dd438cdSDavid Yang 0x14, /* Logical Minimum (0), */
392dd438cdSDavid Yang 0x25, 0x01, /* Logical Maximum (1), */
402dd438cdSDavid Yang 0x75, 0x01, /* Report Size (1), */
412dd438cdSDavid Yang 0x95, 0x08, /* Report Count (8), */
422dd438cdSDavid Yang 0x81, 0x02, /* Input (Variable), */
432dd438cdSDavid Yang 0x95, 0x30, /* Report Count (48), */
442dd438cdSDavid Yang 0x81, 0x01, /* Input (Constant), */
452dd438cdSDavid Yang 0xC0 /* End Collection */
462dd438cdSDavid Yang };
472dd438cdSDavid Yang
482dd438cdSDavid Yang static const __u8 easypen_m506_control_rdesc[] = {
492dd438cdSDavid Yang 0x05, 0x0C, /* Usage Page (Consumer), */
502dd438cdSDavid Yang 0x09, 0x01, /* Usage (Consumer Control), */
512dd438cdSDavid Yang 0xA1, 0x01, /* Collection (Application), */
522dd438cdSDavid Yang 0x85, 0x12, /* Report ID (18), */
532dd438cdSDavid Yang 0x0A, 0x6A, 0x02, /* Usage (AC Delete), */
542dd438cdSDavid Yang 0x0A, 0x1A, 0x02, /* Usage (AC Undo), */
552dd438cdSDavid Yang 0x0A, 0x2D, 0x02, /* Usage (AC Zoom In), */
562dd438cdSDavid Yang 0x0A, 0x2E, 0x02, /* Usage (AC Zoom Out), */
572dd438cdSDavid Yang 0x14, /* Logical Minimum (0), */
582dd438cdSDavid Yang 0x25, 0x01, /* Logical Maximum (1), */
592dd438cdSDavid Yang 0x75, 0x01, /* Report Size (1), */
602dd438cdSDavid Yang 0x95, 0x04, /* Report Count (4), */
612dd438cdSDavid Yang 0x81, 0x02, /* Input (Variable), */
622dd438cdSDavid Yang 0x95, 0x34, /* Report Count (52), */
632dd438cdSDavid Yang 0x81, 0x01, /* Input (Constant), */
642dd438cdSDavid Yang 0xC0 /* End Collection */
652dd438cdSDavid Yang };
662dd438cdSDavid Yang
672dd438cdSDavid Yang static const __u8 easypen_m406w_control_rdesc[] = {
682dd438cdSDavid Yang 0x05, 0x0C, /* Usage Page (Consumer), */
692dd438cdSDavid Yang 0x09, 0x01, /* Usage (Consumer Control), */
702dd438cdSDavid Yang 0xA1, 0x01, /* Collection (Application), */
712dd438cdSDavid Yang 0x85, 0x12, /* Report ID (18), */
722dd438cdSDavid Yang 0x0A, 0x6A, 0x02, /* Usage (AC Delete), */
732dd438cdSDavid Yang 0x0A, 0x1A, 0x02, /* Usage (AC Undo), */
742dd438cdSDavid Yang 0x0A, 0x01, 0x02, /* Usage (AC New), */
752dd438cdSDavid Yang 0x09, 0x40, /* Usage (Menu), */
762dd438cdSDavid Yang 0x14, /* Logical Minimum (0), */
772dd438cdSDavid Yang 0x25, 0x01, /* Logical Maximum (1), */
782dd438cdSDavid Yang 0x75, 0x01, /* Report Size (1), */
792dd438cdSDavid Yang 0x95, 0x04, /* Report Count (4), */
802dd438cdSDavid Yang 0x81, 0x02, /* Input (Variable), */
812dd438cdSDavid Yang 0x95, 0x34, /* Report Count (52), */
822dd438cdSDavid Yang 0x81, 0x01, /* Input (Constant), */
832dd438cdSDavid Yang 0xC0 /* End Collection */
842dd438cdSDavid Yang };
852dd438cdSDavid Yang
864782c0e0SDavid Yang static const __u8 easypen_m610x_control_rdesc[] = {
8722ca20b2SNikolai Kondrashov 0x05, 0x0C, /* Usage Page (Consumer), */
8822ca20b2SNikolai Kondrashov 0x09, 0x01, /* Usage (Consumer Control), */
8922ca20b2SNikolai Kondrashov 0xA1, 0x01, /* Collection (Application), */
9022ca20b2SNikolai Kondrashov 0x85, 0x12, /* Report ID (18), */
9122ca20b2SNikolai Kondrashov 0x0A, 0x1A, 0x02, /* Usage (AC Undo), */
9222ca20b2SNikolai Kondrashov 0x0A, 0x79, 0x02, /* Usage (AC Redo Or Repeat), */
9322ca20b2SNikolai Kondrashov 0x0A, 0x2D, 0x02, /* Usage (AC Zoom In), */
9422ca20b2SNikolai Kondrashov 0x0A, 0x2E, 0x02, /* Usage (AC Zoom Out), */
954782c0e0SDavid Yang 0x14, /* Logical Minimum (0), */
964782c0e0SDavid Yang 0x25, 0x01, /* Logical Maximum (1), */
974782c0e0SDavid Yang 0x75, 0x01, /* Report Size (1), */
984782c0e0SDavid Yang 0x95, 0x04, /* Report Count (4), */
9922ca20b2SNikolai Kondrashov 0x81, 0x02, /* Input (Variable), */
1004782c0e0SDavid Yang 0x95, 0x34, /* Report Count (52), */
1014782c0e0SDavid Yang 0x81, 0x01, /* Input (Constant), */
10222ca20b2SNikolai Kondrashov 0xC0 /* End Collection */
10322ca20b2SNikolai Kondrashov };
10422ca20b2SNikolai Kondrashov
1054782c0e0SDavid Yang static const __u8 pensketch_m912_control_rdesc[] = {
106feb6faf1SMilan Plzik 0x05, 0x0C, /* Usage Page (Consumer), */
107feb6faf1SMilan Plzik 0x09, 0x01, /* Usage (Consumer Control), */
108feb6faf1SMilan Plzik 0xA1, 0x01, /* Collection (Application), */
109feb6faf1SMilan Plzik 0x85, 0x12, /* Report ID (18), */
110feb6faf1SMilan Plzik 0x14, /* Logical Minimum (0), */
111feb6faf1SMilan Plzik 0x25, 0x01, /* Logical Maximum (1), */
112feb6faf1SMilan Plzik 0x75, 0x01, /* Report Size (1), */
113feb6faf1SMilan Plzik 0x95, 0x08, /* Report Count (8), */
114feb6faf1SMilan Plzik 0x05, 0x0C, /* Usage Page (Consumer), */
115feb6faf1SMilan Plzik 0x0A, 0x6A, 0x02, /* Usage (AC Delete), */
116feb6faf1SMilan Plzik 0x0A, 0x1A, 0x02, /* Usage (AC Undo), */
117feb6faf1SMilan Plzik 0x0A, 0x01, 0x02, /* Usage (AC New), */
118feb6faf1SMilan Plzik 0x0A, 0x2F, 0x02, /* Usage (AC Zoom), */
119feb6faf1SMilan Plzik 0x0A, 0x25, 0x02, /* Usage (AC Forward), */
120feb6faf1SMilan Plzik 0x0A, 0x24, 0x02, /* Usage (AC Back), */
121feb6faf1SMilan Plzik 0x0A, 0x2D, 0x02, /* Usage (AC Zoom In), */
122feb6faf1SMilan Plzik 0x0A, 0x2E, 0x02, /* Usage (AC Zoom Out), */
123feb6faf1SMilan Plzik 0x81, 0x02, /* Input (Variable), */
124feb6faf1SMilan Plzik 0x95, 0x30, /* Report Count (48), */
125feb6faf1SMilan Plzik 0x81, 0x03, /* Input (Constant, Variable), */
126feb6faf1SMilan Plzik 0xC0 /* End Collection */
127feb6faf1SMilan Plzik };
128feb6faf1SMilan Plzik
1292dd438cdSDavid Yang static const __u8 mousepen_m508wx_control_rdesc[] = {
1302dd438cdSDavid Yang 0x05, 0x0C, /* Usage Page (Consumer), */
1312dd438cdSDavid Yang 0x09, 0x01, /* Usage (Consumer Control), */
1322dd438cdSDavid Yang 0xA1, 0x01, /* Collection (Application), */
1332dd438cdSDavid Yang 0x85, 0x12, /* Report ID (18), */
1342dd438cdSDavid Yang 0x0A, 0x1A, 0x02, /* Usage (AC Undo), */
1352dd438cdSDavid Yang 0x0A, 0x6A, 0x02, /* Usage (AC Delete), */
1362dd438cdSDavid Yang 0x0A, 0x2D, 0x02, /* Usage (AC Zoom In), */
1372dd438cdSDavid Yang 0x0A, 0x2E, 0x02, /* Usage (AC Zoom Out), */
1382dd438cdSDavid Yang 0x14, /* Logical Minimum (0), */
1392dd438cdSDavid Yang 0x25, 0x01, /* Logical Maximum (1), */
1402dd438cdSDavid Yang 0x75, 0x01, /* Report Size (1), */
1412dd438cdSDavid Yang 0x95, 0x04, /* Report Count (4), */
1422dd438cdSDavid Yang 0x81, 0x02, /* Input (Variable), */
1432dd438cdSDavid Yang 0x95, 0x34, /* Report Count (52), */
1442dd438cdSDavid Yang 0x81, 0x01, /* Input (Constant), */
1452dd438cdSDavid Yang 0xC0 /* End Collection */
1462dd438cdSDavid Yang };
1472dd438cdSDavid Yang
1482dd438cdSDavid Yang static const __u8 mousepen_m508x_control_rdesc[] = {
1492dd438cdSDavid Yang 0x05, 0x0C, /* Usage Page (Consumer), */
1502dd438cdSDavid Yang 0x09, 0x01, /* Usage (Consumer Control), */
1512dd438cdSDavid Yang 0xA1, 0x01, /* Collection (Application), */
1522dd438cdSDavid Yang 0x85, 0x12, /* Report ID (18), */
1532dd438cdSDavid Yang 0x0A, 0x01, 0x02, /* Usage (AC New), */
1542dd438cdSDavid Yang 0x09, 0x40, /* Usage (Menu), */
1552dd438cdSDavid Yang 0x0A, 0x6A, 0x02, /* Usage (AC Delete), */
1562dd438cdSDavid Yang 0x0A, 0x1A, 0x02, /* Usage (AC Undo), */
1572dd438cdSDavid Yang 0x14, /* Logical Minimum (0), */
1582dd438cdSDavid Yang 0x25, 0x01, /* Logical Maximum (1), */
1592dd438cdSDavid Yang 0x75, 0x01, /* Report Size (1), */
1602dd438cdSDavid Yang 0x95, 0x04, /* Report Count (4), */
1612dd438cdSDavid Yang 0x81, 0x02, /* Input (Variable), */
1622dd438cdSDavid Yang 0x81, 0x01, /* Input (Constant), */
1632dd438cdSDavid Yang 0x15, 0xFF, /* Logical Minimum (-1), */
1642dd438cdSDavid Yang 0x95, 0x10, /* Report Count (16), */
1652dd438cdSDavid Yang 0x81, 0x01, /* Input (Constant), */
1662dd438cdSDavid Yang 0x0A, 0x35, 0x02, /* Usage (AC Scroll), */
1672dd438cdSDavid Yang 0x0A, 0x2F, 0x02, /* Usage (AC Zoom), */
1682dd438cdSDavid Yang 0x0A, 0x38, 0x02, /* Usage (AC Pan), */
1692dd438cdSDavid Yang 0x75, 0x08, /* Report Size (8), */
1702dd438cdSDavid Yang 0x95, 0x03, /* Report Count (3), */
1712dd438cdSDavid Yang 0x81, 0x06, /* Input (Variable, Relative), */
1722dd438cdSDavid Yang 0x95, 0x01, /* Report Count (1), */
1732dd438cdSDavid Yang 0x81, 0x01, /* Input (Constant), */
1742dd438cdSDavid Yang 0xC0 /* End Collection */
1752dd438cdSDavid Yang };
1762dd438cdSDavid Yang
1774782c0e0SDavid Yang static const __u8 easypen_m406xe_control_rdesc[] = {
1785e55e2aaSNikolai Kondrashov 0x05, 0x0C, /* Usage Page (Consumer), */
1795e55e2aaSNikolai Kondrashov 0x09, 0x01, /* Usage (Consumer Control), */
1805e55e2aaSNikolai Kondrashov 0xA1, 0x01, /* Collection (Application), */
1815e55e2aaSNikolai Kondrashov 0x85, 0x12, /* Report ID (18), */
1825e55e2aaSNikolai Kondrashov 0x14, /* Logical Minimum (0), */
1835e55e2aaSNikolai Kondrashov 0x25, 0x01, /* Logical Maximum (1), */
1845e55e2aaSNikolai Kondrashov 0x75, 0x01, /* Report Size (1), */
1855e55e2aaSNikolai Kondrashov 0x95, 0x04, /* Report Count (4), */
1865e55e2aaSNikolai Kondrashov 0x0A, 0x79, 0x02, /* Usage (AC Redo Or Repeat), */
1875e55e2aaSNikolai Kondrashov 0x0A, 0x1A, 0x02, /* Usage (AC Undo), */
1885e55e2aaSNikolai Kondrashov 0x0A, 0x2D, 0x02, /* Usage (AC Zoom In), */
1895e55e2aaSNikolai Kondrashov 0x0A, 0x2E, 0x02, /* Usage (AC Zoom Out), */
1905e55e2aaSNikolai Kondrashov 0x81, 0x02, /* Input (Variable), */
1915e55e2aaSNikolai Kondrashov 0x95, 0x34, /* Report Count (52), */
1925e55e2aaSNikolai Kondrashov 0x81, 0x03, /* Input (Constant, Variable), */
1935e55e2aaSNikolai Kondrashov 0xC0 /* End Collection */
1945e55e2aaSNikolai Kondrashov };
1955e55e2aaSNikolai Kondrashov
1962dd438cdSDavid Yang static const __u8 pensketch_t609a_control_rdesc[] = {
1972dd438cdSDavid Yang 0x05, 0x0C, /* Usage Page (Consumer), */
1982dd438cdSDavid Yang 0x09, 0x01, /* Usage (Consumer Control), */
1992dd438cdSDavid Yang 0xA1, 0x01, /* Collection (Application), */
2002dd438cdSDavid Yang 0x85, 0x12, /* Report ID (18), */
2012dd438cdSDavid Yang 0x0A, 0x6A, 0x02, /* Usage (AC Delete), */
2022dd438cdSDavid Yang 0x14, /* Logical Minimum (0), */
2032dd438cdSDavid Yang 0x25, 0x01, /* Logical Maximum (1), */
2042dd438cdSDavid Yang 0x75, 0x01, /* Report Size (1), */
2052dd438cdSDavid Yang 0x95, 0x08, /* Report Count (8), */
2062dd438cdSDavid Yang 0x81, 0x02, /* Input (Variable), */
2072dd438cdSDavid Yang 0x95, 0x37, /* Report Count (55), */
2082dd438cdSDavid Yang 0x81, 0x01, /* Input (Constant), */
2092dd438cdSDavid Yang 0xC0 /* End Collection */
2102dd438cdSDavid Yang };
2112dd438cdSDavid Yang
212*0f6fac2cSDavid Yang /* Fix indexes in kye_tablet_fixup if you change this */
2134782c0e0SDavid Yang static const __u8 kye_tablet_rdesc[] = {
2144782c0e0SDavid Yang 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */
2154782c0e0SDavid Yang 0x09, 0x01, /* Usage (01h), */
2164782c0e0SDavid Yang 0xA1, 0x01, /* Collection (Application), */
2174782c0e0SDavid Yang 0x85, 0x05, /* Report ID (5), */
2184782c0e0SDavid Yang 0x09, 0x01, /* Usage (01h), */
2194782c0e0SDavid Yang 0x15, 0x81, /* Logical Minimum (-127), */
2204782c0e0SDavid Yang 0x25, 0x7F, /* Logical Maximum (127), */
2214782c0e0SDavid Yang 0x75, 0x08, /* Report Size (8), */
2224782c0e0SDavid Yang 0x95, 0x07, /* Report Count (7), */
2234782c0e0SDavid Yang 0xB1, 0x02, /* Feature (Variable), */
2244782c0e0SDavid Yang 0xC0, /* End Collection, */
2254782c0e0SDavid Yang 0x05, 0x0D, /* Usage Page (Digitizer), */
2264782c0e0SDavid Yang 0x09, 0x01, /* Usage (Digitizer), */
2274782c0e0SDavid Yang 0xA1, 0x01, /* Collection (Application), */
2284782c0e0SDavid Yang 0x85, 0x10, /* Report ID (16), */
2294782c0e0SDavid Yang 0x09, 0x20, /* Usage (Stylus), */
2304782c0e0SDavid Yang 0xA0, /* Collection (Physical), */
2314782c0e0SDavid Yang 0x09, 0x42, /* Usage (Tip Switch), */
2324782c0e0SDavid Yang 0x09, 0x44, /* Usage (Barrel Switch), */
2334782c0e0SDavid Yang 0x09, 0x46, /* Usage (Tablet Pick), */
2344782c0e0SDavid Yang 0x14, /* Logical Minimum (0), */
2354782c0e0SDavid Yang 0x25, 0x01, /* Logical Maximum (1), */
2364782c0e0SDavid Yang 0x75, 0x01, /* Report Size (1), */
2374782c0e0SDavid Yang 0x95, 0x03, /* Report Count (3), */
2384782c0e0SDavid Yang 0x81, 0x02, /* Input (Variable), */
2394782c0e0SDavid Yang 0x95, 0x04, /* Report Count (4), */
2404782c0e0SDavid Yang 0x81, 0x01, /* Input (Constant), */
2414782c0e0SDavid Yang 0x09, 0x32, /* Usage (In Range), */
2424782c0e0SDavid Yang 0x95, 0x01, /* Report Count (1), */
2434782c0e0SDavid Yang 0x81, 0x02, /* Input (Variable), */
2444782c0e0SDavid Yang 0x75, 0x10, /* Report Size (16), */
2454782c0e0SDavid Yang 0xA4, /* Push, */
2464782c0e0SDavid Yang 0x05, 0x01, /* Usage Page (Desktop), */
2474782c0e0SDavid Yang 0x09, 0x30, /* Usage (X), */
2484782c0e0SDavid Yang 0x27, 0xFF, 0x7F, 0x00, 0x00, /* Logical Maximum (32767), */
2494782c0e0SDavid Yang 0x34, /* Physical Minimum (0), */
2504782c0e0SDavid Yang 0x47, 0x00, 0x00, 0x00, 0x00, /* Physical Maximum (0), */
2514782c0e0SDavid Yang 0x65, 0x11, /* Unit (Centimeter), */
2524782c0e0SDavid Yang 0x55, 0x00, /* Unit Exponent (0), */
2534782c0e0SDavid Yang 0x75, 0x10, /* Report Size (16), */
2544782c0e0SDavid Yang 0x81, 0x02, /* Input (Variable), */
2554782c0e0SDavid Yang 0x09, 0x31, /* Usage (Y), */
2564782c0e0SDavid Yang 0x27, 0xFF, 0x7F, 0x00, 0x00, /* Logical Maximum (32767), */
2574782c0e0SDavid Yang 0x47, 0x00, 0x00, 0x00, 0x00, /* Physical Maximum (0), */
2584782c0e0SDavid Yang 0x81, 0x02, /* Input (Variable), */
2594782c0e0SDavid Yang 0xB4, /* Pop, */
2604782c0e0SDavid Yang 0x05, 0x0D, /* Usage Page (Digitizer), */
2614782c0e0SDavid Yang 0x09, 0x30, /* Usage (Tip Pressure), */
2624782c0e0SDavid Yang 0x27, 0xFF, 0x07, 0x00, 0x00, /* Logical Maximum (2047), */
2634782c0e0SDavid Yang 0x81, 0x02, /* Input (Variable), */
2644782c0e0SDavid Yang 0xC0, /* End Collection, */
2654782c0e0SDavid Yang 0xC0, /* End Collection, */
2664782c0e0SDavid Yang 0x05, 0x0D, /* Usage Page (Digitizer), */
2674782c0e0SDavid Yang 0x09, 0x21, /* Usage (Puck), */
2684782c0e0SDavid Yang 0xA1, 0x01, /* Collection (Application), */
2694782c0e0SDavid Yang 0x85, 0x11, /* Report ID (17), */
2704782c0e0SDavid Yang 0x09, 0x21, /* Usage (Puck), */
2714782c0e0SDavid Yang 0xA0, /* Collection (Physical), */
2724782c0e0SDavid Yang 0x05, 0x09, /* Usage Page (Button), */
2734782c0e0SDavid Yang 0x19, 0x01, /* Usage Minimum (01h), */
2744782c0e0SDavid Yang 0x29, 0x03, /* Usage Maximum (03h), */
2754782c0e0SDavid Yang 0x14, /* Logical Minimum (0), */
2764782c0e0SDavid Yang 0x25, 0x01, /* Logical Maximum (1), */
2774782c0e0SDavid Yang 0x75, 0x01, /* Report Size (1), */
2784782c0e0SDavid Yang 0x95, 0x03, /* Report Count (3), */
2794782c0e0SDavid Yang 0x81, 0x02, /* Input (Variable), */
2804782c0e0SDavid Yang 0x95, 0x04, /* Report Count (4), */
2814782c0e0SDavid Yang 0x81, 0x01, /* Input (Constant), */
2824782c0e0SDavid Yang 0x05, 0x0D, /* Usage Page (Digitizer), */
2834782c0e0SDavid Yang 0x09, 0x32, /* Usage (In Range), */
2844782c0e0SDavid Yang 0x95, 0x01, /* Report Count (1), */
2854782c0e0SDavid Yang 0x81, 0x02, /* Input (Variable), */
2864782c0e0SDavid Yang 0x05, 0x01, /* Usage Page (Desktop), */
2874782c0e0SDavid Yang 0xA4, /* Push, */
2884782c0e0SDavid Yang 0x09, 0x30, /* Usage (X), */
2894782c0e0SDavid Yang 0x27, 0xFF, 0x7F, 0x00, 0x00, /* Logical Maximum (32767), */
2904782c0e0SDavid Yang 0x34, /* Physical Minimum (0), */
2914782c0e0SDavid Yang 0x47, 0x00, 0x00, 0x00, 0x00, /* Physical Maximum (0), */
2924782c0e0SDavid Yang 0x65, 0x11, /* Unit (Centimeter), */
2934782c0e0SDavid Yang 0x55, 0x00, /* Unit Exponent (0), */
2944782c0e0SDavid Yang 0x75, 0x10, /* Report Size (16), */
2954782c0e0SDavid Yang 0x81, 0x02, /* Input (Variable), */
2964782c0e0SDavid Yang 0x09, 0x31, /* Usage (Y), */
2974782c0e0SDavid Yang 0x27, 0xFF, 0x7F, 0x00, 0x00, /* Logical Maximum (32767), */
2984782c0e0SDavid Yang 0x47, 0x00, 0x00, 0x00, 0x00, /* Physical Maximum (0), */
2994782c0e0SDavid Yang 0x81, 0x02, /* Input (Variable), */
3004782c0e0SDavid Yang 0xB4, /* Pop, */
3014782c0e0SDavid Yang 0x09, 0x38, /* Usage (Wheel), */
3024782c0e0SDavid Yang 0x15, 0xFF, /* Logical Minimum (-1), */
3034782c0e0SDavid Yang 0x75, 0x08, /* Report Size (8), */
3044782c0e0SDavid Yang 0x95, 0x01, /* Report Count (1), */
3054782c0e0SDavid Yang 0x81, 0x06, /* Input (Variable, Relative), */
3064782c0e0SDavid Yang 0x81, 0x01, /* Input (Constant), */
3074782c0e0SDavid Yang 0xC0, /* End Collection, */
3084782c0e0SDavid Yang 0xC0 /* End Collection */
3094782c0e0SDavid Yang };
3104782c0e0SDavid Yang
311b8cd2d96SDavid Yang static const struct kye_tablet_info {
312b8cd2d96SDavid Yang __u32 product;
313b8cd2d96SDavid Yang __s32 x_logical_maximum;
314b8cd2d96SDavid Yang __s32 y_logical_maximum;
315b8cd2d96SDavid Yang __s32 pressure_logical_maximum;
316b8cd2d96SDavid Yang __s32 x_physical_maximum;
317b8cd2d96SDavid Yang __s32 y_physical_maximum;
318b8cd2d96SDavid Yang __s8 unit_exponent;
319b8cd2d96SDavid Yang __s8 unit;
320b8cd2d96SDavid Yang bool has_punk;
321b8cd2d96SDavid Yang unsigned int control_rsize;
322b8cd2d96SDavid Yang const __u8 *control_rdesc;
323b8cd2d96SDavid Yang } kye_tablets_info[] = {
3242dd438cdSDavid Yang {USB_DEVICE_ID_KYE_EASYPEN_M406, /* 0x5005 */
3252dd438cdSDavid Yang 15360, 10240, 1023, 6, 4, 0, 0x13, false,
3262dd438cdSDavid Yang sizeof(easypen_m406_control_rdesc), easypen_m406_control_rdesc},
3272dd438cdSDavid Yang {USB_DEVICE_ID_KYE_EASYPEN_M506, /* 0x500F */
3282dd438cdSDavid Yang 24576, 20480, 1023, 6, 5, 0, 0x13, false,
3292dd438cdSDavid Yang sizeof(easypen_m506_control_rdesc), easypen_m506_control_rdesc},
3304782c0e0SDavid Yang {USB_DEVICE_ID_KYE_EASYPEN_I405X, /* 0x5010 */
3314782c0e0SDavid Yang 14080, 10240, 1023, 55, 40, -1, 0x13, false},
3324782c0e0SDavid Yang {USB_DEVICE_ID_KYE_MOUSEPEN_I608X, /* 0x5011 */
3334782c0e0SDavid Yang 20480, 15360, 2047, 8, 6, 0, 0x13, true},
3342dd438cdSDavid Yang {USB_DEVICE_ID_KYE_EASYPEN_M406W, /* 0x5012 */
3352dd438cdSDavid Yang 15360, 10240, 1023, 6, 4, 0, 0x13, false,
3362dd438cdSDavid Yang sizeof(easypen_m406w_control_rdesc), easypen_m406w_control_rdesc},
3374782c0e0SDavid Yang {USB_DEVICE_ID_KYE_EASYPEN_M610X, /* 0x5013 */
3384782c0e0SDavid Yang 40960, 25600, 1023, 1000, 625, -2, 0x13, false,
3394782c0e0SDavid Yang sizeof(easypen_m610x_control_rdesc), easypen_m610x_control_rdesc},
3402dd438cdSDavid Yang {USB_DEVICE_ID_KYE_EASYPEN_340, /* 0x5014 */
3412dd438cdSDavid Yang 10240, 7680, 1023, 4, 3, 0, 0x13, false},
3424782c0e0SDavid Yang {USB_DEVICE_ID_KYE_PENSKETCH_M912, /* 0x5015 */
3434782c0e0SDavid Yang 61440, 46080, 2047, 12, 9, 0, 0x13, true,
3444782c0e0SDavid Yang sizeof(pensketch_m912_control_rdesc), pensketch_m912_control_rdesc},
3452dd438cdSDavid Yang {USB_DEVICE_ID_KYE_MOUSEPEN_M508WX, /* 0x5016 */
3462dd438cdSDavid Yang 40960, 25600, 2047, 8, 5, 0, 0x13, true,
3472dd438cdSDavid Yang sizeof(mousepen_m508wx_control_rdesc), mousepen_m508wx_control_rdesc},
3482dd438cdSDavid Yang {USB_DEVICE_ID_KYE_MOUSEPEN_M508X, /* 0x5017 */
3492dd438cdSDavid Yang 40960, 25600, 2047, 8, 5, 0, 0x13, true,
3502dd438cdSDavid Yang sizeof(mousepen_m508x_control_rdesc), mousepen_m508x_control_rdesc},
3514782c0e0SDavid Yang {USB_DEVICE_ID_KYE_EASYPEN_M406XE, /* 0x5019 */
3524782c0e0SDavid Yang 15360, 10240, 1023, 6, 4, 0, 0x13, false,
3534782c0e0SDavid Yang sizeof(easypen_m406xe_control_rdesc), easypen_m406xe_control_rdesc},
3544782c0e0SDavid Yang {USB_DEVICE_ID_KYE_MOUSEPEN_I608X_V2, /* 0x501A */
3554782c0e0SDavid Yang 40960, 30720, 2047, 8, 6, 0, 0x13, true},
3562dd438cdSDavid Yang {USB_DEVICE_ID_KYE_PENSKETCH_T609A, /* 0x501B */
3572dd438cdSDavid Yang 43520, 28160, 1023, 85, 55, -1, 0x13, false,
3582dd438cdSDavid Yang sizeof(pensketch_t609a_control_rdesc), pensketch_t609a_control_rdesc},
359b8cd2d96SDavid Yang {}
360b8cd2d96SDavid Yang };
361b8cd2d96SDavid Yang
kye_consumer_control_fixup(struct hid_device * hdev,__u8 * rdesc,unsigned int * rsize,int offset,const char * device_name)3620adb9c2cSBenjamin Tissoires static __u8 *kye_consumer_control_fixup(struct hid_device *hdev, __u8 *rdesc,
363b8cd2d96SDavid Yang unsigned int *rsize, int offset, const char *device_name)
364b8cd2d96SDavid Yang {
3650adb9c2cSBenjamin Tissoires /*
3660adb9c2cSBenjamin Tissoires * the fixup that need to be done:
3673f8b6fb7SMasahiro Yamada * - change Usage Maximum in the Consumer Control
3680adb9c2cSBenjamin Tissoires * (report ID 3) to a reasonable value
3690adb9c2cSBenjamin Tissoires */
3700adb9c2cSBenjamin Tissoires if (*rsize >= offset + 31 &&
3710adb9c2cSBenjamin Tissoires /* Usage Page (Consumer Devices) */
3720adb9c2cSBenjamin Tissoires rdesc[offset] == 0x05 && rdesc[offset + 1] == 0x0c &&
3730adb9c2cSBenjamin Tissoires /* Usage (Consumer Control) */
3740adb9c2cSBenjamin Tissoires rdesc[offset + 2] == 0x09 && rdesc[offset + 3] == 0x01 &&
3750adb9c2cSBenjamin Tissoires /* Usage Maximum > 12287 */
3760adb9c2cSBenjamin Tissoires rdesc[offset + 10] == 0x2a && rdesc[offset + 12] > 0x2f) {
3770adb9c2cSBenjamin Tissoires hid_info(hdev, "fixing up %s report descriptor\n", device_name);
3780adb9c2cSBenjamin Tissoires rdesc[offset + 12] = 0x2f;
3790adb9c2cSBenjamin Tissoires }
3800adb9c2cSBenjamin Tissoires return rdesc;
3810adb9c2cSBenjamin Tissoires }
3820adb9c2cSBenjamin Tissoires
383b8cd2d96SDavid Yang /*
384b8cd2d96SDavid Yang * Fix tablet descriptor of so-called "DataFormat 2".
385b8cd2d96SDavid Yang *
386b8cd2d96SDavid Yang * Though we may achieve a usable descriptor from original vendor-defined one,
387b8cd2d96SDavid Yang * some problems exist:
388b8cd2d96SDavid Yang * - Their Logical Maximum never exceed 32767 (7F FF), though device do report
389b8cd2d96SDavid Yang * values greater than that;
390b8cd2d96SDavid Yang * - Physical Maximums are arbitrarily filled (always equal to Logical
391b8cd2d96SDavid Yang * Maximum);
392b8cd2d96SDavid Yang * - Detail for control buttons are not provided (a vendor-defined Usage Page
393b8cd2d96SDavid Yang * with fixed content).
394b8cd2d96SDavid Yang *
395b8cd2d96SDavid Yang * Thus we use a pre-defined parameter table rather than digging it from
396b8cd2d96SDavid Yang * original descriptor.
397b8cd2d96SDavid Yang *
398b8cd2d96SDavid Yang * We may as well write a fallback routine for unrecognized kye tablet, but it's
399b8cd2d96SDavid Yang * clear kye are unlikely to produce new models in the foreseeable future, so we
400b8cd2d96SDavid Yang * simply enumerate all possible models.
401b8cd2d96SDavid Yang */
kye_tablet_fixup(struct hid_device * hdev,__u8 * rdesc,unsigned int * rsize)402b8cd2d96SDavid Yang static __u8 *kye_tablet_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize)
403b8cd2d96SDavid Yang {
404b8cd2d96SDavid Yang const struct kye_tablet_info *info;
405b8cd2d96SDavid Yang unsigned int newsize;
406b8cd2d96SDavid Yang
407b8cd2d96SDavid Yang if (*rsize < sizeof(kye_tablet_rdesc)) {
408b8cd2d96SDavid Yang hid_warn(hdev,
409b8cd2d96SDavid Yang "tablet report size too small, or kye_tablet_rdesc unexpectedly large\n");
410b8cd2d96SDavid Yang return rdesc;
411b8cd2d96SDavid Yang }
412b8cd2d96SDavid Yang
413b8cd2d96SDavid Yang for (info = kye_tablets_info; info->product; info++) {
414b8cd2d96SDavid Yang if (hdev->product == info->product)
415b8cd2d96SDavid Yang break;
416b8cd2d96SDavid Yang }
417b8cd2d96SDavid Yang
418b8cd2d96SDavid Yang if (!info->product) {
419b8cd2d96SDavid Yang hid_err(hdev, "tablet unknown, someone forget to add kye_tablet_info entry?\n");
420b8cd2d96SDavid Yang return rdesc;
421b8cd2d96SDavid Yang }
422b8cd2d96SDavid Yang
423b8cd2d96SDavid Yang newsize = info->has_punk ? sizeof(kye_tablet_rdesc) : 112;
424b8cd2d96SDavid Yang memcpy(rdesc, kye_tablet_rdesc, newsize);
425b8cd2d96SDavid Yang
426b8cd2d96SDavid Yang put_unaligned_le32(info->x_logical_maximum, rdesc + 66);
427b8cd2d96SDavid Yang put_unaligned_le32(info->x_physical_maximum, rdesc + 72);
428b8cd2d96SDavid Yang rdesc[77] = info->unit;
429b8cd2d96SDavid Yang rdesc[79] = info->unit_exponent;
430b8cd2d96SDavid Yang put_unaligned_le32(info->y_logical_maximum, rdesc + 87);
431b8cd2d96SDavid Yang put_unaligned_le32(info->y_physical_maximum, rdesc + 92);
432b8cd2d96SDavid Yang put_unaligned_le32(info->pressure_logical_maximum, rdesc + 104);
433b8cd2d96SDavid Yang
434b8cd2d96SDavid Yang if (info->has_punk) {
435b8cd2d96SDavid Yang put_unaligned_le32(info->x_logical_maximum, rdesc + 156);
436b8cd2d96SDavid Yang put_unaligned_le32(info->x_physical_maximum, rdesc + 162);
437b8cd2d96SDavid Yang rdesc[167] = info->unit;
438b8cd2d96SDavid Yang rdesc[169] = info->unit_exponent;
439b8cd2d96SDavid Yang put_unaligned_le32(info->y_logical_maximum, rdesc + 177);
440b8cd2d96SDavid Yang put_unaligned_le32(info->y_physical_maximum, rdesc + 182);
441b8cd2d96SDavid Yang }
442b8cd2d96SDavid Yang
443b8cd2d96SDavid Yang if (info->control_rsize) {
444b8cd2d96SDavid Yang if (newsize + info->control_rsize > *rsize)
445b8cd2d96SDavid Yang hid_err(hdev, "control rdesc unexpectedly large");
446b8cd2d96SDavid Yang else {
447b8cd2d96SDavid Yang memcpy(rdesc + newsize, info->control_rdesc, info->control_rsize);
448b8cd2d96SDavid Yang newsize += info->control_rsize;
449b8cd2d96SDavid Yang }
450b8cd2d96SDavid Yang }
451b8cd2d96SDavid Yang
452b8cd2d96SDavid Yang *rsize = newsize;
453b8cd2d96SDavid Yang return rdesc;
454b8cd2d96SDavid Yang }
455b8cd2d96SDavid Yang
kye_report_fixup(struct hid_device * hdev,__u8 * rdesc,unsigned int * rsize)45673e4008dSNikolai Kondrashov static __u8 *kye_report_fixup(struct hid_device *hdev, __u8 *rdesc,
45773e4008dSNikolai Kondrashov unsigned int *rsize)
45879422741SJiri Kosina {
45922ca20b2SNikolai Kondrashov switch (hdev->product) {
46022ca20b2SNikolai Kondrashov case USB_DEVICE_ID_KYE_ERGO_525V:
46122ca20b2SNikolai Kondrashov /* the fixups that need to be done:
46222ca20b2SNikolai Kondrashov * - change led usage page to button for extra buttons
46322ca20b2SNikolai Kondrashov * - report size 8 count 1 must be size 1 count 8 for button
46422ca20b2SNikolai Kondrashov * bitfield
46522ca20b2SNikolai Kondrashov * - change the button usage range to 4-7 for the extra
46622ca20b2SNikolai Kondrashov * buttons
46722ca20b2SNikolai Kondrashov */
4684ab25786SJiri Kosina if (*rsize >= 75 &&
46979422741SJiri Kosina rdesc[61] == 0x05 && rdesc[62] == 0x08 &&
47079422741SJiri Kosina rdesc[63] == 0x19 && rdesc[64] == 0x08 &&
47179422741SJiri Kosina rdesc[65] == 0x29 && rdesc[66] == 0x0f &&
47279422741SJiri Kosina rdesc[71] == 0x75 && rdesc[72] == 0x08 &&
47379422741SJiri Kosina rdesc[73] == 0x95 && rdesc[74] == 0x01) {
4744291ee30SJoe Perches hid_info(hdev,
47522ca20b2SNikolai Kondrashov "fixing up Kye/Genius Ergo Mouse "
47622ca20b2SNikolai Kondrashov "report descriptor\n");
47779422741SJiri Kosina rdesc[62] = 0x09;
47879422741SJiri Kosina rdesc[64] = 0x04;
47979422741SJiri Kosina rdesc[66] = 0x07;
48079422741SJiri Kosina rdesc[72] = 0x01;
48179422741SJiri Kosina rdesc[74] = 0x08;
48279422741SJiri Kosina }
48322ca20b2SNikolai Kondrashov break;
4848c7b79bcSDavid Yang case USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE:
4858c7b79bcSDavid Yang rdesc = kye_consumer_control_fixup(hdev, rdesc, rsize, 104,
4868c7b79bcSDavid Yang "Genius Gila Gaming Mouse");
4878c7b79bcSDavid Yang break;
4888c7b79bcSDavid Yang case USB_DEVICE_ID_GENIUS_MANTICORE:
4898c7b79bcSDavid Yang rdesc = kye_consumer_control_fixup(hdev, rdesc, rsize, 104,
4908c7b79bcSDavid Yang "Genius Manticore Keyboard");
4918c7b79bcSDavid Yang break;
4928c7b79bcSDavid Yang case USB_DEVICE_ID_GENIUS_GX_IMPERATOR:
4938c7b79bcSDavid Yang rdesc = kye_consumer_control_fixup(hdev, rdesc, rsize, 83,
4948c7b79bcSDavid Yang "Genius Gx Imperator Keyboard");
4958c7b79bcSDavid Yang break;
496*0f6fac2cSDavid Yang case USB_DEVICE_ID_KYE_EASYPEN_M406:
497*0f6fac2cSDavid Yang case USB_DEVICE_ID_KYE_EASYPEN_M506:
49822ca20b2SNikolai Kondrashov case USB_DEVICE_ID_KYE_EASYPEN_I405X:
49922ca20b2SNikolai Kondrashov case USB_DEVICE_ID_KYE_MOUSEPEN_I608X:
500*0f6fac2cSDavid Yang case USB_DEVICE_ID_KYE_EASYPEN_M406W:
50122ca20b2SNikolai Kondrashov case USB_DEVICE_ID_KYE_EASYPEN_M610X:
502*0f6fac2cSDavid Yang case USB_DEVICE_ID_KYE_EASYPEN_340:
503feb6faf1SMilan Plzik case USB_DEVICE_ID_KYE_PENSKETCH_M912:
504*0f6fac2cSDavid Yang case USB_DEVICE_ID_KYE_MOUSEPEN_M508WX:
505*0f6fac2cSDavid Yang case USB_DEVICE_ID_KYE_MOUSEPEN_M508X:
506*0f6fac2cSDavid Yang case USB_DEVICE_ID_KYE_EASYPEN_M406XE:
507*0f6fac2cSDavid Yang case USB_DEVICE_ID_KYE_MOUSEPEN_I608X_V2:
508*0f6fac2cSDavid Yang case USB_DEVICE_ID_KYE_PENSKETCH_T609A:
5094782c0e0SDavid Yang rdesc = kye_tablet_fixup(hdev, rdesc, rsize);
510feb6faf1SMilan Plzik break;
51122ca20b2SNikolai Kondrashov }
51273e4008dSNikolai Kondrashov return rdesc;
51379422741SJiri Kosina }
51479422741SJiri Kosina
kye_tablet_enable(struct hid_device * hdev)51522ca20b2SNikolai Kondrashov static int kye_tablet_enable(struct hid_device *hdev)
51622ca20b2SNikolai Kondrashov {
51722ca20b2SNikolai Kondrashov struct list_head *list;
51822ca20b2SNikolai Kondrashov struct list_head *head;
51922ca20b2SNikolai Kondrashov struct hid_report *report;
52022ca20b2SNikolai Kondrashov __s32 *value;
52122ca20b2SNikolai Kondrashov
52222ca20b2SNikolai Kondrashov list = &hdev->report_enum[HID_FEATURE_REPORT].report_list;
52322ca20b2SNikolai Kondrashov list_for_each(head, list) {
52422ca20b2SNikolai Kondrashov report = list_entry(head, struct hid_report, list);
52522ca20b2SNikolai Kondrashov if (report->id == 5)
52622ca20b2SNikolai Kondrashov break;
52722ca20b2SNikolai Kondrashov }
52822ca20b2SNikolai Kondrashov
52922ca20b2SNikolai Kondrashov if (head == list) {
53022ca20b2SNikolai Kondrashov hid_err(hdev, "tablet-enabling feature report not found\n");
53122ca20b2SNikolai Kondrashov return -ENODEV;
53222ca20b2SNikolai Kondrashov }
53322ca20b2SNikolai Kondrashov
53422ca20b2SNikolai Kondrashov if (report->maxfield < 1 || report->field[0]->report_count < 7) {
53522ca20b2SNikolai Kondrashov hid_err(hdev, "invalid tablet-enabling feature report\n");
53622ca20b2SNikolai Kondrashov return -ENODEV;
53722ca20b2SNikolai Kondrashov }
53822ca20b2SNikolai Kondrashov
53922ca20b2SNikolai Kondrashov value = report->field[0]->value;
54022ca20b2SNikolai Kondrashov
541b8cd2d96SDavid Yang /*
542b8cd2d96SDavid Yang * The code is for DataFormat 2 of config xml. They have no obvious
543b8cd2d96SDavid Yang * meaning (at least not configurable in Windows driver) except enabling
544b8cd2d96SDavid Yang * fully-functional tablet mode (absolute positioning). Otherwise, the
545b8cd2d96SDavid Yang * tablet acts like a relative mouse.
546b8cd2d96SDavid Yang *
547b8cd2d96SDavid Yang * Though there're magic codes for DataFormat 3 and 4, no devices use
548b8cd2d96SDavid Yang * these DataFormats.
549b8cd2d96SDavid Yang */
55022ca20b2SNikolai Kondrashov value[0] = 0x12;
55122ca20b2SNikolai Kondrashov value[1] = 0x10;
55222ca20b2SNikolai Kondrashov value[2] = 0x11;
55322ca20b2SNikolai Kondrashov value[3] = 0x12;
55422ca20b2SNikolai Kondrashov value[4] = 0x00;
55522ca20b2SNikolai Kondrashov value[5] = 0x00;
55622ca20b2SNikolai Kondrashov value[6] = 0x00;
557d8814272SBenjamin Tissoires hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
55822ca20b2SNikolai Kondrashov
55922ca20b2SNikolai Kondrashov return 0;
56022ca20b2SNikolai Kondrashov }
56122ca20b2SNikolai Kondrashov
kye_probe(struct hid_device * hdev,const struct hid_device_id * id)56222ca20b2SNikolai Kondrashov static int kye_probe(struct hid_device *hdev, const struct hid_device_id *id)
56322ca20b2SNikolai Kondrashov {
56422ca20b2SNikolai Kondrashov int ret;
56522ca20b2SNikolai Kondrashov
56622ca20b2SNikolai Kondrashov ret = hid_parse(hdev);
56722ca20b2SNikolai Kondrashov if (ret) {
56822ca20b2SNikolai Kondrashov hid_err(hdev, "parse failed\n");
56922ca20b2SNikolai Kondrashov goto err;
57022ca20b2SNikolai Kondrashov }
57122ca20b2SNikolai Kondrashov
57222ca20b2SNikolai Kondrashov ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
57322ca20b2SNikolai Kondrashov if (ret) {
57422ca20b2SNikolai Kondrashov hid_err(hdev, "hw start failed\n");
57522ca20b2SNikolai Kondrashov goto err;
57622ca20b2SNikolai Kondrashov }
57722ca20b2SNikolai Kondrashov
57822ca20b2SNikolai Kondrashov switch (id->product) {
5798a396321SBenjamin Tissoires case USB_DEVICE_ID_GENIUS_MANTICORE:
5808a396321SBenjamin Tissoires /*
5818a396321SBenjamin Tissoires * The manticore keyboard needs to have all the interfaces
5828a396321SBenjamin Tissoires * opened at least once to be fully functional.
5838a396321SBenjamin Tissoires */
5848a396321SBenjamin Tissoires if (hid_hw_open(hdev))
5858a396321SBenjamin Tissoires hid_hw_close(hdev);
5868a396321SBenjamin Tissoires break;
5872dd438cdSDavid Yang case USB_DEVICE_ID_KYE_EASYPEN_M406:
5882dd438cdSDavid Yang case USB_DEVICE_ID_KYE_EASYPEN_M506:
5898c7b79bcSDavid Yang case USB_DEVICE_ID_KYE_EASYPEN_I405X:
5908c7b79bcSDavid Yang case USB_DEVICE_ID_KYE_MOUSEPEN_I608X:
5912dd438cdSDavid Yang case USB_DEVICE_ID_KYE_EASYPEN_M406W:
5928c7b79bcSDavid Yang case USB_DEVICE_ID_KYE_EASYPEN_M610X:
5932dd438cdSDavid Yang case USB_DEVICE_ID_KYE_EASYPEN_340:
5948c7b79bcSDavid Yang case USB_DEVICE_ID_KYE_PENSKETCH_M912:
5952dd438cdSDavid Yang case USB_DEVICE_ID_KYE_MOUSEPEN_M508WX:
5962dd438cdSDavid Yang case USB_DEVICE_ID_KYE_MOUSEPEN_M508X:
5978c7b79bcSDavid Yang case USB_DEVICE_ID_KYE_EASYPEN_M406XE:
5988c7b79bcSDavid Yang case USB_DEVICE_ID_KYE_MOUSEPEN_I608X_V2:
5992dd438cdSDavid Yang case USB_DEVICE_ID_KYE_PENSKETCH_T609A:
6008c7b79bcSDavid Yang ret = kye_tablet_enable(hdev);
6018c7b79bcSDavid Yang if (ret) {
6028c7b79bcSDavid Yang hid_err(hdev, "tablet enabling failed\n");
6038c7b79bcSDavid Yang goto enabling_err;
6048c7b79bcSDavid Yang }
6058c7b79bcSDavid Yang break;
60622ca20b2SNikolai Kondrashov }
60722ca20b2SNikolai Kondrashov
60822ca20b2SNikolai Kondrashov return 0;
60922ca20b2SNikolai Kondrashov enabling_err:
61022ca20b2SNikolai Kondrashov hid_hw_stop(hdev);
61122ca20b2SNikolai Kondrashov err:
61222ca20b2SNikolai Kondrashov return ret;
61322ca20b2SNikolai Kondrashov }
61422ca20b2SNikolai Kondrashov
61579422741SJiri Kosina static const struct hid_device_id kye_devices[] = {
61679422741SJiri Kosina { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) },
61722ca20b2SNikolai Kondrashov { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
6188c7b79bcSDavid Yang USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE) },
6198c7b79bcSDavid Yang { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
6208c7b79bcSDavid Yang USB_DEVICE_ID_GENIUS_MANTICORE) },
6218c7b79bcSDavid Yang { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
6228c7b79bcSDavid Yang USB_DEVICE_ID_GENIUS_GX_IMPERATOR) },
6238c7b79bcSDavid Yang { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
6242dd438cdSDavid Yang USB_DEVICE_ID_KYE_EASYPEN_M406) },
6252dd438cdSDavid Yang { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
6262dd438cdSDavid Yang USB_DEVICE_ID_KYE_EASYPEN_M506) },
6272dd438cdSDavid Yang { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
62822ca20b2SNikolai Kondrashov USB_DEVICE_ID_KYE_EASYPEN_I405X) },
62922ca20b2SNikolai Kondrashov { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
63022ca20b2SNikolai Kondrashov USB_DEVICE_ID_KYE_MOUSEPEN_I608X) },
63122ca20b2SNikolai Kondrashov { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
6322dd438cdSDavid Yang USB_DEVICE_ID_KYE_EASYPEN_M406W) },
6332dd438cdSDavid Yang { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
63422ca20b2SNikolai Kondrashov USB_DEVICE_ID_KYE_EASYPEN_M610X) },
6353685c18eSBenjamin Tissoires { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
6362dd438cdSDavid Yang USB_DEVICE_ID_KYE_EASYPEN_340) },
6372dd438cdSDavid Yang { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
6388c7b79bcSDavid Yang USB_DEVICE_ID_KYE_PENSKETCH_M912) },
6398c7b79bcSDavid Yang { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
6402dd438cdSDavid Yang USB_DEVICE_ID_KYE_MOUSEPEN_M508WX) },
6412dd438cdSDavid Yang { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
6422dd438cdSDavid Yang USB_DEVICE_ID_KYE_MOUSEPEN_M508X) },
6432dd438cdSDavid Yang { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
6445e55e2aaSNikolai Kondrashov USB_DEVICE_ID_KYE_EASYPEN_M406XE) },
6455e55e2aaSNikolai Kondrashov { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
6468c7b79bcSDavid Yang USB_DEVICE_ID_KYE_MOUSEPEN_I608X_V2) },
6472dd438cdSDavid Yang { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
6482dd438cdSDavid Yang USB_DEVICE_ID_KYE_PENSKETCH_T609A) },
64979422741SJiri Kosina { }
65079422741SJiri Kosina };
65179422741SJiri Kosina MODULE_DEVICE_TABLE(hid, kye_devices);
65279422741SJiri Kosina
65379422741SJiri Kosina static struct hid_driver kye_driver = {
65479422741SJiri Kosina .name = "kye",
65579422741SJiri Kosina .id_table = kye_devices,
65622ca20b2SNikolai Kondrashov .probe = kye_probe,
65779422741SJiri Kosina .report_fixup = kye_report_fixup,
65879422741SJiri Kosina };
659f425458eSH Hartley Sweeten module_hid_driver(kye_driver);
66079422741SJiri Kosina
66179422741SJiri Kosina MODULE_LICENSE("GPL");
662