summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Hutterer <peter.hutterer@who-t.net>2019-01-08 22:50:18 -0500
committerJiri Kosina <jkosina@suse.cz>2019-01-10 01:08:18 -0500
commitee46967fc6e74d412fe1ec15f77fdb8624bde2b0 (patch)
tree586d3468d91b7059e2f8e9b200c95894501cd4a6
parentcf26057a9441173ad552e90cea3344607075c9ad (diff)
HID: core: replace the collection tree pointers with indices
Previously, the pointer to the parent collection was stored. If a device exceeds 16 collections (HID_DEFAULT_NUM_COLLECTIONS), the array to store the collections is reallocated, the pointer to the parent collection becomes invalid. Replace the pointers with an index-based lookup into the collections array. Fixes: c53431eb696f3c ("HID: core: store the collections as a basic tree") Reported-by: Pandruvada, Srinivas <srinivas.pandruvada@intel.com> Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> Tested-by: Kyle Pelton <kyle.d.pelton@linux.intel.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r--drivers/hid/hid-core.c32
-rw-r--r--include/linux/hid.h4
2 files changed, 23 insertions, 13 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index f41d5fe51abe..f9093dedf647 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -125,6 +125,7 @@ static int open_collection(struct hid_parser *parser, unsigned type)
125{ 125{
126 struct hid_collection *collection; 126 struct hid_collection *collection;
127 unsigned usage; 127 unsigned usage;
128 int collection_index;
128 129
129 usage = parser->local.usage[0]; 130 usage = parser->local.usage[0];
130 131
@@ -167,13 +168,13 @@ static int open_collection(struct hid_parser *parser, unsigned type)
167 parser->collection_stack[parser->collection_stack_ptr++] = 168 parser->collection_stack[parser->collection_stack_ptr++] =
168 parser->device->maxcollection; 169 parser->device->maxcollection;
169 170
170 collection = parser->device->collection + 171 collection_index = parser->device->maxcollection++;
171 parser->device->maxcollection++; 172 collection = parser->device->collection + collection_index;
172 collection->type = type; 173 collection->type = type;
173 collection->usage = usage; 174 collection->usage = usage;
174 collection->level = parser->collection_stack_ptr - 1; 175 collection->level = parser->collection_stack_ptr - 1;
175 collection->parent = parser->active_collection; 176 collection->parent_idx = parser->active_collection_idx;
176 parser->active_collection = collection; 177 parser->active_collection_idx = collection_index;
177 178
178 if (type == HID_COLLECTION_APPLICATION) 179 if (type == HID_COLLECTION_APPLICATION)
179 parser->device->maxapplication++; 180 parser->device->maxapplication++;
@@ -192,8 +193,13 @@ static int close_collection(struct hid_parser *parser)
192 return -EINVAL; 193 return -EINVAL;
193 } 194 }
194 parser->collection_stack_ptr--; 195 parser->collection_stack_ptr--;
195 if (parser->active_collection) 196 if (parser->active_collection_idx != -1) {
196 parser->active_collection = parser->active_collection->parent; 197 struct hid_device *device = parser->device;
198 struct hid_collection *c;
199
200 c = &device->collection[parser->active_collection_idx];
201 parser->active_collection_idx = c->parent_idx;
202 }
197 return 0; 203 return 0;
198} 204}
199 205
@@ -819,6 +825,7 @@ static int hid_scan_report(struct hid_device *hid)
819 return -ENOMEM; 825 return -ENOMEM;
820 826
821 parser->device = hid; 827 parser->device = hid;
828 parser->active_collection_idx = -1;
822 hid->group = HID_GROUP_GENERIC; 829 hid->group = HID_GROUP_GENERIC;
823 830
824 /* 831 /*
@@ -1006,10 +1013,12 @@ static void hid_apply_multiplier_to_field(struct hid_device *hid,
1006 usage = &field->usage[i]; 1013 usage = &field->usage[i];
1007 1014
1008 collection = &hid->collection[usage->collection_index]; 1015 collection = &hid->collection[usage->collection_index];
1009 while (collection && collection != multiplier_collection) 1016 while (collection->parent_idx != -1 &&
1010 collection = collection->parent; 1017 collection != multiplier_collection)
1018 collection = &hid->collection[collection->parent_idx];
1011 1019
1012 if (collection || multiplier_collection == NULL) 1020 if (collection->parent_idx != -1 ||
1021 multiplier_collection == NULL)
1013 usage->resolution_multiplier = effective_multiplier; 1022 usage->resolution_multiplier = effective_multiplier;
1014 1023
1015 } 1024 }
@@ -1044,9 +1053,9 @@ static void hid_apply_multiplier(struct hid_device *hid,
1044 * applicable fields later. 1053 * applicable fields later.
1045 */ 1054 */
1046 multiplier_collection = &hid->collection[multiplier->usage->collection_index]; 1055 multiplier_collection = &hid->collection[multiplier->usage->collection_index];
1047 while (multiplier_collection && 1056 while (multiplier_collection->parent_idx != -1 &&
1048 multiplier_collection->type != HID_COLLECTION_LOGICAL) 1057 multiplier_collection->type != HID_COLLECTION_LOGICAL)
1049 multiplier_collection = multiplier_collection->parent; 1058 multiplier_collection = &hid->collection[multiplier_collection->parent_idx];
1050 1059
1051 effective_multiplier = hid_calculate_multiplier(hid, multiplier); 1060 effective_multiplier = hid_calculate_multiplier(hid, multiplier);
1052 1061
@@ -1170,6 +1179,7 @@ int hid_open_report(struct hid_device *device)
1170 } 1179 }
1171 1180
1172 parser->device = device; 1181 parser->device = device;
1182 parser->active_collection_idx = -1;
1173 1183
1174 end = start + size; 1184 end = start + size;
1175 1185
diff --git a/include/linux/hid.h b/include/linux/hid.h
index d99287327ef2..992bbb7196df 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -430,7 +430,7 @@ struct hid_local {
430 */ 430 */
431 431
432struct hid_collection { 432struct hid_collection {
433 struct hid_collection *parent; 433 int parent_idx; /* device->collection */
434 unsigned type; 434 unsigned type;
435 unsigned usage; 435 unsigned usage;
436 unsigned level; 436 unsigned level;
@@ -658,7 +658,7 @@ struct hid_parser {
658 unsigned int *collection_stack; 658 unsigned int *collection_stack;
659 unsigned int collection_stack_ptr; 659 unsigned int collection_stack_ptr;
660 unsigned int collection_stack_size; 660 unsigned int collection_stack_size;
661 struct hid_collection *active_collection; 661 int active_collection_idx; /* device->collection */
662 struct hid_device *device; 662 struct hid_device *device;
663 unsigned int scan_flags; 663 unsigned int scan_flags;
664}; 664};