]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - queue-4.4/hid-core-move-usage-page-concatenation-to-main-item.patch
drop drm-rockchip-shutdown-drm-subsystem-on-shutdown.patch from 4.4.y and 4.9.y
[thirdparty/kernel/stable-queue.git] / queue-4.4 / hid-core-move-usage-page-concatenation-to-main-item.patch
CommitLineData
1143c684
SL
1From 51878761d65fa02c43a15d339bd1a756bbf6a03d Mon Sep 17 00:00:00 2001
2From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
3Date: Wed, 27 Mar 2019 11:18:48 +0100
4Subject: HID: core: move Usage Page concatenation to Main item
5
6[ Upstream commit 58e75155009cc800005629955d3482f36a1e0eec ]
7
8As seen on some USB wireless keyboards manufactured by Primax, the HID
9parser was using some assumptions that are not always true. In this case
10it's s the fact that, inside the scope of a main item, an Usage Page
11will always precede an Usage.
12
13The spec is not pretty clear as 6.2.2.7 states "Any usage that follows
14is interpreted as a Usage ID and concatenated with the Usage Page".
15While 6.2.2.8 states "When the parser encounters a main item it
16concatenates the last declared Usage Page with a Usage to form a
17complete usage value." Being somewhat contradictory it was decided to
18match Window's implementation, which follows 6.2.2.8.
19
20In summary, the patch moves the Usage Page concatenation from the local
21item parsing function to the main item parsing function.
22
23Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
24Reviewed-by: Terry Junge <terry.junge@poly.com>
25Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
26Signed-off-by: Sasha Levin <sashal@kernel.org>
27---
28 drivers/hid/hid-core.c | 36 ++++++++++++++++++++++++------------
29 include/linux/hid.h | 1 +
30 2 files changed, 25 insertions(+), 12 deletions(-)
31
32diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
33index 4564ecf711815..9b2b41d683dea 100644
34--- a/drivers/hid/hid-core.c
35+++ b/drivers/hid/hid-core.c
36@@ -200,13 +200,14 @@ static unsigned hid_lookup_collection(struct hid_parser *parser, unsigned type)
37 * Add a usage to the temporary parser table.
38 */
39
40-static int hid_add_usage(struct hid_parser *parser, unsigned usage)
41+static int hid_add_usage(struct hid_parser *parser, unsigned usage, u8 size)
42 {
43 if (parser->local.usage_index >= HID_MAX_USAGES) {
44 hid_err(parser->device, "usage index exceeded\n");
45 return -1;
46 }
47 parser->local.usage[parser->local.usage_index] = usage;
48+ parser->local.usage_size[parser->local.usage_index] = size;
49 parser->local.collection_index[parser->local.usage_index] =
50 parser->collection_stack_ptr ?
51 parser->collection_stack[parser->collection_stack_ptr - 1] : 0;
52@@ -463,10 +464,7 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
53 return 0;
54 }
55
56- if (item->size <= 2)
57- data = (parser->global.usage_page << 16) + data;
58-
59- return hid_add_usage(parser, data);
60+ return hid_add_usage(parser, data, item->size);
61
62 case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM:
63
64@@ -475,9 +473,6 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
65 return 0;
66 }
67
68- if (item->size <= 2)
69- data = (parser->global.usage_page << 16) + data;
70-
71 parser->local.usage_minimum = data;
72 return 0;
73
74@@ -488,9 +483,6 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
75 return 0;
76 }
77
78- if (item->size <= 2)
79- data = (parser->global.usage_page << 16) + data;
80-
81 count = data - parser->local.usage_minimum;
82 if (count + parser->local.usage_index >= HID_MAX_USAGES) {
83 /*
84@@ -510,7 +502,7 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
85 }
86
87 for (n = parser->local.usage_minimum; n <= data; n++)
88- if (hid_add_usage(parser, n)) {
89+ if (hid_add_usage(parser, n, item->size)) {
90 dbg_hid("hid_add_usage failed\n");
91 return -1;
92 }
93@@ -524,6 +516,22 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
94 return 0;
95 }
96
97+/*
98+ * Concatenate Usage Pages into Usages where relevant:
99+ * As per specification, 6.2.2.8: "When the parser encounters a main item it
100+ * concatenates the last declared Usage Page with a Usage to form a complete
101+ * usage value."
102+ */
103+
104+static void hid_concatenate_usage_page(struct hid_parser *parser)
105+{
106+ int i;
107+
108+ for (i = 0; i < parser->local.usage_index; i++)
109+ if (parser->local.usage_size[i] <= 2)
110+ parser->local.usage[i] += parser->global.usage_page << 16;
111+}
112+
113 /*
114 * Process a main item.
115 */
116@@ -533,6 +541,8 @@ static int hid_parser_main(struct hid_parser *parser, struct hid_item *item)
117 __u32 data;
118 int ret;
119
120+ hid_concatenate_usage_page(parser);
121+
122 data = item_udata(item);
123
124 switch (item->tag) {
125@@ -746,6 +756,8 @@ static int hid_scan_main(struct hid_parser *parser, struct hid_item *item)
126 __u32 data;
127 int i;
128
129+ hid_concatenate_usage_page(parser);
130+
131 data = item_udata(item);
132
133 switch (item->tag) {
134diff --git a/include/linux/hid.h b/include/linux/hid.h
135index fd86687f81196..5f31318851366 100644
136--- a/include/linux/hid.h
137+++ b/include/linux/hid.h
138@@ -372,6 +372,7 @@ struct hid_global {
139
140 struct hid_local {
141 unsigned usage[HID_MAX_USAGES]; /* usage array */
142+ u8 usage_size[HID_MAX_USAGES]; /* usage size array */
143 unsigned collection_index[HID_MAX_USAGES]; /* collection index array */
144 unsigned usage_index;
145 unsigned usage_minimum;
146--
1472.20.1
148