This repository has been archived by the owner on Jan 5, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathhid-acer.c
executable file
·74 lines (62 loc) · 2.17 KB
/
hid-acer.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
/*
* 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 keyboard 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) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ACER_SYNAPTICS,
USB_VENDOR_ID_ACER_SYNAPTICS_TP_74D9) },
{ }
};
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");