]>
Commit | Line | Data |
---|---|---|
d4591719 GKH |
1 | From 6ce901eb61aa30ba8565c62049ee80c90728ef14 Mon Sep 17 00:00:00 2001 |
2 | From: David Herrmann <dh.herrmann@gmail.com> | |
3 | Date: Mon, 29 Dec 2014 15:21:26 +0100 | |
4 | Subject: HID: input: fix confusion on conflicting mappings | |
5 | ||
6 | From: David Herrmann <dh.herrmann@gmail.com> | |
7 | ||
8 | commit 6ce901eb61aa30ba8565c62049ee80c90728ef14 upstream. | |
9 | ||
10 | On an PC-101/103/104 keyboard (American layout) the 'Enter' key and its | |
11 | neighbours look like this: | |
12 | ||
13 | +---+ +---+ +-------+ | |
14 | | 1 | | 2 | | 5 | | |
15 | +---+ +---+ +-------+ | |
16 | +---+ +-----------+ | |
17 | | 3 | | 4 | | |
18 | +---+ +-----------+ | |
19 | ||
20 | On a PC-102/105 keyboard (European layout) it looks like this: | |
21 | ||
22 | +---+ +---+ +-------+ | |
23 | | 1 | | 2 | | | | |
24 | +---+ +---+ +-+ 4 | | |
25 | +---+ +---+ | | | |
26 | | 3 | | 5 | | | | |
27 | +---+ +---+ +-----+ | |
28 | ||
29 | (Note that the number of keys is the same, but key '5' is moved down and | |
30 | the shape of key '4' is changed. Keys '1' to '3' are exactly the same.) | |
31 | ||
32 | The keys 1-4 report the same scan-code in HID in both layouts, even though | |
33 | the keysym they produce is usually different depending on the XKB-keymap | |
34 | used by user-space. | |
35 | However, key '5' (US 'backslash'/'pipe') reports 0x31 for the upper layout | |
36 | and 0x32 for the lower layout, as defined by the HID spec. This is highly | |
37 | confusing as the linux-input API uses a single keycode for both. | |
38 | ||
39 | So far, this was never a problem as there never has been a keyboard with | |
40 | both of those keys present at the same time. It would have to look | |
41 | something like this: | |
42 | ||
43 | +---+ +---+ +-------+ | |
44 | | 1 | | 2 | | x31 | | |
45 | +---+ +---+ +-------+ | |
46 | +---+ +---+ +-----+ | |
47 | | 3 | |x32| | 4 | | |
48 | +---+ +---+ +-----+ | |
49 | ||
50 | HID can represent such a keyboard, but the linux-input API cannot. | |
51 | Furthermore, any user-space mapping would be confused by this and, | |
52 | luckily, no-one ever produced such hardware. | |
53 | ||
54 | Now, the HID input layer fixed this mess by mapping both 0x31 and 0x32 to | |
55 | the same keycode (KEY_BACKSLASH==0x2b). As only one of both physical keys | |
56 | is present on a hardware, this works just fine. | |
57 | ||
58 | Lets introduce hardware-vendors into this: | |
59 | ------------------------------------------ | |
60 | ||
61 | Unfortunately, it seems way to expensive to produce a different device for | |
62 | American and European layouts. Therefore, hardware-vendors put both keys, | |
63 | (0x31 and 0x32) on the same keyboard, but only one of them is hooked up | |
64 | to the physical button, the other one is 'dead'. | |
65 | This means, they can use the same hardware, with a different button-layout | |
66 | and automatically produce the correct HID events for American *and* | |
67 | European layouts. This is unproblematic for normal keyboards, as the | |
68 | 'dead' key will never report any KEY-DOWN events. But RollOver keyboards | |
69 | send the whole matrix on each key-event, allowing n-key roll-over mode. | |
70 | This means, we get a 0x31 and 0x32 event on each key-press. One of them | |
71 | will always be 0, the other reports the real state. As we map both to the | |
72 | same keycode, we will get spurious key-events, even though the real | |
73 | key-state never changed. | |
74 | ||
75 | The easiest way would be to blacklist 'dead' keys and never handle those. | |
76 | We could simply read the 'country' tag of USB devices and blacklist either | |
77 | key according to the layout. But... hardware vendors... want the same | |
78 | device for all countries and thus many of them set 'country' to 0 for all | |
79 | devices. Meh.. | |
80 | ||
81 | So we have to deal with this properly. As we cannot know which of the keys | |
82 | is 'dead', we either need a heuristic and track those keys, or we simply | |
83 | make use of our value-tracking for HID fields. We simply ignore HID events | |
84 | for absolute data if the data didn't change. As HID tracks events on the | |
85 | HID level, we haven't done the keycode translation, yet. Therefore, the | |
86 | 'dead' key is tracked independently of the real key, therefore, any events | |
87 | on it will be ignored. | |
88 | ||
89 | This patch simply discards any HID events for absolute data if it didn't | |
90 | change compared to the last report. We need to ignore relative and | |
91 | buffered-byte reports for obvious reasons. But those cannot be affected by | |
92 | this bug, so we're fine. | |
93 | ||
94 | Preferably, we'd do this filtering on the HID-core level. But this might | |
95 | break a lot of custom drivers, if they do not follow the HID specs. | |
96 | Therefore, we do this late in hid-input just before we inject it into the | |
97 | input layer (which does the exact same filtering, but on the keycode | |
98 | level). | |
99 | ||
100 | If this turns out to break some devices, we might have to limit filtering | |
101 | to EV_KEY events. But lets try to do the Right Thing first, and properly | |
102 | filter any absolute data that didn't change. | |
103 | ||
104 | This patch is tagged for 'stable' as it fixes a lot of n-key RollOver | |
105 | hardware. We might wanna wait with backporting for a while, before we know | |
106 | it doesn't break anything else, though. | |
107 | ||
108 | Reported-by: Adam Goode <adam@spicenitz.org> | |
109 | Reported-by: Fredrik Hallenberg <megahallon@gmail.com> | |
110 | Tested-by: Fredrik Hallenberg <megahallon@gmail.com> | |
111 | Signed-off-by: David Herrmann <dh.herrmann@gmail.com> | |
112 | Signed-off-by: Jiri Kosina <jkosina@suse.cz> | |
113 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
114 | ||
115 | --- | |
116 | drivers/hid/hid-input.c | 16 ++++++++++++++++ | |
117 | 1 file changed, 16 insertions(+) | |
118 | ||
119 | --- a/drivers/hid/hid-input.c | |
120 | +++ b/drivers/hid/hid-input.c | |
121 | @@ -1066,6 +1066,22 @@ void hidinput_hid_event(struct hid_devic | |
122 | return; | |
123 | } | |
124 | ||
125 | + /* | |
126 | + * Ignore reports for absolute data if the data didn't change. This is | |
127 | + * not only an optimization but also fixes 'dead' key reports. Some | |
128 | + * RollOver implementations for localized keys (like BACKSLASH/PIPE; HID | |
129 | + * 0x31 and 0x32) report multiple keys, even though a localized keyboard | |
130 | + * can only have one of them physically available. The 'dead' keys | |
131 | + * report constant 0. As all map to the same keycode, they'd confuse | |
132 | + * the input layer. If we filter the 'dead' keys on the HID level, we | |
133 | + * skip the keycode translation and only forward real events. | |
134 | + */ | |
135 | + if (!(field->flags & (HID_MAIN_ITEM_RELATIVE | | |
136 | + HID_MAIN_ITEM_BUFFERED_BYTE)) && | |
137 | + usage->usage_index < field->maxusage && | |
138 | + value == field->value[usage->usage_index]) | |
139 | + return; | |
140 | + | |
141 | /* report the usage code as scancode if the key status has changed */ | |
142 | if (usage->type == EV_KEY && !!test_bit(usage->code, input->key) != value) | |
143 | input_event(input, EV_MSC, MSC_SCAN, usage->hid); |