1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * HID driver for some ITE "special" devices
4*4882a593Smuzhiyun * Copyright (c) 2017 Hans de Goede <hdegoede@redhat.com>
5*4882a593Smuzhiyun */
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun #include <linux/device.h>
8*4882a593Smuzhiyun #include <linux/input.h>
9*4882a593Smuzhiyun #include <linux/hid.h>
10*4882a593Smuzhiyun #include <linux/module.h>
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun #include "hid-ids.h"
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun #define QUIRK_TOUCHPAD_ON_OFF_REPORT BIT(0)
15*4882a593Smuzhiyun
ite_report_fixup(struct hid_device * hdev,__u8 * rdesc,unsigned int * rsize)16*4882a593Smuzhiyun static __u8 *ite_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize)
17*4882a593Smuzhiyun {
18*4882a593Smuzhiyun unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun if (quirks & QUIRK_TOUCHPAD_ON_OFF_REPORT) {
21*4882a593Smuzhiyun /* For Acer Aspire Switch 10 SW5-012 keyboard-dock */
22*4882a593Smuzhiyun if (*rsize == 188 && rdesc[162] == 0x81 && rdesc[163] == 0x02) {
23*4882a593Smuzhiyun hid_info(hdev, "Fixing up Acer Sw5-012 ITE keyboard report descriptor\n");
24*4882a593Smuzhiyun rdesc[163] = HID_MAIN_ITEM_RELATIVE;
25*4882a593Smuzhiyun }
26*4882a593Smuzhiyun /* For Acer One S1002/S1003 keyboard-dock */
27*4882a593Smuzhiyun if (*rsize == 188 && rdesc[185] == 0x81 && rdesc[186] == 0x02) {
28*4882a593Smuzhiyun hid_info(hdev, "Fixing up Acer S1002/S1003 ITE keyboard report descriptor\n");
29*4882a593Smuzhiyun rdesc[186] = HID_MAIN_ITEM_RELATIVE;
30*4882a593Smuzhiyun }
31*4882a593Smuzhiyun /* For Acer Aspire Switch 10E (SW3-016) keyboard-dock */
32*4882a593Smuzhiyun if (*rsize == 210 && rdesc[184] == 0x81 && rdesc[185] == 0x02) {
33*4882a593Smuzhiyun hid_info(hdev, "Fixing up Acer Aspire Switch 10E (SW3-016) ITE keyboard report descriptor\n");
34*4882a593Smuzhiyun rdesc[185] = HID_MAIN_ITEM_RELATIVE;
35*4882a593Smuzhiyun }
36*4882a593Smuzhiyun }
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun return rdesc;
39*4882a593Smuzhiyun }
40*4882a593Smuzhiyun
ite_input_mapping(struct hid_device * hdev,struct hid_input * hi,struct hid_field * field,struct hid_usage * usage,unsigned long ** bit,int * max)41*4882a593Smuzhiyun static int ite_input_mapping(struct hid_device *hdev,
42*4882a593Smuzhiyun struct hid_input *hi, struct hid_field *field,
43*4882a593Smuzhiyun struct hid_usage *usage, unsigned long **bit,
44*4882a593Smuzhiyun int *max)
45*4882a593Smuzhiyun {
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun if ((quirks & QUIRK_TOUCHPAD_ON_OFF_REPORT) &&
50*4882a593Smuzhiyun (usage->hid & HID_USAGE_PAGE) == 0x00880000) {
51*4882a593Smuzhiyun if (usage->hid == 0x00880078) {
52*4882a593Smuzhiyun /* Touchpad on, userspace expects F22 for this */
53*4882a593Smuzhiyun hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_F22);
54*4882a593Smuzhiyun return 1;
55*4882a593Smuzhiyun }
56*4882a593Smuzhiyun if (usage->hid == 0x00880079) {
57*4882a593Smuzhiyun /* Touchpad off, userspace expects F23 for this */
58*4882a593Smuzhiyun hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_F23);
59*4882a593Smuzhiyun return 1;
60*4882a593Smuzhiyun }
61*4882a593Smuzhiyun return -1;
62*4882a593Smuzhiyun }
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun return 0;
65*4882a593Smuzhiyun }
66*4882a593Smuzhiyun
ite_event(struct hid_device * hdev,struct hid_field * field,struct hid_usage * usage,__s32 value)67*4882a593Smuzhiyun static int ite_event(struct hid_device *hdev, struct hid_field *field,
68*4882a593Smuzhiyun struct hid_usage *usage, __s32 value)
69*4882a593Smuzhiyun {
70*4882a593Smuzhiyun struct input_dev *input;
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput)
73*4882a593Smuzhiyun return 0;
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun input = field->hidinput->input;
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun /*
78*4882a593Smuzhiyun * The ITE8595 always reports 0 as value for the rfkill button. Luckily
79*4882a593Smuzhiyun * it is the only button in its report, and it sends a report on
80*4882a593Smuzhiyun * release only, so receiving a report means the button was pressed.
81*4882a593Smuzhiyun */
82*4882a593Smuzhiyun if (usage->hid == HID_GD_RFKILL_BTN) {
83*4882a593Smuzhiyun input_event(input, EV_KEY, KEY_RFKILL, 1);
84*4882a593Smuzhiyun input_sync(input);
85*4882a593Smuzhiyun input_event(input, EV_KEY, KEY_RFKILL, 0);
86*4882a593Smuzhiyun input_sync(input);
87*4882a593Smuzhiyun return 1;
88*4882a593Smuzhiyun }
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun return 0;
91*4882a593Smuzhiyun }
92*4882a593Smuzhiyun
ite_probe(struct hid_device * hdev,const struct hid_device_id * id)93*4882a593Smuzhiyun static int ite_probe(struct hid_device *hdev, const struct hid_device_id *id)
94*4882a593Smuzhiyun {
95*4882a593Smuzhiyun int ret;
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun hid_set_drvdata(hdev, (void *)id->driver_data);
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun ret = hid_open_report(hdev);
100*4882a593Smuzhiyun if (ret)
101*4882a593Smuzhiyun return ret;
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun return hid_hw_start(hdev, HID_CONNECT_DEFAULT);
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun static const struct hid_device_id ite_devices[] = {
107*4882a593Smuzhiyun { HID_USB_DEVICE(USB_VENDOR_ID_ITE, USB_DEVICE_ID_ITE8595) },
108*4882a593Smuzhiyun { HID_USB_DEVICE(USB_VENDOR_ID_258A, USB_DEVICE_ID_258A_6A88) },
109*4882a593Smuzhiyun /* ITE8595 USB kbd ctlr, with Synaptics touchpad connected to it. */
110*4882a593Smuzhiyun { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
111*4882a593Smuzhiyun USB_VENDOR_ID_SYNAPTICS,
112*4882a593Smuzhiyun USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5_012),
113*4882a593Smuzhiyun .driver_data = QUIRK_TOUCHPAD_ON_OFF_REPORT },
114*4882a593Smuzhiyun /* ITE8910 USB kbd ctlr, with Synaptics touchpad connected to it. */
115*4882a593Smuzhiyun { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
116*4882a593Smuzhiyun USB_VENDOR_ID_SYNAPTICS,
117*4882a593Smuzhiyun USB_DEVICE_ID_SYNAPTICS_ACER_ONE_S1002),
118*4882a593Smuzhiyun .driver_data = QUIRK_TOUCHPAD_ON_OFF_REPORT },
119*4882a593Smuzhiyun /* ITE8910 USB kbd ctlr, with Synaptics touchpad connected to it. */
120*4882a593Smuzhiyun { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
121*4882a593Smuzhiyun USB_VENDOR_ID_SYNAPTICS,
122*4882a593Smuzhiyun USB_DEVICE_ID_SYNAPTICS_ACER_ONE_S1003),
123*4882a593Smuzhiyun .driver_data = QUIRK_TOUCHPAD_ON_OFF_REPORT },
124*4882a593Smuzhiyun /* ITE8910 USB kbd ctlr, with Synaptics touchpad connected to it. */
125*4882a593Smuzhiyun { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
126*4882a593Smuzhiyun USB_VENDOR_ID_SYNAPTICS,
127*4882a593Smuzhiyun USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5_017),
128*4882a593Smuzhiyun .driver_data = QUIRK_TOUCHPAD_ON_OFF_REPORT },
129*4882a593Smuzhiyun { }
130*4882a593Smuzhiyun };
131*4882a593Smuzhiyun MODULE_DEVICE_TABLE(hid, ite_devices);
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun static struct hid_driver ite_driver = {
134*4882a593Smuzhiyun .name = "itetech",
135*4882a593Smuzhiyun .id_table = ite_devices,
136*4882a593Smuzhiyun .probe = ite_probe,
137*4882a593Smuzhiyun .report_fixup = ite_report_fixup,
138*4882a593Smuzhiyun .input_mapping = ite_input_mapping,
139*4882a593Smuzhiyun .event = ite_event,
140*4882a593Smuzhiyun };
141*4882a593Smuzhiyun module_hid_driver(ite_driver);
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun MODULE_LICENSE("GPL");
144