Module: wine Branch: master Commit: 3b3b7670ec0a7d3ba207d1588dac2e6d26b51236 URL: http://source.winehq.org/git/wine.git/?a=commit;h=3b3b7670ec0a7d3ba207d1588d...
Author: Aric Stewart aric@codeweavers.com Date: Mon Nov 14 08:29:20 2016 -0600
hidclass.sys: Handle POP and PUSH in device descriptors.
Signed-off-by: Aric Stewart aric@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/hidclass.sys/descriptor.c | 50 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 45 insertions(+), 5 deletions(-)
diff --git a/dlls/hidclass.sys/descriptor.c b/dlls/hidclass.sys/descriptor.c index 9a26f0f4..e1c48dd 100644 --- a/dlls/hidclass.sys/descriptor.c +++ b/dlls/hidclass.sys/descriptor.c @@ -172,6 +172,11 @@ struct collection { struct list collections; };
+struct caps_stack { + struct list entry; + struct caps caps; +}; + static const char* debugstr_usages(struct caps *caps) { if (!caps->IsRange) @@ -458,7 +463,10 @@ static void new_caps(struct caps *caps) caps->usage_count = 0; }
-static int parse_descriptor(BYTE *descriptor, unsigned int index, unsigned int length, unsigned int *feature_index, unsigned int *collection_index, struct collection *collection, struct caps *caps, struct list *features) +static int parse_descriptor(BYTE *descriptor, unsigned int index, unsigned int length, + unsigned int *feature_index, unsigned int *collection_index, + struct collection *collection, struct caps *caps, + struct list *features, struct list *stack) { unsigned int i; for (i = index; i < length;) @@ -544,7 +552,7 @@ static int parse_descriptor(BYTE *descriptor, unsigned int index, unsigned int l
parse_collection(bSize, itemVal, subcollection);
- i = parse_descriptor(descriptor, i+1, length, feature_index, collection_index, subcollection, caps, features); + i = parse_descriptor(descriptor, i+1, length, feature_index, collection_index, subcollection, caps, features, stack); continue; } case TAG_MAIN_END_COLLECTION: @@ -588,11 +596,30 @@ static int parse_descriptor(BYTE *descriptor, unsigned int index, unsigned int l caps->ReportCount = getValue(bSize, itemVal); break; case TAG_GLOBAL_PUSH: - FIXME("Unhandled Push\n"); + { + struct caps_stack *saved = HeapAlloc(GetProcessHeap(), 0, sizeof(*saved)); + saved->caps = *caps; + TRACE("Push\n"); + list_add_tail(stack, &saved->entry); break; + } case TAG_GLOBAL_POP: - FIXME("Unhandled Pop\n"); + { + struct list *tail; + struct caps_stack *saved; + TRACE("Pop\n"); + tail = list_tail(stack); + if (tail) + { + saved = LIST_ENTRY(tail, struct caps_stack, entry); + *caps = saved->caps; + list_remove(tail); + HeapFree(GetProcessHeap(), 0, saved); + } + else + ERR("Pop but no stack!\n"); break; + } default: ERR("Unknown (bTag: 0x%x, bType: 0x%x)\n", bTag, bType); } @@ -1020,6 +1047,7 @@ WINE_HIDP_PREPARSED_DATA* ParseDescriptor(BYTE *descriptor, unsigned int length) struct caps caps;
struct list features; + struct list caps_stack;
unsigned int feature_count = 0; unsigned int cidx; @@ -1037,6 +1065,7 @@ WINE_HIDP_PREPARSED_DATA* ParseDescriptor(BYTE *descriptor, unsigned int length) }
list_init(&features); + list_init(&caps_stack);
base = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*base)); base->index = 1; @@ -1045,10 +1074,21 @@ WINE_HIDP_PREPARSED_DATA* ParseDescriptor(BYTE *descriptor, unsigned int length) memset(&caps, 0, sizeof(caps));
cidx = 0; - parse_descriptor(descriptor, 0, length, &feature_count, &cidx, base, &caps, &features); + parse_descriptor(descriptor, 0, length, &feature_count, &cidx, base, &caps, &features, &caps_stack);
debug_collection(base);
+ if (!list_empty(&caps_stack)) + { + struct caps_stack *entry, *cursor; + ERR("%i unpopped device caps on the stack\n", list_count(&caps_stack)); + LIST_FOR_EACH_ENTRY_SAFE(entry, cursor, &caps_stack, struct caps_stack, entry) + { + list_remove(&entry->entry); + HeapFree(GetProcessHeap(), 0, entry); + } + } + cidx = 2; if (feature_count) {