From: Simon Wörner <mail@xxxxxxxxxxxxxxxx> HID: Add driver for acer keybard with broken rdesc Signed-off-by: Simon Wörner <mail@xxxxxxxxxxxxxxxx> --- drivers/hid/Kconfig | 6 +++++ drivers/hid/Makefile | 1 + drivers/hid/hid-acer.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++ drivers/hid/hid-ids.h | 3 +++ 4 files changed, 80 insertions(+) create mode 100644 drivers/hid/hid-acer.c diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index dfdc269..f3ae543 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -98,6 +98,12 @@ config HID_A4TECH ---help--- Support for A4 tech X5 and WOP-35 / Trust 450L mice. +config HID_ACER + tristate "Acer keyboard support" + depends on HID + ---help--- + Support for acer keyboard with invalid rdesc. + config HID_ACRUX tristate "ACRUX game controller support" depends on HID diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index debd15b..143602b 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile @@ -34,6 +34,7 @@ ifdef CONFIG_DEBUG_FS endif obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o +obj-$(CONFIG_HID_ACER) += hid-acer.o obj-$(CONFIG_HID_ACRUX) += hid-axff.o obj-$(CONFIG_HID_APPLE) += hid-apple.o obj-$(CONFIG_HID_APPLEIR) += hid-appleir.o diff --git a/drivers/hid/hid-acer.c b/drivers/hid/hid-acer.c new file mode 100644 index 0000000..b3ccd8b --- /dev/null +++ b/drivers/hid/hid-acer.c @@ -0,0 +1,70 @@ +/* + * HID driver for acer devices + * + * Copyright (c) 2015 Simon Wörner + */ + +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + */ + +#include <linux/device.h> +#include <linux/hid.h> +#include <linux/module.h> + +#include "hid-ids.h" + +/* Acer keyboards e.g. in Acer SW5-012 use synaptics touchpad USB ID (06cb:2968) + * and have the following issue: + * - The report descriptor specifies an excessively large number of usages + * and logical max (2^16), which is more than HID_MAX_USAGES. This prevents + * proper parsing of the report descriptor. + * + * The byte replace in the descriptor below fixes the size. + */ + +#define ACER_KBD_RDESC_ORIG_SIZE 188 +#define ACER_KBD_RDESC_CHECK_POS (150 * sizeof(__u8)) +#define ACER_KBD_RDESC_CHECK_DATA 0x2AFFFF150026FFFF +#define ACER_KBD_RDESC_FIX_POS1 152 +#define ACER_KBD_RDESC_FIX_POS2 157 + +static __u8 *acer_kbd_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) +{ + /* check for invalid descriptor */ + if (*rsize == ACER_KBD_RDESC_ORIG_SIZE) { + __u64 check = be64_to_cpu(*(__be64 *)(rdesc + ACER_KBD_RDESC_CHECK_POS)); + + /* check for invalid max usages and logical 0xFFFF (2^16) */ + if (check == ACER_KBD_RDESC_CHECK_DATA) { + hid_info(hdev, "fixing up acer keybaord report descriptor\n"); + + /* fix max values with 0xFF00 (2^8) */ + rdesc[ACER_KBD_RDESC_FIX_POS1] = 0x00; + rdesc[ACER_KBD_RDESC_FIX_POS2] = 0x00; + } + } + + return rdesc; +} + +static const struct hid_device_id acer_devices[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_ACER_SYNAPTICS, + USB_VENDOR_ID_ACER_SYNAPTICS_TP) }, + { } +}; +MODULE_DEVICE_TABLE(hid, acer_devices); + +static struct hid_driver acer_driver = { + .name = "acer", + .id_table = acer_devices, + .report_fixup = acer_kbd_report_fixup, +}; +module_hid_driver(acer_driver); + +MODULE_AUTHOR("Simon Wörner"); +MODULE_LICENSE("GPL"); diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 9243359..5d9482b 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -35,6 +35,9 @@ #define USB_DEVICE_ID_ACECAD_FLAIR 0x0004 #define USB_DEVICE_ID_ACECAD_302 0x0008 +#define USB_VENDOR_ID_ACER_SYNAPTICS 0x06cb +#define USB_VENDOR_ID_ACER_SYNAPTICS_TP 0x2968 + #define USB_VENDOR_ID_ACRUX 0x1a34 #define USB_VENDOR_ID_ACTIONSTAR 0x2101 -- 2.2.2 -- To unsubscribe from this list: send the line "unsubscribe linux-input" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html