HID: semitek: new driver for GK6X series keyboards
A number of USB keyboards, using the Semitek firmware, are capable of handling arbitrary N-key rollover, but due to a buggy report descriptor, keys beyond the sixth cannot be detected by the generic HID driver. There are numerous hardware variants sold by several vendors, mostly using generic names like "GK61" for the 61-key version. These keyboards are sometimes known collectively as the "GK6X" series. The keyboard has three USB interfaces. Interface 0 uses the standard HID boot protocol, limited to eight modifier keys and six normal keys; interface 2 uses a custom report format that permits any number of keys. If more than six keys are pressed simultaneously, the first six are reported via interface 0 while subsequent keys are reported via interface 2. (Interface 1 uses a custom protocol for reprogramming the keyboard; this can be controlled through userspace tools and is not of concern for the present driver.) The report descriptor for interface 2, however, is incorrect (for report ID 0x04, the input field is marked as "array" rather than "variable".) The descriptor appears to be correct in other respects, so we simply replace the incorrect byte before parsing the descriptor. Signed-off-by: Benjamin Moody <bmoody@member.fsf.org> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
This commit is contained in:
parent
efd8929b9e
commit
6a01268687
|
@ -922,6 +922,21 @@ config HID_SAMSUNG
|
||||||
help
|
help
|
||||||
Support for Samsung InfraRed remote control or keyboards.
|
Support for Samsung InfraRed remote control or keyboards.
|
||||||
|
|
||||||
|
config HID_SEMITEK
|
||||||
|
tristate "Semitek USB keyboards"
|
||||||
|
depends on HID
|
||||||
|
help
|
||||||
|
Support for Semitek USB keyboards that are not fully compliant
|
||||||
|
with the HID standard.
|
||||||
|
|
||||||
|
There are many variants, including:
|
||||||
|
- GK61, GK64, GK68, GK84, GK96, etc.
|
||||||
|
- SK61, SK64, SK68, SK84, SK96, etc.
|
||||||
|
- Dierya DK61/DK66
|
||||||
|
- Tronsmart TK09R
|
||||||
|
- Woo-dy
|
||||||
|
- X-Bows Nature/Knight
|
||||||
|
|
||||||
config HID_SONY
|
config HID_SONY
|
||||||
tristate "Sony PS2/3/4 accessories"
|
tristate "Sony PS2/3/4 accessories"
|
||||||
depends on USB_HID
|
depends on USB_HID
|
||||||
|
|
|
@ -106,6 +106,7 @@ obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o hid-roccat-common.o \
|
||||||
obj-$(CONFIG_HID_RMI) += hid-rmi.o
|
obj-$(CONFIG_HID_RMI) += hid-rmi.o
|
||||||
obj-$(CONFIG_HID_SAITEK) += hid-saitek.o
|
obj-$(CONFIG_HID_SAITEK) += hid-saitek.o
|
||||||
obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o
|
obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o
|
||||||
|
obj-$(CONFIG_HID_SEMITEK) += hid-semitek.o
|
||||||
obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o
|
obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o
|
||||||
obj-$(CONFIG_HID_SONY) += hid-sony.o
|
obj-$(CONFIG_HID_SONY) += hid-sony.o
|
||||||
obj-$(CONFIG_HID_SPEEDLINK) += hid-speedlink.o
|
obj-$(CONFIG_HID_SPEEDLINK) += hid-speedlink.o
|
||||||
|
|
|
@ -1060,6 +1060,9 @@
|
||||||
#define USB_DEVICE_ID_SEMICO_USB_KEYKOARD 0x0023
|
#define USB_DEVICE_ID_SEMICO_USB_KEYKOARD 0x0023
|
||||||
#define USB_DEVICE_ID_SEMICO_USB_KEYKOARD2 0x0027
|
#define USB_DEVICE_ID_SEMICO_USB_KEYKOARD2 0x0027
|
||||||
|
|
||||||
|
#define USB_VENDOR_ID_SEMITEK 0x1ea7
|
||||||
|
#define USB_DEVICE_ID_SEMITEK_KEYBOARD 0x0907
|
||||||
|
|
||||||
#define USB_VENDOR_ID_SENNHEISER 0x1395
|
#define USB_VENDOR_ID_SENNHEISER 0x1395
|
||||||
#define USB_DEVICE_ID_SENNHEISER_BTD500USB 0x002c
|
#define USB_DEVICE_ID_SENNHEISER_BTD500USB 0x002c
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
/*
|
||||||
|
* HID driver for Semitek keyboards
|
||||||
|
*
|
||||||
|
* Copyright (c) 2021 Benjamin Moody
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/device.h>
|
||||||
|
#include <linux/hid.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
|
||||||
|
#include "hid-ids.h"
|
||||||
|
|
||||||
|
static __u8 *semitek_report_fixup(struct hid_device *hdev, __u8 *rdesc,
|
||||||
|
unsigned int *rsize)
|
||||||
|
{
|
||||||
|
/* In the report descriptor for interface 2, fix the incorrect
|
||||||
|
description of report ID 0x04 (the report contains a
|
||||||
|
bitmask, not an array of keycodes.) */
|
||||||
|
if (*rsize == 0xcb && rdesc[0x83] == 0x81 && rdesc[0x84] == 0x00) {
|
||||||
|
hid_info(hdev, "fixing up Semitek report descriptor\n");
|
||||||
|
rdesc[0x84] = 0x02;
|
||||||
|
}
|
||||||
|
return rdesc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct hid_device_id semitek_devices[] = {
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_SEMITEK, USB_DEVICE_ID_SEMITEK_KEYBOARD) },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(hid, semitek_devices);
|
||||||
|
|
||||||
|
static struct hid_driver semitek_driver = {
|
||||||
|
.name = "semitek",
|
||||||
|
.id_table = semitek_devices,
|
||||||
|
.report_fixup = semitek_report_fixup,
|
||||||
|
};
|
||||||
|
module_hid_driver(semitek_driver);
|
||||||
|
|
||||||
|
MODULE_LICENSE("GPL");
|
Loading…
Reference in New Issue