Commit a109d5c4 authored by Harry Stern's avatar Harry Stern Committed by Benjamin Tissoires
Browse files

hid: topre: Add driver fixing report descriptor

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: default avatarHarry Stern <harry@harrystern.net>
Signed-off-by: default avatarBenjamin Tissoires <benjamin.tissoires@redhat.com>
Link: https://lore.kernel.org/r/20220911003614.297613-1-harry@harrystern.net
parent a1f76426
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -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
+1 −0
Original line number Diff line number Diff line
@@ -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 \
+3 −0
Original line number Diff line number Diff line
@@ -1231,6 +1231,9 @@
#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

+49 −0
Original line number Diff line number Diff line
// 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);