On Tue, 2020-07-21 at 05:10 +0900, Frank Yang <puilp0502@xxxxxxxxx> wrote: > > The Varmilo VA104M Keyboard (04b4:07b1, reported as Varmilo Z104M) > exposes media control hotkeys as a USB HID consumer control device, > but these keys do not work in the current (5.8-rc1) kernel due to > the incorrect HID report descriptor. Fix the problem by modifying > the internal HID report descriptor. > > More specifically, the keyboard report descriptor specifies the > logical boundary as 572~10754 (0x023c ~ 0x2a02) while the usage > boundary is specified as 0~10754 (0x00 ~ 0x2a02). This results in an > incorrect interpretation of input reports, causing inputs to be ignored. > By setting the Logical Minimum to zero, we align the logical boundary > with the Usage ID boundary. > > Some notes: > > * There seem to be multiple variants of the VA104M keyboard. This > patch specifically targets 04b4:07b1 variant. > > * The device works out-of-the-box on Windows platform with the generic > consumer control device driver (hidserv.inf). This suggests that > Windows either ignores the Logical Minimum/Logical Maximum or > interprets the Usage ID assignment differently from the linux > implementation; Maybe there are other devices out there that only > works on Windows due to this problem? > > Signed-off-by: Frank Yang <puilp0502@xxxxxxxxx> > --- > drivers/hid/Kconfig | 6 ++++ > drivers/hid/Makefile | 1 + > drivers/hid/hid-ids.h | 2 ++ > drivers/hid/hid-varmilo.c | 58 +++++++++++++++++++++++++++++++++++++++ > 4 files changed, 67 insertions(+) > create mode 100644 drivers/hid/hid-varmilo.c > > diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig > index 443c5cbbde04..c9f0c9b79158 100644 > --- a/drivers/hid/Kconfig > +++ b/drivers/hid/Kconfig > @@ -441,6 +441,12 @@ config HID_WALTOP > ---help--- > Support for Waltop tablets. > > +config HID_VARMILO > + tristate "Varmilo Keyboards" > + depends on HID > + help > + Support for Varmilo keyboards. > + > config HID_VIEWSONIC > tristate "ViewSonic/Signotec" > depends on HID > diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile > index d8ea4b8c95af..e90a98090452 100644 > --- a/drivers/hid/Makefile > +++ b/drivers/hid/Makefile > @@ -124,6 +124,7 @@ obj-$(CONFIG_HID_LED) += hid-led.o > obj-$(CONFIG_HID_XINMO) += hid-xinmo.o > obj-$(CONFIG_HID_ZEROPLUS) += hid-zpff.o > obj-$(CONFIG_HID_ZYDACRON) += hid-zydacron.o > +obj-$(CONFIG_HID_VARMILO) += hid-varmilo.o > obj-$(CONFIG_HID_VIEWSONIC) += hid-viewsonic.o > > wacom-objs := wacom_wac.o wacom_sys.o > diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h > index 874fc3791f3b..955be22fc69d 100644 > --- a/drivers/hid/hid-ids.h > +++ b/drivers/hid/hid-ids.h > @@ -1189,6 +1189,8 @@ > #define USB_DEVICE_ID_UNITEC_USB_TOUCH_0709 0x0709 > #define USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19 0x0a19 > > +#define USB_DEVICE_ID_VARMILO_VA104M_07B1 0X07b1 > + > #define USB_VENDOR_ID_VELLEMAN 0x10cf > #define USB_DEVICE_ID_VELLEMAN_K8055_FIRST 0x5500 > #define USB_DEVICE_ID_VELLEMAN_K8055_LAST 0x5503 > diff --git a/drivers/hid/hid-varmilo.c b/drivers/hid/hid-varmilo.c > new file mode 100644 > index 000000000000..10e50f2dca61 > --- /dev/null > +++ b/drivers/hid/hid-varmilo.c > @@ -0,0 +1,58 @@ > +// SPDX-License-Identifier: GPL-2.0-or-later > +/* > + * HID report fixup for varmilo keyboards > + * > + * Copyright (c) 2020 Frank Yang <puilp0502@xxxxxxxxx> > + * > + */ > + > +#include <linux/hid.h> > +#include <linux/module.h> > + > +#include "hid-ids.h" > + > +/* > + * Varmilo VA104M with device ID of 07B1 incorrectly reports Logical Minimum as > + * 572 (0x02 0x3c). We fix this by setting Logical Minimum to zero. > + */ > +static __u8 *varmilo_07b1_report_fixup(struct hid_device *hdev, __u8 *rdesc, > + unsigned int *rsize) > +{ > + if (*rsize == 25 && > + rdesc[0] == 0x05 && rdesc[1] == 0x0c && > + rdesc[2] == 0x09 && rdesc[3] == 0x01 && > + rdesc[6] == 0x19 && rdesc[7] == 0x00 && > + rdesc[11] == 0x16 && rdesc[12] == 0x3c && rdesc[13] == 0x02) { > + hid_info(hdev, > + "fixing up varmilo VA104M consumer control report descriptor\n"); > + rdesc[12] = 0x00; > + rdesc[13] = 0x00; > + } > + return rdesc; > +} > + > +static __u8 *varmilo_report_fixup(struct hid_device *hdev, __u8 *rdesc, > + unsigned int *rsize) > +{ > + if (hdev->product == USB_DEVICE_ID_VARMILO_VA104M_07B1 && > + hdev->vendor == USB_VENDOR_ID_CYPRESS) > + rdesc = varmilo_07b1_report_fixup(hdev, rdesc, rsize); > + return rdesc; > +} > + > +static const struct hid_device_id varmilo_devices[] = { > + { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_VARMILO_VA104M_07B1) }, > + {} > +}; > + > +MODULE_DEVICE_TABLE(hid, varmilo_devices); > + > +static struct hid_driver varmilo_driver = { > + .name = "varmilo", > + .id_table = varmilo_devices, > + .report_fixup = varmilo_report_fixup, > +}; > + > +module_hid_driver(varmilo_driver); > + > +MODULE_LICENSE("GPL"); > -- > 2.17.1 > CCing linux-input mailing list. Cc: linux-input@xxxxxxxxxxxxxxx