diff options
author | Benjamin Tissoires <benjamin.tissoires@redhat.com> | 2018-07-13 17:13:50 +0300 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2018-07-17 16:33:47 +0300 |
commit | 08a8a7cf14595f95d5cbb28ef5c15c56a6255fb4 (patch) | |
tree | 7b51d919ff29ee607b2229bd69f6a9059975c131 /drivers/hid/hid-core.c | |
parent | ba6b055e0f3b4ff4942e4ab273260affcfad9bff (diff) |
HID: core: do not upper bound the collection stack
Looks like 4 was sufficient until now. However, the Surface Dial needs
a stack of 5 and simply fails at probing.
Dynamically add HID_COLLECTION_STACK_SIZE to the size of the stack if
we hit the upper bound.
Checkpatch complains about bare unsigned, so converting those to
'unsigned int' in struct hid_parser
Acked-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid/hid-core.c')
-rw-r--r-- | drivers/hid/hid-core.c | 17 |
1 files changed, 14 insertions, 3 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 3942ee61bd1c..5de6f18c9bf7 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -128,9 +128,19 @@ static int open_collection(struct hid_parser *parser, unsigned type) usage = parser->local.usage[0]; - if (parser->collection_stack_ptr == HID_COLLECTION_STACK_SIZE) { - hid_err(parser->device, "collection stack overflow\n"); - return -EINVAL; + if (parser->collection_stack_ptr == parser->collection_stack_size) { + unsigned int *collection_stack; + unsigned int new_size = parser->collection_stack_size + + HID_COLLECTION_STACK_SIZE; + + collection_stack = krealloc(parser->collection_stack, + new_size * sizeof(unsigned int), + GFP_KERNEL); + if (!collection_stack) + return -ENOMEM; + + parser->collection_stack = collection_stack; + parser->collection_stack_size = new_size; } if (parser->device->maxcollection == parser->device->collection_size) { @@ -840,6 +850,7 @@ static int hid_scan_report(struct hid_device *hid) break; } + kfree(parser->collection_stack); vfree(parser); return 0; } |