hidparse.sys: Recompute HIDP_CAPS from the value caps in HidP_GetCaps.

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-09-22 10:08:29 +02:00 committed by Alexandre Julliard
parent 7722168823
commit 218e2718a7
3 changed files with 115 additions and 81 deletions

View File

@ -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)

View File

@ -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;

View File

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