Rémi Bernon : hidclass.sys: Use the stack to store collection items.
Alexandre Julliard
julliard at winehq.org
Thu Jun 17 15:38:06 CDT 2021
Module: wine
Branch: master
Commit: bf0ab04b10a6153084780e70a80b34c923dc3ea3
URL: https://source.winehq.org/git/wine.git/?a=commit;h=bf0ab04b10a6153084780e70a80b34c923dc3ea3
Author: Rémi Bernon <rbernon at codeweavers.com>
Date: Thu Jun 17 10:20:20 2021 +0200
hidclass.sys: Use the stack to store collection items.
Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/hidclass.sys/descriptor.c | 57 ++++++++++++++++++++++++++++++++++++++----
include/wine/hid.h | 3 +++
2 files changed, 55 insertions(+), 5 deletions(-)
diff --git a/dlls/hidclass.sys/descriptor.c b/dlls/hidclass.sys/descriptor.c
index b57ab2a7da8..19f12d77ded 100644
--- a/dlls/hidclass.sys/descriptor.c
+++ b/dlls/hidclass.sys/descriptor.c
@@ -144,6 +144,9 @@ static void copy_hidp_value_caps( HIDP_VALUE_CAPS *out, const struct hid_value_c
{
out->UsagePage = in->usage_page;
out->ReportID = in->report_id;
+ out->LinkCollection = in->link_collection;
+ out->LinkUsagePage = in->link_usage_page;
+ out->LinkUsage = in->link_usage;
out->IsAlias = FALSE;
out->BitSize = in->bit_size;
out->ReportCount = in->report_count;
@@ -289,6 +292,8 @@ static void debug_print_preparsed(WINE_HIDP_PREPARSED_DATA *data)
struct hid_parser_state
{
+ HIDP_CAPS caps;
+
USAGE usages[256];
DWORD usages_size;
@@ -297,6 +302,7 @@ struct hid_parser_state
struct hid_value_caps *stack;
DWORD stack_size;
DWORD global_idx;
+ DWORD collection_idx;
};
static BOOL array_reserve( struct hid_value_caps **array, DWORD *array_size, DWORD index )
@@ -321,12 +327,21 @@ static void copy_global_items( struct hid_value_caps *dst, const struct hid_valu
dst->report_count = src->report_count;
}
+static void copy_collection_items( struct hid_value_caps *dst, const struct hid_value_caps *src )
+{
+ dst->link_collection = src->link_collection;
+ dst->link_usage_page = src->link_usage_page;
+ dst->link_usage = src->link_usage;
+}
+
static void reset_local_items( struct hid_parser_state *state )
{
struct hid_value_caps tmp;
copy_global_items( &tmp, &state->items );
+ copy_collection_items( &tmp, &state->items );
memset( &state->items, 0, sizeof(state->items) );
copy_global_items( &state->items, &tmp );
+ copy_collection_items( &state->items, &tmp );
state->usages_size = 0;
}
@@ -364,9 +379,44 @@ static BOOL parse_local_usage( struct hid_parser_state *state, USAGE usage )
return state->usages_size <= 255;
}
+static BOOL parse_new_collection( struct hid_parser_state *state )
+{
+ if (!array_reserve( &state->stack, &state->stack_size, state->collection_idx ))
+ {
+ ERR( "HID parser stack overflow!\n" );
+ return FALSE;
+ }
+
+ copy_collection_items( state->stack + state->collection_idx, &state->items );
+ state->collection_idx++;
+
+ state->items.link_collection = state->caps.NumberLinkCollectionNodes;
+ state->items.link_usage_page = state->items.usage_page;
+ state->items.link_usage = state->items.usage_min;
+ state->caps.NumberLinkCollectionNodes++;
+
+ reset_local_items( state );
+ return TRUE;
+}
+
+static BOOL parse_end_collection( struct hid_parser_state *state )
+{
+ if (!state->collection_idx)
+ {
+ ERR( "HID parser collection stack underflow!\n" );
+ return FALSE;
+ }
+
+ state->collection_idx--;
+ copy_collection_items( &state->items, state->stack + state->collection_idx );
+ reset_local_items( state );
+ return TRUE;
+}
+
static void free_parser_state( struct hid_parser_state *state )
{
if (state->global_idx) ERR( "%u unpopped device caps on the stack\n", state->global_idx );
+ if (state->collection_idx) ERR( "%u unpopped device collection on the stack\n", state->collection_idx );
free( state->stack );
free( state );
}
@@ -496,7 +546,7 @@ static int parse_descriptor( BYTE *descriptor, unsigned int index, unsigned int
list_init(&subcollection->features);
list_init(&subcollection->collections);
parse_collection(size, value, subcollection);
- reset_local_items( state );
+ if (!parse_new_collection( state )) return -1;
if ((i = parse_descriptor( descriptor, i, length, feature_index, collection_index,
subcollection, state )) < 0)
@@ -504,7 +554,7 @@ static int parse_descriptor( BYTE *descriptor, unsigned int index, unsigned int
continue;
}
case SHORT_ITEM(TAG_MAIN_END_COLLECTION, TAG_TYPE_MAIN):
- reset_local_items( state );
+ if (!parse_end_collection( state )) return -1;
return i;
case SHORT_ITEM(TAG_GLOBAL_USAGE_PAGE, TAG_TYPE_GLOBAL):
@@ -611,9 +661,6 @@ static void build_elements(WINE_HID_REPORT *wine_report, WINE_HID_ELEMENT *elems
wine_element->caps = feature->caps;
wine_element->caps.BitField = feature->BitField;
- wine_element->caps.LinkCollection = feature->collection->index;
- wine_element->caps.LinkUsage = feature->collection->caps.NotRange.Usage;
- wine_element->caps.LinkUsagePage = feature->collection->caps.UsagePage;
wine_element->caps.IsAbsolute = feature->IsAbsolute;
wine_element->caps.HasNull = feature->HasNull;
diff --git a/include/wine/hid.h b/include/wine/hid.h
index 50b1493ab62..47aeda5575c 100644
--- a/include/wine/hid.h
+++ b/include/wine/hid.h
@@ -81,6 +81,9 @@ struct hid_value_caps
BOOLEAN is_string_range;
BOOLEAN is_designator_range;
UCHAR report_id;
+ USHORT link_collection;
+ USAGE link_usage_page;
+ USAGE link_usage;
USHORT bit_size;
USHORT report_count;
LONG logical_min;
More information about the wine-cvs
mailing list