xref: /OK3568_Linux_fs/kernel/drivers/hid/hid-viewsonic.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0+
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  *  HID driver for ViewSonic devices not fully compliant with HID standard
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  *  Copyright (c) 2017 Nikolai Kondrashov
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun /*
9*4882a593Smuzhiyun  * This program is free software; you can redistribute it and/or modify it
10*4882a593Smuzhiyun  * under the terms of the GNU General Public License as published by the Free
11*4882a593Smuzhiyun  * Software Foundation; either version 2 of the License, or (at your option)
12*4882a593Smuzhiyun  * any later version.
13*4882a593Smuzhiyun  */
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun #include <linux/device.h>
16*4882a593Smuzhiyun #include <linux/hid.h>
17*4882a593Smuzhiyun #include <linux/module.h>
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun #include "hid-ids.h"
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun /* Size of the original descriptor of PD1011 signature pad */
22*4882a593Smuzhiyun #define PD1011_RDESC_ORIG_SIZE	408
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun /* Fixed report descriptor of PD1011 signature pad */
25*4882a593Smuzhiyun static __u8 pd1011_rdesc_fixed[] = {
26*4882a593Smuzhiyun 	0x05, 0x0D,             /*  Usage Page (Digitizer),             */
27*4882a593Smuzhiyun 	0x09, 0x02,             /*  Usage (Pen),                        */
28*4882a593Smuzhiyun 	0xA1, 0x01,             /*  Collection (Application),           */
29*4882a593Smuzhiyun 	0x85, 0x02,             /*      Report ID (2),                  */
30*4882a593Smuzhiyun 	0x09, 0x20,             /*      Usage (Stylus),                 */
31*4882a593Smuzhiyun 	0xA0,                   /*      Collection (Physical),          */
32*4882a593Smuzhiyun 	0x75, 0x10,             /*          Report Size (16),           */
33*4882a593Smuzhiyun 	0x95, 0x01,             /*          Report Count (1),           */
34*4882a593Smuzhiyun 	0xA4,                   /*          Push,                       */
35*4882a593Smuzhiyun 	0x05, 0x01,             /*          Usage Page (Desktop),       */
36*4882a593Smuzhiyun 	0x65, 0x13,             /*          Unit (Inch),                */
37*4882a593Smuzhiyun 	0x55, 0xFD,             /*          Unit Exponent (-3),         */
38*4882a593Smuzhiyun 	0x34,                   /*          Physical Minimum (0),       */
39*4882a593Smuzhiyun 	0x09, 0x30,             /*          Usage (X),                  */
40*4882a593Smuzhiyun 	0x46, 0x5D, 0x21,       /*          Physical Maximum (8541),    */
41*4882a593Smuzhiyun 	0x27, 0x80, 0xA9,
42*4882a593Smuzhiyun 		0x00, 0x00,     /*          Logical Maximum (43392),    */
43*4882a593Smuzhiyun 	0x81, 0x02,             /*          Input (Variable),           */
44*4882a593Smuzhiyun 	0x09, 0x31,             /*          Usage (Y),                  */
45*4882a593Smuzhiyun 	0x46, 0xDA, 0x14,       /*          Physical Maximum (5338),    */
46*4882a593Smuzhiyun 	0x26, 0xF0, 0x69,       /*          Logical Maximum (27120),    */
47*4882a593Smuzhiyun 	0x81, 0x02,             /*          Input (Variable),           */
48*4882a593Smuzhiyun 	0xB4,                   /*          Pop,                        */
49*4882a593Smuzhiyun 	0x14,                   /*          Logical Minimum (0),        */
50*4882a593Smuzhiyun 	0x25, 0x01,             /*          Logical Maximum (1),        */
51*4882a593Smuzhiyun 	0x75, 0x01,             /*          Report Size (1),            */
52*4882a593Smuzhiyun 	0x95, 0x01,             /*          Report Count (1),           */
53*4882a593Smuzhiyun 	0x81, 0x03,             /*          Input (Constant, Variable), */
54*4882a593Smuzhiyun 	0x09, 0x32,             /*          Usage (In Range),           */
55*4882a593Smuzhiyun 	0x09, 0x42,             /*          Usage (Tip Switch),         */
56*4882a593Smuzhiyun 	0x95, 0x02,             /*          Report Count (2),           */
57*4882a593Smuzhiyun 	0x81, 0x02,             /*          Input (Variable),           */
58*4882a593Smuzhiyun 	0x95, 0x05,             /*          Report Count (5),           */
59*4882a593Smuzhiyun 	0x81, 0x03,             /*          Input (Constant, Variable), */
60*4882a593Smuzhiyun 	0x75, 0x10,             /*          Report Size (16),           */
61*4882a593Smuzhiyun 	0x95, 0x01,             /*          Report Count (1),           */
62*4882a593Smuzhiyun 	0x09, 0x30,             /*          Usage (Tip Pressure),       */
63*4882a593Smuzhiyun 	0x15, 0x05,             /*          Logical Minimum (5),        */
64*4882a593Smuzhiyun 	0x26, 0xFF, 0x07,       /*          Logical Maximum (2047),     */
65*4882a593Smuzhiyun 	0x81, 0x02,             /*          Input (Variable),           */
66*4882a593Smuzhiyun 	0x75, 0x10,             /*          Report Size (16),           */
67*4882a593Smuzhiyun 	0x95, 0x01,             /*          Report Count (1),           */
68*4882a593Smuzhiyun 	0x81, 0x03,             /*          Input (Constant, Variable), */
69*4882a593Smuzhiyun 	0xC0,                   /*      End Collection,                 */
70*4882a593Smuzhiyun 	0xC0                    /*  End Collection                      */
71*4882a593Smuzhiyun };
72*4882a593Smuzhiyun 
viewsonic_report_fixup(struct hid_device * hdev,__u8 * rdesc,unsigned int * rsize)73*4882a593Smuzhiyun static __u8 *viewsonic_report_fixup(struct hid_device *hdev, __u8 *rdesc,
74*4882a593Smuzhiyun 				    unsigned int *rsize)
75*4882a593Smuzhiyun {
76*4882a593Smuzhiyun 	switch (hdev->product) {
77*4882a593Smuzhiyun 	case USB_DEVICE_ID_VIEWSONIC_PD1011:
78*4882a593Smuzhiyun 	case USB_DEVICE_ID_SIGNOTEC_VIEWSONIC_PD1011:
79*4882a593Smuzhiyun 		if (*rsize == PD1011_RDESC_ORIG_SIZE) {
80*4882a593Smuzhiyun 			rdesc = pd1011_rdesc_fixed;
81*4882a593Smuzhiyun 			*rsize = sizeof(pd1011_rdesc_fixed);
82*4882a593Smuzhiyun 		}
83*4882a593Smuzhiyun 		break;
84*4882a593Smuzhiyun 	}
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun 	return rdesc;
87*4882a593Smuzhiyun }
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun static const struct hid_device_id viewsonic_devices[] = {
90*4882a593Smuzhiyun 	{ HID_USB_DEVICE(USB_VENDOR_ID_VIEWSONIC,
91*4882a593Smuzhiyun 				USB_DEVICE_ID_VIEWSONIC_PD1011) },
92*4882a593Smuzhiyun 	{ HID_USB_DEVICE(USB_VENDOR_ID_SIGNOTEC,
93*4882a593Smuzhiyun 				USB_DEVICE_ID_SIGNOTEC_VIEWSONIC_PD1011) },
94*4882a593Smuzhiyun 	{ }
95*4882a593Smuzhiyun };
96*4882a593Smuzhiyun MODULE_DEVICE_TABLE(hid, viewsonic_devices);
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun static struct hid_driver viewsonic_driver = {
99*4882a593Smuzhiyun 	.name = "viewsonic",
100*4882a593Smuzhiyun 	.id_table = viewsonic_devices,
101*4882a593Smuzhiyun 	.report_fixup = viewsonic_report_fixup,
102*4882a593Smuzhiyun };
103*4882a593Smuzhiyun module_hid_driver(viewsonic_driver);
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun MODULE_LICENSE("GPL");
106