[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