hid: topre: Add driver fixing report descriptor
authorHarry Stern <harry@harrystern.net>
Sun, 11 Sep 2022 00:36:13 +0000 (20:36 -0400)
committerBenjamin Tissoires <benjamin.tissoires@redhat.com>
Tue, 20 Sep 2022 11:16:25 +0000 (12:16 +0100)
The Topre REALFORCE R2 firmware incorrectly reports that interface
descriptor number 1, input report descriptor 2's events are array events
rather than variable events. That particular report descriptor is used
to report keypresses when there are more than 6 keys held at a time.
This bug prevents events from this interface from being registered
properly, so only 6 keypresses (from a different interface) can be
registered at once, rather than full n-key rollover.

This commit fixes the bug by setting the correct value in a report_fixup
function.

The original bug report can be found here:
Link: https://gitlab.freedesktop.org/libinput/libinput/-/issues/804
Thanks to Benjamin Tissoires for diagnosing the issue with the report
descriptor.

Signed-off-by: Harry Stern <harry@harrystern.net>
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Link: https://lore.kernel.org/r/20220911003614.297613-1-harry@harrystern.net
drivers/hid/Kconfig
drivers/hid/Makefile
drivers/hid/hid-ids.h
drivers/hid/hid-topre.c [new file with mode: 0644]

index 6ce92830b5d1f9c90444401f0167f64b92bde816..c4308d4988dc065b6557fa49231d348bda4f4a61 100644 (file)
@@ -1141,6 +1141,12 @@ config HID_TOPSEED
        Say Y if you have a TopSeed Cyberlink or BTC Emprex or Conceptronic
        CLLRCMCE remote control.
 
+config HID_TOPRE
+       tristate "Topre REALFORCE keyboards"
+       depends on HID
+       help
+         Say Y for N-key rollover support on Topre REALFORCE R2 108 key keyboards.
+
 config HID_THINGM
        tristate "ThingM blink(1) USB RGB LED"
        depends on HID
index b0bef80981394e616ee7f99da0565de32b9e0850..bccaec0d77d362841f1d3c931a727d3ab04d520c 100644 (file)
@@ -123,6 +123,7 @@ obj-$(CONFIG_HID_GREENASIA) += hid-gaff.o
 obj-$(CONFIG_HID_THRUSTMASTER) += hid-tmff.o hid-thrustmaster.o
 obj-$(CONFIG_HID_TIVO)         += hid-tivo.o
 obj-$(CONFIG_HID_TOPSEED)      += hid-topseed.o
+obj-$(CONFIG_HID_TOPRE)        += hid-topre.o
 obj-$(CONFIG_HID_TWINHAN)      += hid-twinhan.o
 obj-$(CONFIG_HID_U2FZERO)      += hid-u2fzero.o
 hid-uclogic-objs               := hid-uclogic-core.o \
index f80d6193fca6e7fc977797a56eb59389c8788744..50bab12d9476fae7611eca08c6dc1cb2e5b1b76b 100644 (file)
 #define USB_DEVICE_ID_TIVO_SLIDE       0x1201
 #define USB_DEVICE_ID_TIVO_SLIDE_PRO   0x1203
 
+#define USB_VENDOR_ID_TOPRE                    0x0853
+#define USB_DEVICE_ID_TOPRE_REALFORCE_R2_108                   0x0148
+
 #define USB_VENDOR_ID_TOPSEED          0x0766
 #define USB_DEVICE_ID_TOPSEED_CYBERLINK        0x0204
 
diff --git a/drivers/hid/hid-topre.c b/drivers/hid/hid-topre.c
new file mode 100644 (file)
index 0000000..88a91cd
--- /dev/null
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ *  HID driver for Topre REALFORCE Keyboards
+ *
+ *  Copyright (c) 2022 Harry Stern <harry@harrystern.net>
+ *
+ *  Based on the hid-macally driver
+ */
+
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+MODULE_AUTHOR("Harry Stern <harry@harrystern.net>");
+MODULE_DESCRIPTION("REALFORCE R2 Keyboard driver");
+MODULE_LICENSE("GPL");
+
+/*
+ * Fix the REALFORCE R2's non-boot interface's report descriptor to match the
+ * events it's actually sending. It claims to send array events but is instead
+ * sending variable events.
+ */
+static __u8 *topre_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+                                unsigned int *rsize)
+{
+       if (*rsize >= 119 && rdesc[69] == 0x29 && rdesc[70] == 0xe7 &&
+                                                rdesc[71] == 0x81 && rdesc[72] == 0x00) {
+               hid_info(hdev,
+                       "fixing up Topre REALFORCE keyboard report descriptor\n");
+               rdesc[72] = 0x02;
+       }
+       return rdesc;
+}
+
+static const struct hid_device_id topre_id_table[] = {
+       { HID_USB_DEVICE(USB_VENDOR_ID_TOPRE,
+                        USB_DEVICE_ID_TOPRE_REALFORCE_R2_108) },
+       { }
+};
+MODULE_DEVICE_TABLE(hid, topre_id_table);
+
+static struct hid_driver topre_driver = {
+       .name                   = "topre",
+       .id_table               = topre_id_table,
+       .report_fixup           = topre_report_fixup,
+};
+
+module_hid_driver(topre_driver);