1a109d5c4SHarry Stern // SPDX-License-Identifier: GPL-2.0+ 2a109d5c4SHarry Stern /* 3a109d5c4SHarry Stern * HID driver for Topre REALFORCE Keyboards 4a109d5c4SHarry Stern * 5a109d5c4SHarry Stern * Copyright (c) 2022 Harry Stern <harry@harrystern.net> 6a109d5c4SHarry Stern * 7a109d5c4SHarry Stern * Based on the hid-macally driver 8a109d5c4SHarry Stern */ 9a109d5c4SHarry Stern 10a109d5c4SHarry Stern #include <linux/hid.h> 11a109d5c4SHarry Stern #include <linux/module.h> 12a109d5c4SHarry Stern 13a109d5c4SHarry Stern #include "hid-ids.h" 14a109d5c4SHarry Stern 15a109d5c4SHarry Stern MODULE_AUTHOR("Harry Stern <harry@harrystern.net>"); 16a109d5c4SHarry Stern MODULE_DESCRIPTION("REALFORCE R2 Keyboard driver"); 17a109d5c4SHarry Stern MODULE_LICENSE("GPL"); 18a109d5c4SHarry Stern 19a109d5c4SHarry Stern /* 20a109d5c4SHarry Stern * Fix the REALFORCE R2's non-boot interface's report descriptor to match the 21a109d5c4SHarry Stern * events it's actually sending. It claims to send array events but is instead 22a109d5c4SHarry Stern * sending variable events. 23a109d5c4SHarry Stern */ 24*fe73965dSThomas Weißschuh static const __u8 *topre_report_fixup(struct hid_device *hdev, __u8 *rdesc, 25a109d5c4SHarry Stern unsigned int *rsize) 26a109d5c4SHarry Stern { 27a109d5c4SHarry Stern if (*rsize >= 119 && rdesc[69] == 0x29 && rdesc[70] == 0xe7 && 28a109d5c4SHarry Stern rdesc[71] == 0x81 && rdesc[72] == 0x00) { 29a109d5c4SHarry Stern hid_info(hdev, 30a109d5c4SHarry Stern "fixing up Topre REALFORCE keyboard report descriptor\n"); 31a109d5c4SHarry Stern rdesc[72] = 0x02; 32a109d5c4SHarry Stern } 33a109d5c4SHarry Stern return rdesc; 34a109d5c4SHarry Stern } 35a109d5c4SHarry Stern 36a109d5c4SHarry Stern static const struct hid_device_id topre_id_table[] = { 37a109d5c4SHarry Stern { HID_USB_DEVICE(USB_VENDOR_ID_TOPRE, 38a109d5c4SHarry Stern USB_DEVICE_ID_TOPRE_REALFORCE_R2_108) }, 39dbf56d2fSAlessandro Manca { HID_USB_DEVICE(USB_VENDOR_ID_TOPRE, 40dbf56d2fSAlessandro Manca USB_DEVICE_ID_TOPRE_REALFORCE_R2_87) }, 41a109d5c4SHarry Stern { } 42a109d5c4SHarry Stern }; 43a109d5c4SHarry Stern MODULE_DEVICE_TABLE(hid, topre_id_table); 44a109d5c4SHarry Stern 45a109d5c4SHarry Stern static struct hid_driver topre_driver = { 46a109d5c4SHarry Stern .name = "topre", 47a109d5c4SHarry Stern .id_table = topre_id_table, 48a109d5c4SHarry Stern .report_fixup = topre_report_fixup, 49a109d5c4SHarry Stern }; 50a109d5c4SHarry Stern 51a109d5c4SHarry Stern module_hid_driver(topre_driver); 52