Rémi Bernon : hidparse.sys: Precompute collection node list on the parser side.

Alexandre Julliard julliard at winehq.org
Wed Sep 22 16:04:37 CDT 2021


Module: wine
Branch: master
Commit: 75e74b3a734e7a5c9bf179f252fae22a82536c6b
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=75e74b3a734e7a5c9bf179f252fae22a82536c6b

Author: Rémi Bernon <rbernon at codeweavers.com>
Date:   Wed Sep 22 10:08:31 2021 +0200

hidparse.sys: Precompute collection node list on the parser side.

Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 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 */




More information about the wine-cvs mailing list