Skip to content

Commit ee46967

Browse files
whotJiri Kosina
authored andcommitted
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: c53431e ("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>
1 parent cf26057 commit ee46967

File tree

2 files changed

+23
-13
lines changed

2 files changed

+23
-13
lines changed

drivers/hid/hid-core.c

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ static int open_collection(struct hid_parser *parser, unsigned type)
125125
{
126126
struct hid_collection *collection;
127127
unsigned usage;
128+
int collection_index;
128129

129130
usage = parser->local.usage[0];
130131

@@ -167,13 +168,13 @@ static int open_collection(struct hid_parser *parser, unsigned type)
167168
parser->collection_stack[parser->collection_stack_ptr++] =
168169
parser->device->maxcollection;
169170

170-
collection = parser->device->collection +
171-
parser->device->maxcollection++;
171+
collection_index = parser->device->maxcollection++;
172+
collection = parser->device->collection + collection_index;
172173
collection->type = type;
173174
collection->usage = usage;
174175
collection->level = parser->collection_stack_ptr - 1;
175-
collection->parent = parser->active_collection;
176-
parser->active_collection = collection;
176+
collection->parent_idx = parser->active_collection_idx;
177+
parser->active_collection_idx = collection_index;
177178

178179
if (type == HID_COLLECTION_APPLICATION)
179180
parser->device->maxapplication++;
@@ -192,8 +193,13 @@ static int close_collection(struct hid_parser *parser)
192193
return -EINVAL;
193194
}
194195
parser->collection_stack_ptr--;
195-
if (parser->active_collection)
196-
parser->active_collection = parser->active_collection->parent;
196+
if (parser->active_collection_idx != -1) {
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+
}
197203
return 0;
198204
}
199205

@@ -819,6 +825,7 @@ static int hid_scan_report(struct hid_device *hid)
819825
return -ENOMEM;
820826

821827
parser->device = hid;
828+
parser->active_collection_idx = -1;
822829
hid->group = HID_GROUP_GENERIC;
823830

824831
/*
@@ -1006,10 +1013,12 @@ static void hid_apply_multiplier_to_field(struct hid_device *hid,
10061013
usage = &field->usage[i];
10071014

10081015
collection = &hid->collection[usage->collection_index];
1009-
while (collection && collection != multiplier_collection)
1010-
collection = collection->parent;
1016+
while (collection->parent_idx != -1 &&
1017+
collection != multiplier_collection)
1018+
collection = &hid->collection[collection->parent_idx];
10111019

1012-
if (collection || multiplier_collection == NULL)
1020+
if (collection->parent_idx != -1 ||
1021+
multiplier_collection == NULL)
10131022
usage->resolution_multiplier = effective_multiplier;
10141023

10151024
}
@@ -1044,9 +1053,9 @@ static void hid_apply_multiplier(struct hid_device *hid,
10441053
* applicable fields later.
10451054
*/
10461055
multiplier_collection = &hid->collection[multiplier->usage->collection_index];
1047-
while (multiplier_collection &&
1056+
while (multiplier_collection->parent_idx != -1 &&
10481057
multiplier_collection->type != HID_COLLECTION_LOGICAL)
1049-
multiplier_collection = multiplier_collection->parent;
1058+
multiplier_collection = &hid->collection[multiplier_collection->parent_idx];
10501059

10511060
effective_multiplier = hid_calculate_multiplier(hid, multiplier);
10521061

@@ -1170,6 +1179,7 @@ int hid_open_report(struct hid_device *device)
11701179
}
11711180

11721181
parser->device = device;
1182+
parser->active_collection_idx = -1;
11731183

11741184
end = start + size;
11751185

include/linux/hid.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,7 @@ struct hid_local {
430430
*/
431431

432432
struct hid_collection {
433-
struct hid_collection *parent;
433+
int parent_idx; /* device->collection */
434434
unsigned type;
435435
unsigned usage;
436436
unsigned level;
@@ -658,7 +658,7 @@ struct hid_parser {
658658
unsigned int *collection_stack;
659659
unsigned int collection_stack_ptr;
660660
unsigned int collection_stack_size;
661-
struct hid_collection *active_collection;
661+
int active_collection_idx; /* device->collection */
662662
struct hid_device *device;
663663
unsigned int scan_flags;
664664
};

0 commit comments

Comments
 (0)