hidclass.sys: Support parsing of explicit usage page.

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-21 09:05:18 +02:00 committed by Alexandre Julliard
parent 2731a014cf
commit 9c77c44509

View file

@ -272,7 +272,9 @@ struct hid_parser_state
{
HIDP_CAPS caps;
USAGE usages[256];
USAGE usages_page[256];
USAGE usages_min[256];
USAGE usages_max[256];
DWORD usages_size;
struct hid_value_caps items;
@ -323,6 +325,9 @@ static void reset_local_items( struct hid_parser_state *state )
memset( &state->items, 0, sizeof(state->items) );
copy_global_items( &state->items, &tmp );
copy_collection_items( &state->items, &tmp );
memset( &state->usages_page, 0, sizeof(state->usages_page) );
memset( &state->usages_min, 0, sizeof(state->usages_min) );
memset( &state->usages_max, 0, sizeof(state->usages_max) );
state->usages_size = 0;
}
@ -352,14 +357,42 @@ static BOOL parse_global_pop( struct hid_parser_state *state )
return TRUE;
}
static BOOL parse_local_usage( struct hid_parser_state *state, USAGE usage )
static BOOL parse_local_usage( struct hid_parser_state *state, USAGE usage_page, USAGE usage )
{
state->usages[state->usages_size] = usage;
if (!usage_page) usage_page = state->items.usage_page;
if (state->items.is_range) state->usages_size = 0;
state->usages_page[state->usages_size] = usage_page;
state->usages_min[state->usages_size] = usage;
state->usages_max[state->usages_size] = usage;
state->items.usage_min = usage;
state->items.usage_max = usage;
state->items.is_range = FALSE;
if (state->usages_size++ == 255) ERR( "HID parser usages stack overflow!\n" );
return state->usages_size <= 255;
}
static void parse_local_usage_min( struct hid_parser_state *state, USAGE usage_page, USAGE usage )
{
if (!usage_page) usage_page = state->items.usage_page;
if (!state->items.is_range) state->usages_max[0] = 0;
state->usages_page[0] = usage_page;
state->usages_min[0] = usage;
state->items.usage_min = usage;
state->items.is_range = TRUE;
state->usages_size = 1;
}
static void parse_local_usage_max( struct hid_parser_state *state, USAGE usage_page, USAGE usage )
{
if (!usage_page) usage_page = state->items.usage_page;
if (!state->items.is_range) state->usages_min[0] = 0;
state->usages_page[0] = usage_page;
state->usages_max[0] = usage;
state->items.usage_max = usage;
state->items.is_range = TRUE;
state->usages_size = 1;
}
static BOOL parse_new_collection( struct hid_parser_state *state )
{
if (!array_reserve( &state->stack, &state->stack_size, state->collection_idx ))
@ -377,6 +410,9 @@ static BOOL parse_new_collection( struct hid_parser_state *state )
copy_collection_items( state->stack + state->collection_idx, &state->items );
state->collection_idx++;
state->items.usage_min = state->usages_min[0];
state->items.usage_max = state->usages_max[0];
state->collections[state->caps.NumberLinkCollectionNodes] = state->items;
state->items.link_collection = state->caps.NumberLinkCollectionNodes;
state->items.link_usage_page = state->items.usage_page;
@ -417,8 +453,8 @@ static BOOL parse_new_value_caps( struct hid_parser_state *state, HIDP_REPORT_TY
list_add_tail( &collection->features, &feature->entry );
feature->type = type;
feature->isData = ((state->items.bit_field & INPUT_DATA_CONST) == 0);
if (j < state->usages_size) state->items.usage_min = state->usages[j];
copy_hidp_value_caps( &feature->caps, &state->items );
if (j < state->usages_size) feature->caps.NotRange.Usage = state->usages_min[j];
feature->caps.ReportCount = 1;
if (j + 1 >= state->usages_size)
{
@ -508,7 +544,6 @@ static int parse_descriptor( BYTE *descriptor, unsigned int index, unsigned int
subcollection->parent = collection;
/* Only set our collection once...
We do not properly handle composite devices yet. */
if (state->usages_size) state->items.usage_min = state->usages[state->usages_size - 1];
list_init(&subcollection->features);
list_init(&subcollection->collections);
parse_collection(size, value, subcollection);
@ -559,15 +594,13 @@ static int parse_descriptor( BYTE *descriptor, unsigned int index, unsigned int
break;
case SHORT_ITEM(TAG_LOCAL_USAGE, TAG_TYPE_LOCAL):
if (!parse_local_usage( state, value )) return -1;
if (!parse_local_usage( state, value >> 16, value & 0xffff )) return -1;
break;
case SHORT_ITEM(TAG_LOCAL_USAGE_MINIMUM, TAG_TYPE_LOCAL):
state->items.usage_min = value;
state->items.is_range = TRUE;
parse_local_usage_min( state, value >> 16, value & 0xffff );
break;
case SHORT_ITEM(TAG_LOCAL_USAGE_MAXIMUM, TAG_TYPE_LOCAL):
state->items.usage_max = value;
state->items.is_range = TRUE;
parse_local_usage_max( state, value >> 16, value & 0xffff );
break;
case SHORT_ITEM(TAG_LOCAL_DESIGNATOR_INDEX, TAG_TYPE_LOCAL):
state->items.designator_min = state->items.designator_max = value;