1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * HID driver for EVision devices 4 * For now, only ignore bogus consumer reports 5 * sent after the keyboard has been configured 6 * 7 * Copyright (c) 2022 Philippe Valembois 8 */ 9 10 #include <linux/device.h> 11 #include <linux/input.h> 12 #include <linux/hid.h> 13 #include <linux/module.h> 14 15 #include "hid-ids.h" 16 17 static int evision_input_mapping(struct hid_device *hdev, struct hid_input *hi, 18 struct hid_field *field, struct hid_usage *usage, 19 unsigned long **bit, int *max) 20 { 21 /* mapping only applies to USB_DEVICE_ID_EVISION_ICL01 */ 22 if (hdev->product != USB_DEVICE_ID_EVISION_ICL01) 23 return 0; 24 25 if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER) 26 return 0; 27 28 /* Ignore key down event */ 29 if ((usage->hid & HID_USAGE) >> 8 == 0x05) 30 return -1; 31 /* Ignore key up event */ 32 if ((usage->hid & HID_USAGE) >> 8 == 0x06) 33 return -1; 34 35 switch (usage->hid & HID_USAGE) { 36 /* Ignore configuration saved event */ 37 case 0x0401: return -1; 38 /* Ignore reset event */ 39 case 0x0402: return -1; 40 } 41 return 0; 42 } 43 44 #define REP_DSC_SIZE 236 45 #define USAGE_MAX_INDEX 59 46 47 static const __u8 *evision_report_fixup(struct hid_device *hdev, __u8 *rdesc, 48 unsigned int *rsize) 49 { 50 if (hdev->product == USB_DEVICE_ID_EV_TELINK_RECEIVER && 51 *rsize == REP_DSC_SIZE && rdesc[USAGE_MAX_INDEX] == 0x29 && 52 rdesc[USAGE_MAX_INDEX + 1] == 3) { 53 hid_info(hdev, "fixing EVision:TeLink Receiver report descriptor\n"); 54 rdesc[USAGE_MAX_INDEX + 1] = 5; // change usage max from 3 to 5 55 } 56 return rdesc; 57 } 58 59 static const struct hid_device_id evision_devices[] = { 60 { HID_USB_DEVICE(USB_VENDOR_ID_EVISION, USB_DEVICE_ID_EVISION_ICL01) }, 61 { HID_USB_DEVICE(USB_VENDOR_ID_EVISION, USB_DEVICE_ID_EV_TELINK_RECEIVER) }, 62 { } 63 }; 64 MODULE_DEVICE_TABLE(hid, evision_devices); 65 66 static struct hid_driver evision_driver = { 67 .name = "evision", 68 .id_table = evision_devices, 69 .input_mapping = evision_input_mapping, 70 .report_fixup = evision_report_fixup, 71 }; 72 module_hid_driver(evision_driver); 73 74 MODULE_DESCRIPTION("HID driver for EVision devices"); 75 MODULE_LICENSE("GPL"); 76