[PATCH 1/7] hidparse.sys: Recompute HIDP_CAPS from the value caps in HidP_GetCaps.

Rémi Bernon rbernon at codeweavers.com
Wed Sep 22 03:08:29 CDT 2021


Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
 dlls/hid/hidp.c          |  60 ++++++++++++++++++---
 dlls/hidparse.sys/main.c | 111 +++++++++++++++------------------------
 include/wine/hid.h       |  25 ++++++---
 3 files changed, 115 insertions(+), 81 deletions(-)

diff --git a/dlls/hid/hidp.c b/dlls/hid/hidp.c
index a1cdb951fd4..acb02246523 100644
--- a/dlls/hid/hidp.c
+++ b/dlls/hid/hidp.c
@@ -44,25 +44,27 @@ static NTSTATUS get_value_caps_range( struct hid_preparsed_data *preparsed, HIDP
     switch (report_type)
     {
     case HidP_Input:
-        if (report_len && report_len != preparsed->caps.InputReportByteLength)
+        if (report_len && report_len != preparsed->input_report_byte_length)
             return HIDP_STATUS_INVALID_REPORT_LENGTH;
         *caps = HID_INPUT_VALUE_CAPS( preparsed );
+        *caps_end = *caps + preparsed->input_caps_count;
         break;
     case HidP_Output:
-        if (report_len && report_len != preparsed->caps.OutputReportByteLength)
+        if (report_len && report_len != preparsed->output_report_byte_length)
             return HIDP_STATUS_INVALID_REPORT_LENGTH;
         *caps = HID_OUTPUT_VALUE_CAPS( preparsed );
+        *caps_end = *caps + preparsed->output_caps_count;
         break;
     case HidP_Feature:
-        if (report_len && report_len != preparsed->caps.FeatureReportByteLength)
+        if (report_len && report_len != preparsed->feature_report_byte_length)
             return HIDP_STATUS_INVALID_REPORT_LENGTH;
         *caps = HID_FEATURE_VALUE_CAPS( preparsed );
+        *caps_end = *caps + preparsed->feature_caps_count;
         break;
     default:
         return HIDP_STATUS_INVALID_REPORT_TYPE;
     }
 
-    *caps_end = *caps + preparsed->value_caps_count[report_type];
     return HIDP_STATUS_SUCCESS;
 }
 
@@ -165,12 +167,58 @@ NTSTATUS WINAPI HidP_GetButtonCaps( HIDP_REPORT_TYPE report_type, HIDP_BUTTON_CA
 NTSTATUS WINAPI HidP_GetCaps( PHIDP_PREPARSED_DATA preparsed_data, HIDP_CAPS *caps )
 {
     struct hid_preparsed_data *preparsed = (struct hid_preparsed_data *)preparsed_data;
+    struct hid_value_caps *it, *end;
 
     TRACE( "preparsed_data %p, caps %p.\n", preparsed_data, caps );
 
     if (!preparsed || preparsed->magic != HID_MAGIC) return HIDP_STATUS_INVALID_PREPARSED_DATA;
 
-    *caps = preparsed->caps;
+    caps->Usage = preparsed->usage;
+    caps->UsagePage = preparsed->usage_page;
+    caps->InputReportByteLength = preparsed->input_report_byte_length;
+    caps->OutputReportByteLength = preparsed->output_report_byte_length;
+    caps->FeatureReportByteLength = preparsed->feature_report_byte_length;
+    caps->NumberLinkCollectionNodes = preparsed->number_link_collection_nodes;
+    caps->NumberInputButtonCaps = 0;
+    caps->NumberInputValueCaps = 0;
+    caps->NumberInputDataIndices = 0;
+    caps->NumberOutputButtonCaps = 0;
+    caps->NumberOutputValueCaps = 0;
+    caps->NumberOutputDataIndices = 0;
+    caps->NumberFeatureButtonCaps = 0;
+    caps->NumberFeatureValueCaps = 0;
+    caps->NumberFeatureDataIndices = 0;
+
+    for (it = HID_INPUT_VALUE_CAPS( preparsed ), end = it + preparsed->input_caps_count;
+         it != end; ++it)
+    {
+        if (!it->usage_min && !it->usage_max) continue;
+        if (it->flags & HID_VALUE_CAPS_IS_BUTTON) caps->NumberInputButtonCaps++;
+        else caps->NumberInputValueCaps++;
+        if (!(it->flags & HID_VALUE_CAPS_IS_RANGE)) caps->NumberInputDataIndices++;
+        else caps->NumberInputDataIndices += it->data_index_max - it->data_index_min + 1;
+    }
+
+    for (it = HID_OUTPUT_VALUE_CAPS( preparsed ), end = it + preparsed->output_caps_count;
+         it != end; ++it)
+    {
+        if (!it->usage_min && !it->usage_max) continue;
+        if (it->flags & HID_VALUE_CAPS_IS_BUTTON) caps->NumberOutputButtonCaps++;
+        else caps->NumberOutputValueCaps++;
+        if (!(it->flags & HID_VALUE_CAPS_IS_RANGE)) caps->NumberOutputDataIndices++;
+        else caps->NumberOutputDataIndices += it->data_index_max - it->data_index_min + 1;
+    }
+
+    for (it = HID_FEATURE_VALUE_CAPS( preparsed ), end = it + preparsed->feature_caps_count;
+         it != end; ++it)
+    {
+        if (!it->usage_min && !it->usage_max) continue;
+        if (it->flags & HID_VALUE_CAPS_IS_BUTTON) caps->NumberFeatureButtonCaps++;
+        else caps->NumberFeatureValueCaps++;
+        if (!(it->flags & HID_VALUE_CAPS_IS_RANGE)) caps->NumberFeatureDataIndices++;
+        else caps->NumberFeatureDataIndices += it->data_index_max - it->data_index_min + 1;
+    }
+
     return HIDP_STATUS_SUCCESS;
 }
 
@@ -956,7 +1004,7 @@ NTSTATUS WINAPI HidP_GetLinkCollectionNodes( HIDP_LINK_COLLECTION_NODE *nodes, U
 
     if (!preparsed || preparsed->magic != HID_MAGIC) return HIDP_STATUS_INVALID_PREPARSED_DATA;
 
-    count = *nodes_len = preparsed->caps.NumberLinkCollectionNodes;
+    count = *nodes_len = preparsed->number_link_collection_nodes;
     if (capacity < count) return HIDP_STATUS_BUFFER_TOO_SMALL;
 
     for (i = 0; i < count; ++i)
diff --git a/dlls/hidparse.sys/main.c b/dlls/hidparse.sys/main.c
index 3170abc50b5..d1191a20789 100644
--- a/dlls/hidparse.sys/main.c
+++ b/dlls/hidparse.sys/main.c
@@ -116,30 +116,20 @@ static void debug_print_preparsed( struct hid_preparsed_data *data )
 
     if (TRACE_ON( hidp ))
     {
-        TRACE( "START PREPARSED Data <<< Usage: %i, UsagePage: %i, "
-               "InputReportByteLength: %i, tOutputReportByteLength: %i, "
-               "FeatureReportByteLength: %i, NumberLinkCollectionNodes: %i, "
-               "NumberInputButtonCaps: %i, NumberInputValueCaps: %i, "
-               "NumberInputDataIndices: %i, NumberOutputButtonCaps: %i, "
-               "NumberOutputValueCaps: %i, NumberOutputDataIndices: %i, "
-               "NumberFeatureButtonCaps: %i, NumberFeatureValueCaps: %i, "
-               "NumberFeatureDataIndices: %i\n",
-               data->caps.Usage, data->caps.UsagePage, data->caps.InputReportByteLength,
-               data->caps.OutputReportByteLength, data->caps.FeatureReportByteLength,
-               data->caps.NumberLinkCollectionNodes, data->caps.NumberInputButtonCaps,
-               data->caps.NumberInputValueCaps, data->caps.NumberInputDataIndices,
-               data->caps.NumberOutputButtonCaps, data->caps.NumberOutputValueCaps,
-               data->caps.NumberOutputDataIndices, data->caps.NumberFeatureButtonCaps,
-               data->caps.NumberFeatureValueCaps, data->caps.NumberFeatureDataIndices );
-        end = data->value_caps_count[HidP_Input];
-        for (i = 0; i < end; i++) TRACE( "INPUT: %s\n", debugstr_hid_value_caps( HID_INPUT_VALUE_CAPS( data ) + i ) );
-        end = data->value_caps_count[HidP_Output];
-        for (i = 0; i < end; i++) TRACE( "OUTPUT: %s\n", debugstr_hid_value_caps( HID_OUTPUT_VALUE_CAPS( data ) + i ) );
-        end = data->value_caps_count[HidP_Feature];
-        for (i = 0; i < end; i++) TRACE( "FEATURE: %s\n", debugstr_hid_value_caps( HID_FEATURE_VALUE_CAPS( data ) + i ) );
-        end = data->caps.NumberLinkCollectionNodes;
-        for (i = 0; i < end; i++) TRACE( "COLLECTION: %s\n", debugstr_hid_value_caps( HID_COLLECTION_VALUE_CAPS( data ) + i ) );
-        TRACE(">>> END Preparsed Data\n");
+        TRACE( "usage %02x:%02x input %u-(%u)-%u, report len %u output %u-(%u)-%u, report len %u "
+               "feature %u-(%u)-%u, report len %u collections %u\n", data->usage_page, data->usage,
+                data->input_caps_start, data->input_caps_count, data->input_caps_end, data->input_report_byte_length,
+                data->output_caps_start, data->output_caps_count, data->output_caps_end, data->output_report_byte_length,
+                data->feature_caps_start, data->feature_caps_count, data->feature_caps_end, data->feature_report_byte_length,
+                data->number_link_collection_nodes );
+        end = data->input_caps_count;
+        for (i = 0; i < end; i++) TRACE( "input %d: %s\n", i, debugstr_hid_value_caps( HID_INPUT_VALUE_CAPS( data ) + i ) );
+        end = data->output_caps_count;
+        for (i = 0; i < end; i++) TRACE( "output %d: %s\n", i, debugstr_hid_value_caps( HID_OUTPUT_VALUE_CAPS( data ) + i ) );
+        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 ) );
     }
 }
 
@@ -416,7 +406,7 @@ static struct hid_preparsed_data *build_preparsed_data( struct hid_parser_state
 {
     struct hid_preparsed_data *data;
     struct hid_value_caps *caps;
-    DWORD i, button, filler, caps_len, size;
+    DWORD caps_len, size;
 
     caps_len = state->caps.NumberInputValueCaps + state->caps.NumberOutputValueCaps +
                state->caps.NumberFeatureValueCaps + state->caps.NumberLinkCollectionNodes;
@@ -426,47 +416,30 @@ static struct hid_preparsed_data *build_preparsed_data( struct hid_parser_state
     memset( data, 0, size );
     data->magic = HID_MAGIC;
     data->size = size;
-    data->caps = state->caps;
-    data->value_caps_count[HidP_Input] = state->caps.NumberInputValueCaps;
-    data->value_caps_count[HidP_Output] = state->caps.NumberOutputValueCaps;
-    data->value_caps_count[HidP_Feature] = state->caps.NumberFeatureValueCaps;
-
-    /* fixup value vs button vs filler counts */
+    data->usage = state->caps.Usage;
+    data->usage_page = state->caps.UsagePage;
+    data->input_caps_start = 0;
+    data->input_caps_count = state->caps.NumberInputValueCaps;
+    data->input_caps_end = data->input_caps_start + data->input_caps_count;
+    data->input_report_byte_length = state->caps.InputReportByteLength;
+    data->output_caps_start = data->input_caps_end;
+    data->output_caps_count = state->caps.NumberOutputValueCaps;
+    data->output_caps_end = data->output_caps_start + data->output_caps_count;
+    data->output_report_byte_length = state->caps.OutputReportByteLength;
+    data->feature_caps_start = data->output_caps_end;
+    data->feature_caps_count = state->caps.NumberFeatureValueCaps;
+    data->feature_caps_end = data->feature_caps_start + data->feature_caps_count;
+    data->feature_report_byte_length = state->caps.FeatureReportByteLength;
+    data->number_link_collection_nodes = state->caps.NumberLinkCollectionNodes;
 
     caps = HID_INPUT_VALUE_CAPS( data );
-    memcpy( caps, state->values[0], data->caps.NumberInputValueCaps * sizeof(*caps) );
-    for (i = 0, button = 0, filler = 0; i < data->caps.NumberInputValueCaps; ++i)
-    {
-        if (!caps[i].usage_min && !caps[i].usage_max) filler++;
-        else if (caps[i].flags & HID_VALUE_CAPS_IS_BUTTON) button++;
-    }
-    data->caps.NumberInputButtonCaps = button;
-    data->caps.NumberInputValueCaps -= filler + button;
-
+    memcpy( caps, state->values[0], data->input_caps_count * sizeof(*caps) );
     caps = HID_OUTPUT_VALUE_CAPS( data );
-    memcpy( caps, state->values[1], data->caps.NumberOutputValueCaps * sizeof(*caps) );
-    for (i = 0, button = 0, filler = 0; i < data->caps.NumberOutputValueCaps; ++i)
-    {
-        if (!caps[i].usage_min && !caps[i].usage_max) filler++;
-        else if (caps[i].flags & HID_VALUE_CAPS_IS_BUTTON) button++;
-    }
-    caps += data->caps.NumberOutputValueCaps;
-    data->caps.NumberOutputButtonCaps = button;
-    data->caps.NumberOutputValueCaps -= filler + button;
-
+    memcpy( caps, state->values[1], data->output_caps_count * sizeof(*caps) );
     caps = HID_FEATURE_VALUE_CAPS( data );
-    memcpy( caps, state->values[2], data->caps.NumberFeatureValueCaps * sizeof(*caps) );
-    for (i = 0, button = 0, filler = 0; i < data->caps.NumberFeatureValueCaps; ++i)
-    {
-        if (!caps[i].usage_min && !caps[i].usage_max) filler++;
-        else if (caps[i].flags & HID_VALUE_CAPS_IS_BUTTON) button++;
-    }
-    caps += data->caps.NumberFeatureValueCaps;
-    data->caps.NumberFeatureButtonCaps = button;
-    data->caps.NumberFeatureValueCaps -= filler + button;
-
+    memcpy( caps, state->values[2], data->feature_caps_count * sizeof(*caps) );
     caps = HID_COLLECTION_VALUE_CAPS( data );
-    memcpy( caps, state->collections, data->caps.NumberLinkCollectionNodes * sizeof(*caps) );
+    memcpy( caps, state->collections, data->number_link_collection_nodes * sizeof(*caps) );
 
     return data;
 }
@@ -645,17 +618,17 @@ NTSTATUS WINAPI HidP_GetCollectionDescription( PHIDP_REPORT_DESCRIPTOR report_de
     }
 
     device_desc->CollectionDescLength = 1;
-    device_desc->CollectionDesc[0].UsagePage = preparsed->caps.UsagePage;
-    device_desc->CollectionDesc[0].Usage = preparsed->caps.Usage;
+    device_desc->CollectionDesc[0].UsagePage = preparsed->usage_page;
+    device_desc->CollectionDesc[0].Usage = preparsed->usage;
     device_desc->CollectionDesc[0].CollectionNumber = 1;
-    device_desc->CollectionDesc[0].InputLength = preparsed->caps.InputReportByteLength;
-    device_desc->CollectionDesc[0].OutputLength = preparsed->caps.OutputReportByteLength;
-    device_desc->CollectionDesc[0].FeatureLength = preparsed->caps.FeatureReportByteLength;
+    device_desc->CollectionDesc[0].InputLength = preparsed->input_report_byte_length;
+    device_desc->CollectionDesc[0].OutputLength = preparsed->output_report_byte_length;
+    device_desc->CollectionDesc[0].FeatureLength = preparsed->feature_report_byte_length;
     device_desc->CollectionDesc[0].PreparsedDataLength = preparsed->size;
     device_desc->CollectionDesc[0].PreparsedData = (PHIDP_PREPARSED_DATA)preparsed;
 
     caps = HID_INPUT_VALUE_CAPS( preparsed );
-    caps_end = caps + preparsed->value_caps_count[HidP_Input];
+    caps_end = caps + preparsed->input_caps_count;
     for (; caps != caps_end; ++caps)
     {
         len = caps->start_byte * 8 + caps->start_bit + caps->bit_size * caps->report_count;
@@ -664,7 +637,7 @@ NTSTATUS WINAPI HidP_GetCollectionDescription( PHIDP_REPORT_DESCRIPTOR report_de
     }
 
     caps = HID_OUTPUT_VALUE_CAPS( preparsed );
-    caps_end = caps + preparsed->value_caps_count[HidP_Output];
+    caps_end = caps + preparsed->output_caps_count;
     for (; caps != caps_end; ++caps)
     {
         len = caps->start_byte * 8 + caps->start_bit + caps->bit_size * caps->report_count;
@@ -673,7 +646,7 @@ NTSTATUS WINAPI HidP_GetCollectionDescription( PHIDP_REPORT_DESCRIPTOR report_de
     }
 
     caps = HID_FEATURE_VALUE_CAPS( preparsed );
-    caps_end = caps + preparsed->value_caps_count[HidP_Feature];
+    caps_end = caps + preparsed->feature_caps_count;
     for (; caps != caps_end; ++caps)
     {
         len = caps->start_byte * 8 + caps->start_bit + caps->bit_size * caps->report_count;
diff --git a/include/wine/hid.h b/include/wine/hid.h
index 43f881bcc52..10fccda07cc 100644
--- a/include/wine/hid.h
+++ b/include/wine/hid.h
@@ -76,14 +76,27 @@ struct hid_preparsed_data
 {
     DWORD magic;
     DWORD size;
-    HIDP_CAPS caps;
-    USHORT value_caps_count[3];
+    USAGE usage;
+    USAGE usage_page;
+    USHORT input_caps_start;
+    USHORT input_caps_count;
+    USHORT input_caps_end;
+    USHORT input_report_byte_length;
+    USHORT output_caps_start;
+    USHORT output_caps_count;
+    USHORT output_caps_end;
+    USHORT output_report_byte_length;
+    USHORT feature_caps_start;
+    USHORT feature_caps_count;
+    USHORT feature_caps_end;
+    USHORT feature_report_byte_length;
+    USHORT number_link_collection_nodes;
     struct hid_value_caps value_caps[1];
 };
 
-#define HID_INPUT_VALUE_CAPS(d) ((d)->value_caps)
-#define HID_OUTPUT_VALUE_CAPS(d) (HID_INPUT_VALUE_CAPS(d) + (d)->value_caps_count[0])
-#define HID_FEATURE_VALUE_CAPS(d) (HID_OUTPUT_VALUE_CAPS(d) + (d)->value_caps_count[1])
-#define HID_COLLECTION_VALUE_CAPS(d) (HID_FEATURE_VALUE_CAPS(d) + (d)->value_caps_count[2])
+#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)
 
 #endif /* __WINE_PARSE_H */
-- 
2.33.0




More information about the wine-devel mailing list