hidclass.sys: Use the stack to store collection items.

Signed-off-by: Rémi Bernon <rbernon@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Rémi Bernon 2021-06-17 10:20:20 +02:00 committed by Alexandre Julliard
parent 34cbc202f3
commit bf0ab04b10
2 changed files with 55 additions and 5 deletions

View File

@ -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;

View File

@ -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;