From 75e74b3a734e7a5c9bf179f252fae22a82536c6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Bernon?= Date: Wed, 22 Sep 2021 10:08:31 +0200 Subject: [PATCH] hidparse.sys: Precompute collection node list on the parser side. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: RĂ©mi Bernon Signed-off-by: Alexandre Julliard --- dlls/hid/hidp.c | 23 ++++++++------------- dlls/hidparse.sys/main.c | 44 +++++++++++++++++++++++++++++++++------- include/wine/hid.h | 15 +++++++++++++- 3 files changed, 59 insertions(+), 23 deletions(-) diff --git a/dlls/hid/hidp.c b/dlls/hid/hidp.c index acb02246523..4abc867fe0f 100644 --- a/dlls/hid/hidp.c +++ b/dlls/hid/hidp.c @@ -997,7 +997,7 @@ NTSTATUS WINAPI HidP_GetData( HIDP_REPORT_TYPE report_type, HIDP_DATA *data, ULO NTSTATUS WINAPI HidP_GetLinkCollectionNodes( HIDP_LINK_COLLECTION_NODE *nodes, ULONG *nodes_len, PHIDP_PREPARSED_DATA preparsed_data ) { struct hid_preparsed_data *preparsed = (struct hid_preparsed_data *)preparsed_data; - struct hid_value_caps *caps = HID_COLLECTION_VALUE_CAPS( preparsed ); + struct hid_collection_node *collections = HID_COLLECTION_NODES( preparsed ); ULONG i, count, capacity = *nodes_len; TRACE( "nodes %p, nodes_len %p, preparsed_data %p.\n", nodes, nodes_len, preparsed_data ); @@ -1009,21 +1009,14 @@ NTSTATUS WINAPI HidP_GetLinkCollectionNodes( HIDP_LINK_COLLECTION_NODE *nodes, U for (i = 0; i < count; ++i) { - nodes[i].LinkUsagePage = caps[i].usage_page; - nodes[i].LinkUsage = caps[i].usage_min; - nodes[i].Parent = caps[i].link_collection; - nodes[i].CollectionType = caps[i].bit_field; + nodes[i].LinkUsagePage = collections[i].usage_page; + nodes[i].LinkUsage = collections[i].usage; + nodes[i].Parent = collections[i].parent; + nodes[i].CollectionType = collections[i].collection_type; + nodes[i].FirstChild = collections[i].first_child; + nodes[i].NextSibling = collections[i].next_sibling; + nodes[i].NumberOfChildren = collections[i].number_of_children; nodes[i].IsAlias = 0; - nodes[i].FirstChild = 0; - nodes[i].NextSibling = 0; - nodes[i].NumberOfChildren = 0; - - if (i > 0) - { - nodes[i].NextSibling = nodes[nodes[i].Parent].FirstChild; - nodes[nodes[i].Parent].FirstChild = i; - nodes[nodes[i].Parent].NumberOfChildren++; - } } return HIDP_STATUS_SUCCESS; diff --git a/dlls/hidparse.sys/main.c b/dlls/hidparse.sys/main.c index 8440d93e34e..02a1c2d58d0 100644 --- a/dlls/hidparse.sys/main.c +++ b/dlls/hidparse.sys/main.c @@ -110,6 +110,14 @@ static inline const char *debugstr_hid_value_caps( struct hid_value_caps *caps ) caps->units, caps->units_exp, caps->logical_min, caps->logical_max, caps->physical_min, caps->physical_max ); } +static inline const char *debugstr_hid_collection_node( struct hid_collection_node *node ) +{ + if (!node) return "(null)"; + return wine_dbg_sprintf( "Usg %02x:%02x, Parent %u, Next %u, NbChild %u, Child %u, Type %02x", + node->usage_page, node->usage, node->parent, node->next_sibling, + node->number_of_children, node->first_child, node->collection_type ); +} + static void debug_print_preparsed( struct hid_preparsed_data *data ) { unsigned int i, end; @@ -129,7 +137,7 @@ static void debug_print_preparsed( struct hid_preparsed_data *data ) end = data->feature_caps_count; for (i = 0; i < end; i++) TRACE( "feature %d: %s\n", i, debugstr_hid_value_caps( HID_FEATURE_VALUE_CAPS( data ) + i ) ); end = data->number_link_collection_nodes; - for (i = 0; i < end; i++) TRACE( "collection %d: %s\n", i, debugstr_hid_value_caps( HID_COLLECTION_VALUE_CAPS( data ) + i ) ); + for (i = 0; i < end; i++) TRACE( "collection %d: %s\n", i, debugstr_hid_collection_node( HID_COLLECTION_NODES( data ) + i ) ); } } @@ -393,16 +401,20 @@ static void free_parser_state( struct hid_parser_state *state ) static struct hid_preparsed_data *build_preparsed_data( struct hid_parser_state *state, POOL_TYPE pool_type ) { + struct hid_collection_node *nodes; struct hid_preparsed_data *data; struct hid_value_caps *caps; - DWORD caps_len, size; + DWORD i, size, caps_size; - caps_len = state->caps_count[HidP_Input] + state->caps_count[HidP_Output] + - state->caps_count[HidP_Feature] + state->number_link_collection_nodes; - size = FIELD_OFFSET( struct hid_preparsed_data, value_caps[caps_len] ); + caps_size = state->caps_count[HidP_Input] + state->caps_count[HidP_Output] + + state->caps_count[HidP_Feature]; + caps_size *= sizeof(struct hid_value_caps); + size = caps_size + FIELD_OFFSET(struct hid_preparsed_data, value_caps[0]) + + state->number_link_collection_nodes * sizeof(struct hid_collection_node); if (!(data = ExAllocatePool( pool_type, size ))) return NULL; memset( data, 0, size ); + data->magic = HID_MAGIC; data->size = size; data->usage = state->usage; @@ -419,6 +431,7 @@ static struct hid_preparsed_data *build_preparsed_data( struct hid_parser_state data->feature_caps_count = state->caps_count[HidP_Feature]; data->feature_caps_end = data->feature_caps_start + data->feature_caps_count; data->feature_report_byte_length = state->byte_length[HidP_Feature]; + data->caps_size = caps_size; data->number_link_collection_nodes = state->number_link_collection_nodes; caps = HID_INPUT_VALUE_CAPS( data ); @@ -427,8 +440,25 @@ static struct hid_preparsed_data *build_preparsed_data( struct hid_parser_state memcpy( caps, state->values[1], data->output_caps_count * sizeof(*caps) ); caps = HID_FEATURE_VALUE_CAPS( data ); memcpy( caps, state->values[2], data->feature_caps_count * sizeof(*caps) ); - caps = HID_COLLECTION_VALUE_CAPS( data ); - memcpy( caps, state->collections, data->number_link_collection_nodes * sizeof(*caps) ); + + nodes = HID_COLLECTION_NODES( data ); + for (i = 0; i < data->number_link_collection_nodes; ++i) + { + nodes[i].usage_page = state->collections[i].usage_page; + nodes[i].usage = state->collections[i].usage_min; + nodes[i].parent = state->collections[i].link_collection; + nodes[i].collection_type = state->collections[i].bit_field; + nodes[i].first_child = 0; + nodes[i].next_sibling = 0; + nodes[i].number_of_children = 0; + + if (i > 0) + { + nodes[i].next_sibling = nodes[nodes[i].parent].first_child; + nodes[nodes[i].parent].first_child = i; + nodes[nodes[i].parent].number_of_children++; + } + } return data; } diff --git a/include/wine/hid.h b/include/wine/hid.h index 10fccda07cc..a74b7eed02b 100644 --- a/include/wine/hid.h +++ b/include/wine/hid.h @@ -31,6 +31,17 @@ #define HID_MAGIC 0x8491759 +struct hid_collection_node +{ + USAGE usage; + USAGE usage_page; + USHORT parent; + USHORT number_of_children; + USHORT next_sibling; + USHORT first_child; + ULONG collection_type; +}; + struct hid_value_caps { USAGE usage_page; @@ -90,13 +101,15 @@ struct hid_preparsed_data USHORT feature_caps_count; USHORT feature_caps_end; USHORT feature_report_byte_length; + USHORT caps_size; USHORT number_link_collection_nodes; struct hid_value_caps value_caps[1]; + /* struct hid_collection_node nodes[1] */ }; #define HID_INPUT_VALUE_CAPS(d) ((d)->value_caps + (d)->input_caps_start) #define HID_OUTPUT_VALUE_CAPS(d) ((d)->value_caps + (d)->output_caps_start) #define HID_FEATURE_VALUE_CAPS(d) ((d)->value_caps + (d)->feature_caps_start) -#define HID_COLLECTION_VALUE_CAPS(d) ((d)->value_caps + (d)->feature_caps_end) +#define HID_COLLECTION_NODES(d) (struct hid_collection_node *)((char *)(d)->value_caps + (d)->caps_size) #endif /* __WINE_PARSE_H */