Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions drivers/hid/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,16 @@ config HID_GLORIOUS
Support for Glorious PC Gaming Race mice such as
the Glorious Model O, O- and D.

config HID_GPD
tristate "GPD Win handheld OEM HID support"
depends on USB_HID
help
Report descriptor fix for the OEM USB HID interface (GameSir
2f24:0137) found on GPD Win handhelds. The firmware declares 63-byte
reports but only sends 11 bytes, which the HID core rejects.

Say Y or M here if you use a GPD Win handheld with this interface.

config HID_HOLTEK
tristate "Holtek HID devices"
depends on USB_HID
Expand Down
1 change: 1 addition & 0 deletions drivers/hid/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ obj-$(CONFIG_HID_ELO) += hid-elo.o
obj-$(CONFIG_HID_EVISION) += hid-evision.o
obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o
obj-$(CONFIG_HID_FT260) += hid-ft260.o
obj-$(CONFIG_HID_GPD) += hid-gpd.o
obj-$(CONFIG_HID_GEMBIRD) += hid-gembird.o
obj-$(CONFIG_HID_GFRM) += hid-gfrm.o
obj-$(CONFIG_HID_GLORIOUS) += hid-glorious.o
Expand Down
52 changes: 52 additions & 0 deletions drivers/hid/hid-gpd.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* HID report descriptor fixup for GPD Win handhelds.
*
* The OEM HID interface (VID 2f24 / GameSir, PID 0137) declares Report ID 1
* with Report Count 63 (8-bit fields) for both Input and Feature, but the
* firmware only sends 11 bytes of payload after the report ID.
*/

#include <linux/hid.h>
#include <linux/module.h>

#include "hid-ids.h"

#define RDESC_LEN 38
#define RPT_COUNT_INPUT_OFF 21
#define RPT_COUNT_FEATURE_OFF 34

static const __u8 *gpd_report_fixup(struct hid_device *hdev, __u8 *rdesc,
unsigned int *rsize)
{
if (*rsize != RDESC_LEN)
return rdesc;

if (rdesc[RPT_COUNT_INPUT_OFF - 1] == 0x95 &&
rdesc[RPT_COUNT_INPUT_OFF] == 0x3f &&
rdesc[RPT_COUNT_FEATURE_OFF - 1] == 0x95 &&
rdesc[RPT_COUNT_FEATURE_OFF] == 0x3f) {
hid_info(hdev, "fixing report counts (63 -> 11 bytes)\n");
rdesc[RPT_COUNT_INPUT_OFF] = 11;
rdesc[RPT_COUNT_FEATURE_OFF] = 11;
}

return rdesc;
}

static const struct hid_device_id gpd_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_GAMESIR, USB_DEVICE_ID_GAMESIR_0137) },
{ }
};
MODULE_DEVICE_TABLE(hid, gpd_devices);

static struct hid_driver gpd_driver = {
.name = "gpd",
.id_table = gpd_devices,
.report_fixup = gpd_report_fixup,
};

module_hid_driver(gpd_driver);

MODULE_DESCRIPTION("HID report descriptor fix for GPD Win handheld (GameSir 2f24:0137)");
MODULE_LICENSE("GPL");
3 changes: 3 additions & 0 deletions drivers/hid/hid-ids.h
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,9 @@
#define USB_VENDOR_ID_FRUCTEL 0x25B6
#define USB_DEVICE_ID_GAMETEL_MT_MODE 0x0002

#define USB_VENDOR_ID_GAMESIR 0x2f24
#define USB_DEVICE_ID_GAMESIR_0137 0x0137

#define USB_VENDOR_ID_GAMEVICE 0x27F8
#define USB_DEVICE_ID_GAMEVICE_GV186 0x0BBE
#define USB_DEVICE_ID_GAMEVICE_KISHI 0x0BBF
Expand Down