diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 494a39e74939..945533b36010 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -362,6 +362,13 @@ config HID_GFRM ---help--- Support for Google Fiber TV Box remote controls +config HID_GLORIOUS + tristate "Glorious PC Gaming Race mice" + depends on HID + help + Support for Glorious PC Gaming Race mice such as + the Glorious Model O, O- and D. + config HID_HOLTEK tristate "Holtek HID devices" depends on USB_HID diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index bfefa365b1ce..be0f38dcf942 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile @@ -48,6 +48,7 @@ obj-$(CONFIG_HID_ELO) += hid-elo.o obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o obj-$(CONFIG_HID_GEMBIRD) += hid-gembird.o obj-$(CONFIG_HID_GFRM) += hid-gfrm.o +obj-$(CONFIG_HID_GLORIOUS) += hid-glorious.o obj-$(CONFIG_HID_GOOGLE_HAMMER) += hid-google-hammer.o obj-$(CONFIG_HID_GT683R) += hid-gt683r.o obj-$(CONFIG_HID_GYRATION) += hid-gyration.o diff --git a/drivers/hid/hid-glorious.c b/drivers/hid/hid-glorious.c new file mode 100644 index 000000000000..558eb08c19ef --- /dev/null +++ b/drivers/hid/hid-glorious.c @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * USB HID driver for Glorious PC Gaming Race + * Glorious Model O, O- and D mice. + * + * Copyright (c) 2020 Samuel Čavoj + */ + +/* + */ + +#include +#include + +#include "hid-ids.h" + +MODULE_AUTHOR("Samuel Čavoj "); +MODULE_DESCRIPTION("HID driver for Glorious PC Gaming Race mice"); + +/* + * Glorious Model O and O- specify the const flag in the consumer input + * report descriptor, which leads to inputs being ignored. Fix this + * by patching the descriptor. + */ +static __u8 *glorious_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) +{ + if (*rsize == 213 && + rdesc[84] == 129 && rdesc[112] == 129 && rdesc[140] == 129 && + rdesc[85] == 3 && rdesc[113] == 3 && rdesc[141] == 3) { + hid_info(hdev, "patching Glorious Model O consumer control report descriptor\n"); + rdesc[85] = rdesc[113] = rdesc[141] = \ + HID_MAIN_ITEM_VARIABLE | HID_MAIN_ITEM_RELATIVE; + } + return rdesc; +} + +static void glorious_update_name(struct hid_device *hdev) +{ + const char *model = "Device"; + + switch (hdev->product) { + case USB_DEVICE_ID_GLORIOUS_MODEL_O: + model = "Model O"; break; + case USB_DEVICE_ID_GLORIOUS_MODEL_D: + model = "Model D"; break; + } + + snprintf(hdev->name, sizeof(hdev->name), "%s %s", "Glorious", model); +} + +static int glorious_probe(struct hid_device *hdev, + const struct hid_device_id *id) +{ + int ret; + + hdev->quirks |= HID_QUIRK_INPUT_PER_APP; + + ret = hid_parse(hdev); + if (ret) + return ret; + + glorious_update_name(hdev); + + return hid_hw_start(hdev, HID_CONNECT_DEFAULT); +} + +static const struct hid_device_id glorious_devices[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_GLORIOUS, + USB_DEVICE_ID_GLORIOUS_MODEL_O) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GLORIOUS, + USB_DEVICE_ID_GLORIOUS_MODEL_D) }, + { } +}; +MODULE_DEVICE_TABLE(hid, glorious_devices); + +static struct hid_driver glorious_driver = { + .name = "glorious", + .id_table = glorious_devices, + .probe = glorious_probe, + .report_fixup = glorious_report_fixup +}; + +module_hid_driver(glorious_driver); + +MODULE_LICENSE("GPL"); diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 9f2213426556..54474205b12c 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -464,6 +464,10 @@ #define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_010A 0x010a #define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_E100 0xe100 +#define USB_VENDOR_ID_GLORIOUS 0x258a +#define USB_DEVICE_ID_GLORIOUS_MODEL_D 0x0033 +#define USB_DEVICE_ID_GLORIOUS_MODEL_O 0x0036 + #define I2C_VENDOR_ID_GOODIX 0x27c6 #define I2C_DEVICE_ID_GOODIX_01F0 0x01f0