Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
From a6de4aef06ad9b182ee80dfc682c90a45fe68890 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Simon=20W=C3=B6rner?= <mail@simon-woerner.de>
Date: Mon, 11 May 2015 16:16:09 +0200
Subject: [PATCH] HID acer keyboard rdesc fix.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Acer keyboards e.g. in Acer SW5-012 use synaptics touchpad USB ID
(06cb:2968 and 06CB:2991) 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.
Signed-off-by: Simon Wörner <mail@simon-woerner.de>
---
drivers/hid/Kconfig | 9 ++++++-
drivers/hid/Makefile | 1 +
drivers/hid/hid-acer.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++
drivers/hid/hid-ids.h | 4 +++
4 files changed, 86 insertions(+), 1 deletion(-)
create mode 100644 drivers/hid/hid-acer.c
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 15338af..67ebdad 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -98,6 +98,13 @@ 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 keyboards with invalid rdesc.
+ (hid-generic: usage index exceeded)
+
config HID_ACRUX
tristate "ACRUX game controller support"
depends on HID
@@ -686,7 +693,7 @@ config HID_SONY
* Logitech Harmony adapter for Sony Playstation 3 (Bluetooth)
config SONY_FF
- bool "Sony PS2/3/4 accessories force feedback support"
+ bool "Sony PS2/3/4 accessories force feedback support"
depends on HID_SONY
select INPUT_FF_MEMLESS
---help---
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index e4a21df..ea5495a 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -21,6 +21,7 @@ hid-wiimote-y := hid-wiimote-core.o hid-wiimote-modules.o
hid-wiimote-$(CONFIG_DEBUG_FS) += hid-wiimote-debug.o
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..4030a10
--- /dev/null
+++ b/drivers/hid/hid-acer.c
@@ -0,0 +1,73 @@
+/*
+ * 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 06CB:2991) 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_2968) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ACER_SYNAPTICS,
+ USB_VENDOR_ID_ACER_SYNAPTICS_TP_2991) },
+ { }
+};
+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 41f167e..b19340b 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -35,6 +35,10 @@
#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_2968 0x2968
+#define USB_VENDOR_ID_ACER_SYNAPTICS_TP_2991 0x2991
+
#define USB_VENDOR_ID_ACRUX 0x1a34
#define USB_VENDOR_ID_ACTIONSTAR 0x2101
--
2.4.0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.