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