Signed-off-by: Rémi Bernon rbernon@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 */
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/hidparse.sys/main.c | 90 +++++++++++++++++----------------------- 1 file changed, 39 insertions(+), 51 deletions(-)
diff --git a/dlls/hidparse.sys/main.c b/dlls/hidparse.sys/main.c index d1191a20789..8440d93e34e 100644 --- a/dlls/hidparse.sys/main.c +++ b/dlls/hidparse.sys/main.c @@ -135,7 +135,12 @@ static void debug_print_preparsed( struct hid_preparsed_data *data )
struct hid_parser_state { - HIDP_CAPS caps; + USAGE usage; + USAGE usage_page; + USHORT input_report_byte_length; + USHORT output_report_byte_length; + USHORT feature_report_byte_length; + USHORT number_link_collection_nodes;
USAGE usages_page[256]; USAGE usages_min[256]; @@ -155,10 +160,10 @@ struct hid_parser_state struct hid_value_caps *values[3]; ULONG values_size[3];
- ULONG bit_size[3][256]; - USHORT *byte_size[3]; /* pointers to caps */ - USHORT *value_idx[3]; /* pointers to caps */ - USHORT *data_idx[3]; /* pointers to caps */ + ULONG bit_size[3][256]; + USHORT byte_length[3]; + USHORT caps_count[3]; + USHORT data_count[3]; };
static BOOL array_reserve( struct hid_value_caps **array, DWORD *array_size, DWORD index ) @@ -274,7 +279,7 @@ static BOOL parse_new_collection( struct hid_parser_state *state ) return FALSE; }
- if (!array_reserve( &state->collections, &state->collections_size, state->caps.NumberLinkCollectionNodes )) + if (!array_reserve( &state->collections, &state->collections_size, state->number_link_collection_nodes )) { ERR( "HID parser collections overflow!\n" ); return FALSE; @@ -286,16 +291,16 @@ static BOOL parse_new_collection( struct hid_parser_state *state ) state->items.usage_min = state->usages_min[0]; state->items.usage_max = state->usages_max[0];
- state->collections[state->caps.NumberLinkCollectionNodes] = state->items; - state->items.link_collection = state->caps.NumberLinkCollectionNodes; + state->collections[state->number_link_collection_nodes] = state->items; + state->items.link_collection = state->number_link_collection_nodes; state->items.link_usage_page = state->items.usage_page; state->items.link_usage = state->items.usage_min; - if (!state->caps.NumberLinkCollectionNodes) + if (!state->number_link_collection_nodes) { - state->caps.UsagePage = state->items.usage_page; - state->caps.Usage = state->items.usage_min; + state->usage_page = state->items.usage_page; + state->usage = state->items.usage_min; } - state->caps.NumberLinkCollectionNodes++; + state->number_link_collection_nodes++;
reset_local_items( state ); return TRUE; @@ -320,15 +325,15 @@ static BOOL parse_new_value_caps( struct hid_parser_state *state, HIDP_REPORT_TY struct hid_value_caps *value; USAGE usage_page = state->items.usage_page; DWORD usages_size = max( 1, state->usages_size ); - USHORT *byte_size = state->byte_size[type]; - USHORT *value_idx = state->value_idx[type]; - USHORT *data_idx = state->data_idx[type]; + USHORT *byte_length = &state->byte_length[type]; + USHORT *caps_count = &state->caps_count[type]; + USHORT *data_count = &state->data_count[type]; ULONG start_bit, *bit_size = &state->bit_size[type][state->items.report_id]; BOOL is_array;
if (!*bit_size) *bit_size = 8; *bit_size += state->items.bit_size * state->items.report_count; - *byte_size = max( *byte_size, (*bit_size + 7) / 8 ); + *byte_length = max( *byte_length, (*bit_size + 7) / 8 ); start_bit = *bit_size;
if (!state->items.report_count) @@ -337,12 +342,12 @@ static BOOL parse_new_value_caps( struct hid_parser_state *state, HIDP_REPORT_TY return TRUE; }
- if (!array_reserve( &state->values[type], &state->values_size[type], *value_idx + usages_size )) + if (!array_reserve( &state->values[type], &state->values_size[type], *caps_count + usages_size )) { ERR( "HID parser values overflow!\n" ); return FALSE; } - value = state->values[type] + *value_idx; + value = state->values[type] + *caps_count;
if (!(is_array = HID_VALUE_CAPS_IS_ARRAY( &state->items ))) state->items.report_count -= usages_size - 1; else start_bit -= state->items.report_count * state->items.bit_size; @@ -361,11 +366,11 @@ static BOOL parse_new_value_caps( struct hid_parser_state *state, HIDP_REPORT_TY state->items.usage_page = state->usages_page[usages_size]; state->items.usage_min = state->usages_min[usages_size]; state->items.usage_max = state->usages_max[usages_size]; - state->items.data_index_min = *data_idx; - state->items.data_index_max = *data_idx + state->items.usage_max - state->items.usage_min; - if (state->items.usage_max || state->items.usage_min) *data_idx = state->items.data_index_max + 1; + state->items.data_index_min = *data_count; + state->items.data_index_max = *data_count + state->items.usage_max - state->items.usage_min; + if (state->items.usage_max || state->items.usage_min) *data_count = state->items.data_index_max + 1; *value++ = state->items; - *value_idx += 1; + *caps_count += 1; if (!is_array) state->items.report_count = 1; }
@@ -374,22 +379,6 @@ static BOOL parse_new_value_caps( struct hid_parser_state *state, HIDP_REPORT_TY return TRUE; }
-static void init_parser_state( struct hid_parser_state *state ) -{ - memset( state, 0, sizeof(*state) ); - state->byte_size[HidP_Input] = &state->caps.InputReportByteLength; - state->byte_size[HidP_Output] = &state->caps.OutputReportByteLength; - state->byte_size[HidP_Feature] = &state->caps.FeatureReportByteLength; - - state->value_idx[HidP_Input] = &state->caps.NumberInputValueCaps; - state->value_idx[HidP_Output] = &state->caps.NumberOutputValueCaps; - state->value_idx[HidP_Feature] = &state->caps.NumberFeatureValueCaps; - - state->data_idx[HidP_Input] = &state->caps.NumberInputDataIndices; - state->data_idx[HidP_Output] = &state->caps.NumberOutputDataIndices; - state->data_idx[HidP_Feature] = &state->caps.NumberFeatureDataIndices; -} - static void free_parser_state( struct hid_parser_state *state ) { if (state->global_idx) ERR( "%u unpopped device caps on the stack\n", state->global_idx ); @@ -408,29 +397,29 @@ static struct hid_preparsed_data *build_preparsed_data( struct hid_parser_state struct hid_value_caps *caps; DWORD caps_len, size;
- caps_len = state->caps.NumberInputValueCaps + state->caps.NumberOutputValueCaps + - state->caps.NumberFeatureValueCaps + state->caps.NumberLinkCollectionNodes; + 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] );
if (!(data = ExAllocatePool( pool_type, size ))) return NULL; memset( data, 0, size ); data->magic = HID_MAGIC; data->size = size; - data->usage = state->caps.Usage; - data->usage_page = state->caps.UsagePage; + data->usage = state->usage; + data->usage_page = state->usage_page; data->input_caps_start = 0; - data->input_caps_count = state->caps.NumberInputValueCaps; + data->input_caps_count = state->caps_count[HidP_Input]; data->input_caps_end = data->input_caps_start + data->input_caps_count; - data->input_report_byte_length = state->caps.InputReportByteLength; + data->input_report_byte_length = state->byte_length[HidP_Input]; data->output_caps_start = data->input_caps_end; - data->output_caps_count = state->caps.NumberOutputValueCaps; + data->output_caps_count = state->caps_count[HidP_Output]; data->output_caps_end = data->output_caps_start + data->output_caps_count; - data->output_report_byte_length = state->caps.OutputReportByteLength; + data->output_report_byte_length = state->byte_length[HidP_Output]; data->feature_caps_start = data->output_caps_end; - data->feature_caps_count = state->caps.NumberFeatureValueCaps; + 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->caps.FeatureReportByteLength; - data->number_link_collection_nodes = state->caps.NumberLinkCollectionNodes; + data->feature_report_byte_length = state->byte_length[HidP_Feature]; + data->number_link_collection_nodes = state->number_link_collection_nodes;
caps = HID_INPUT_VALUE_CAPS( data ); memcpy( caps, state->values[0], data->input_caps_count * sizeof(*caps) ); @@ -464,8 +453,7 @@ struct hid_preparsed_data *parse_descriptor( BYTE *descriptor, unsigned int leng } }
- if (!(state = malloc( sizeof(*state) ))) return NULL; - init_parser_state( state ); + if (!(state = calloc( 1, sizeof(*state) ))) return NULL;
for (ptr = descriptor, end = descriptor + length; ptr != end; ptr += size + 1) {
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- 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 */
Or compatible enough ast least.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput8/tests/hid.c | 14 ++++++++-- dlls/hid/hidp.c | 6 ++-- dlls/hidparse.sys/main.c | 8 ++++-- dlls/user32/rawinput.c | 6 +++- include/wine/hid.h | 59 ++++++++++++++++++++++------------------ 5 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index b4aad6b7d5a..2694391bc4e 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -3116,7 +3116,6 @@ static void test_hidp_kdr(void) ok( ret, "HidD_GetPreparsedData failed with error %u\n", GetLastError() );
kdr = (struct hidp_kdr *)preparsed_data; - todo_wine ok( !strncmp( kdr->magic, expect_kdr.magic, 8 ), "got %s expected %s\n", debugstr_an(kdr->magic, 8), debugstr_an(expect_kdr.magic, 8) );
@@ -3135,13 +3134,15 @@ static void test_hidp_kdr(void) check_member( *kdr, expect_kdr, "%d", output_caps_end ); check_member( *kdr, expect_kdr, "%d", output_report_byte_length ); check_member( *kdr, expect_kdr, "%d", feature_caps_start ); + todo_wine check_member( *kdr, expect_kdr, "%d", feature_caps_count ); check_member( *kdr, expect_kdr, "%d", feature_caps_end ); check_member( *kdr, expect_kdr, "%d", feature_report_byte_length ); + todo_wine check_member( *kdr, expect_kdr, "%d", caps_size ); check_member( *kdr, expect_kdr, "%d", number_link_collection_nodes );
- for (i = 0; i < ARRAY_SIZE(expect_caps); ++i) + for (i = 0; i < min( ARRAY_SIZE(expect_caps), kdr->caps_size / sizeof(struct hidp_kdr_caps) ); ++i) { winetest_push_context( "caps[%d]", i ); check_member( kdr->caps[i], expect_caps[i], "%04x", usage_page ); @@ -3150,8 +3151,10 @@ static void test_hidp_kdr(void) check_member( kdr->caps[i], expect_caps[i], "%d", bit_size ); check_member( kdr->caps[i], expect_caps[i], "%d", report_count ); check_member( kdr->caps[i], expect_caps[i], "%d", start_byte ); + todo_wine check_member( kdr->caps[i], expect_caps[i], "%d", total_bits ); check_member( kdr->caps[i], expect_caps[i], "%#x", bit_field ); + todo_wine_if( expect_caps[i].end_byte ) check_member( kdr->caps[i], expect_caps[i], "%d", end_byte ); check_member( kdr->caps[i], expect_caps[i], "%d", link_collection ); check_member( kdr->caps[i], expect_caps[i], "%04x", link_usage_page ); @@ -3171,13 +3174,20 @@ static void test_hidp_kdr(void) check_member( kdr->caps[i], expect_caps[i], "%d", string_max ); check_member( kdr->caps[i], expect_caps[i], "%d", designator_min ); check_member( kdr->caps[i], expect_caps[i], "%d", designator_max ); + todo_wine_if( !(kdr->caps[i].bit_field & 2) && !(kdr->caps[i].flags & HIDP_KDR_CAPS_IS_RANGE) ) check_member( kdr->caps[i], expect_caps[i], "%#x", data_index_min ); + todo_wine_if( !(kdr->caps[i].bit_field & 2) && !(kdr->caps[i].flags & HIDP_KDR_CAPS_IS_RANGE) ) check_member( kdr->caps[i], expect_caps[i], "%#x", data_index_max ); + todo_wine_if( expect_caps[i].null_value ) check_member( kdr->caps[i], expect_caps[i], "%d", null_value ); check_member( kdr->caps[i], expect_caps[i], "%d", unknown ); + todo_wine_if( !(kdr->caps[i].bit_field & 2) ) check_member( kdr->caps[i], expect_caps[i], "%d", logical_min ); + todo_wine_if( kdr->caps[i].flags & HIDP_KDR_CAPS_IS_BUTTON ) check_member( kdr->caps[i], expect_caps[i], "%d", logical_max ); + todo_wine_if( kdr->caps[i].flags & HIDP_KDR_CAPS_IS_BUTTON ) check_member( kdr->caps[i], expect_caps[i], "%d", physical_min ); + todo_wine_if( kdr->caps[i].flags & HIDP_KDR_CAPS_IS_BUTTON ) check_member( kdr->caps[i], expect_caps[i], "%d", physical_max ); check_member( kdr->caps[i], expect_caps[i], "%#x", units ); check_member( kdr->caps[i], expect_caps[i], "%#x", units_exp ); diff --git a/dlls/hid/hidp.c b/dlls/hid/hidp.c index 4abc867fe0f..90dc3211e45 100644 --- a/dlls/hid/hidp.c +++ b/dlls/hid/hidp.c @@ -39,7 +39,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(hidp); static NTSTATUS get_value_caps_range( struct hid_preparsed_data *preparsed, HIDP_REPORT_TYPE report_type, ULONG report_len, const struct hid_value_caps **caps, const struct hid_value_caps **caps_end ) { - if (!preparsed || preparsed->magic != HID_MAGIC) return HIDP_STATUS_INVALID_PREPARSED_DATA; + if (!preparsed || memcmp( preparsed->magic, "HidP KDR", 8 )) return HIDP_STATUS_INVALID_PREPARSED_DATA;
switch (report_type) { @@ -171,7 +171,7 @@ NTSTATUS WINAPI HidP_GetCaps( PHIDP_PREPARSED_DATA preparsed_data, HIDP_CAPS *ca
TRACE( "preparsed_data %p, caps %p.\n", preparsed_data, caps );
- if (!preparsed || preparsed->magic != HID_MAGIC) return HIDP_STATUS_INVALID_PREPARSED_DATA; + if (!preparsed || memcmp( preparsed->magic, "HidP KDR", 8 )) return HIDP_STATUS_INVALID_PREPARSED_DATA;
caps->Usage = preparsed->usage; caps->UsagePage = preparsed->usage_page; @@ -1002,7 +1002,7 @@ NTSTATUS WINAPI HidP_GetLinkCollectionNodes( HIDP_LINK_COLLECTION_NODE *nodes, U
TRACE( "nodes %p, nodes_len %p, preparsed_data %p.\n", nodes, nodes_len, preparsed_data );
- if (!preparsed || preparsed->magic != HID_MAGIC) return HIDP_STATUS_INVALID_PREPARSED_DATA; + if (!preparsed || memcmp( preparsed->magic, "HidP KDR", 8 )) return HIDP_STATUS_INVALID_PREPARSED_DATA;
count = *nodes_len = preparsed->number_link_collection_nodes; if (capacity < count) return HIDP_STATUS_BUFFER_TOO_SMALL; diff --git a/dlls/hidparse.sys/main.c b/dlls/hidparse.sys/main.c index 02a1c2d58d0..19c756d9002 100644 --- a/dlls/hidparse.sys/main.c +++ b/dlls/hidparse.sys/main.c @@ -415,8 +415,7 @@ static struct hid_preparsed_data *build_preparsed_data( struct hid_parser_state if (!(data = ExAllocatePool( pool_type, size ))) return NULL; memset( data, 0, size );
- data->magic = HID_MAGIC; - data->size = size; + memcpy( data->magic, "HidP KDR", 8 ); data->usage = state->usage; data->usage_page = state->usage_page; data->input_caps_start = 0; @@ -635,6 +634,9 @@ NTSTATUS WINAPI HidP_GetCollectionDescription( PHIDP_REPORT_DESCRIPTOR report_de return STATUS_NO_MEMORY; }
+ len = preparsed->caps_size + FIELD_OFFSET(struct hid_preparsed_data, value_caps[0]) + + preparsed->number_link_collection_nodes * sizeof(struct hid_collection_node); + device_desc->CollectionDescLength = 1; device_desc->CollectionDesc[0].UsagePage = preparsed->usage_page; device_desc->CollectionDesc[0].Usage = preparsed->usage; @@ -642,7 +644,7 @@ NTSTATUS WINAPI HidP_GetCollectionDescription( PHIDP_REPORT_DESCRIPTOR report_de 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].PreparsedDataLength = len; device_desc->CollectionDesc[0].PreparsedData = (PHIDP_PREPARSED_DATA)preparsed;
caps = HID_INPUT_VALUE_CAPS( preparsed ); diff --git a/dlls/user32/rawinput.c b/dlls/user32/rawinput.c index 39f8c622fee..3a316024656 100644 --- a/dlls/user32/rawinput.c +++ b/dlls/user32/rawinput.c @@ -717,6 +717,7 @@ UINT WINAPI GetRawInputDeviceInfoA(HANDLE device, UINT command, void *data, UINT */ UINT WINAPI GetRawInputDeviceInfoW(HANDLE handle, UINT command, void *data, UINT *data_size) { + struct hid_preparsed_data *preparsed; RID_DEVICE_INFO info; struct device *device; DWORD len, data_len; @@ -751,7 +752,10 @@ UINT WINAPI GetRawInputDeviceInfoW(HANDLE handle, UINT command, void *data, UINT break;
case RIDI_PREPARSEDDATA: - len = device->data ? ((struct hid_preparsed_data *)device->data)->size : 0; + if (!(preparsed = (struct hid_preparsed_data *)device->data)) len = 0; + else len = preparsed->caps_size + FIELD_OFFSET(struct hid_preparsed_data, value_caps[0]) + + preparsed->number_link_collection_nodes * sizeof(struct hid_collection_node); + if (device->data && len <= data_len && data) memcpy(data, device->data, len); *data_size = len; diff --git a/include/wine/hid.h b/include/wine/hid.h index a74b7eed02b..1d489a24c88 100644 --- a/include/wine/hid.h +++ b/include/wine/hid.h @@ -44,31 +44,36 @@ struct hid_collection_node
struct hid_value_caps { - USAGE usage_page; - USAGE usage_min; - USAGE usage_max; - USHORT data_index_min; - USHORT data_index_max; - USHORT string_min; - USHORT string_max; - USHORT designator_min; - USHORT designator_max; - ULONG flags; - UCHAR report_id; - USHORT link_collection; - USAGE link_usage_page; - USAGE link_usage; - USHORT bit_field; - USHORT bit_size; - USHORT report_count; - UCHAR start_bit; - USHORT start_byte; - LONG logical_min; - LONG logical_max; - LONG physical_min; - LONG physical_max; - ULONG units; - ULONG units_exp; + USHORT usage_page; + UCHAR report_id; + UCHAR start_bit; + USHORT bit_size; + USHORT report_count; + USHORT start_byte; + USHORT total_bits; + ULONG bit_field; + USHORT end_byte; + USHORT link_collection; + USAGE link_usage_page; + USAGE link_usage; + ULONG flags; + ULONG padding[8]; + USAGE usage_min; + USAGE usage_max; + USHORT string_min; + USHORT string_max; + USHORT designator_min; + USHORT designator_max; + USHORT data_index_min; + USHORT data_index_max; + USHORT null_value; + USHORT unknown; + LONG logical_min; + LONG logical_max; + LONG physical_min; + LONG physical_max; + LONG units; + LONG units_exp; };
/* named array continues on next caps */ @@ -85,10 +90,10 @@ struct hid_value_caps
struct hid_preparsed_data { - DWORD magic; - DWORD size; + char magic[8]; USAGE usage; USAGE usage_page; + USHORT unknown[2]; USHORT input_caps_start; USHORT input_caps_count; USHORT input_caps_end;
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/hidparse.sys/main.c | 46 ++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 18 deletions(-)
diff --git a/dlls/hidparse.sys/main.c b/dlls/hidparse.sys/main.c index 19c756d9002..ca102765f93 100644 --- a/dlls/hidparse.sys/main.c +++ b/dlls/hidparse.sys/main.c @@ -328,14 +328,29 @@ static BOOL parse_end_collection( struct hid_parser_state *state ) return TRUE; }
+static void add_new_value_caps( struct hid_parser_state *state, struct hid_value_caps *values, + LONG i, ULONG start_bit ) +{ + DWORD count, usages_size = max( 1, state->usages_size ); + + state->items.start_byte = start_bit / 8; + state->items.start_bit = start_bit % 8; + state->items.usage_page = state->usages_page[usages_size - 1 - i]; + state->items.usage_min = state->usages_min[usages_size - 1 - i]; + state->items.usage_max = state->usages_max[usages_size - 1 - i]; + if (!state->items.usage_max && !state->items.usage_min) count = -1; + else count = state->items.usage_max - state->items.usage_min; + state->items.data_index_min = state->items.data_index_max + 1; + state->items.data_index_max = state->items.data_index_min + count; + values[i] = state->items; +} + static BOOL parse_new_value_caps( struct hid_parser_state *state, HIDP_REPORT_TYPE type ) { - struct hid_value_caps *value; + struct hid_value_caps *values; USAGE usage_page = state->items.usage_page; - DWORD usages_size = max( 1, state->usages_size ); + DWORD i, usages_size = max( 1, state->usages_size ); USHORT *byte_length = &state->byte_length[type]; - USHORT *caps_count = &state->caps_count[type]; - USHORT *data_count = &state->data_count[type]; ULONG start_bit, *bit_size = &state->bit_size[type][state->items.report_id]; BOOL is_array;
@@ -350,12 +365,13 @@ static BOOL parse_new_value_caps( struct hid_parser_state *state, HIDP_REPORT_TY return TRUE; }
- if (!array_reserve( &state->values[type], &state->values_size[type], *caps_count + usages_size )) + if (!array_reserve( &state->values[type], &state->values_size[type], + state->caps_count[type] + usages_size )) { ERR( "HID parser values overflow!\n" ); return FALSE; } - value = state->values[type] + *caps_count; + values = state->values[type] + state->caps_count[type];
if (!(is_array = HID_VALUE_CAPS_IS_ARRAY( &state->items ))) state->items.report_count -= usages_size - 1; else start_bit -= state->items.report_count * state->items.bit_size; @@ -364,23 +380,17 @@ static BOOL parse_new_value_caps( struct hid_parser_state *state, HIDP_REPORT_TY if (state->items.bit_field & INPUT_DATA_CONST) state->items.flags |= HID_VALUE_CAPS_IS_CONSTANT; if (state->items.bit_size == 1 || is_array) state->items.flags |= HID_VALUE_CAPS_IS_BUTTON;
- while (usages_size--) + state->items.data_index_max = state->data_count[type] - 1; + for (i = 0; i < usages_size; ++i) { if (!is_array) start_bit -= state->items.report_count * state->items.bit_size; - else if (usages_size) state->items.flags |= HID_VALUE_CAPS_ARRAY_HAS_MORE; + else if (i < usages_size - 1) state->items.flags |= HID_VALUE_CAPS_ARRAY_HAS_MORE; else state->items.flags &= ~HID_VALUE_CAPS_ARRAY_HAS_MORE; - state->items.start_byte = start_bit / 8; - state->items.start_bit = start_bit % 8; - state->items.usage_page = state->usages_page[usages_size]; - state->items.usage_min = state->usages_min[usages_size]; - state->items.usage_max = state->usages_max[usages_size]; - state->items.data_index_min = *data_count; - state->items.data_index_max = *data_count + state->items.usage_max - state->items.usage_min; - if (state->items.usage_max || state->items.usage_min) *data_count = state->items.data_index_max + 1; - *value++ = state->items; - *caps_count += 1; + add_new_value_caps( state, values, i, start_bit ); if (!is_array) state->items.report_count = 1; } + state->caps_count[type] += usages_size; + state->data_count[type] = state->items.data_index_max + 1;
state->items.usage_page = usage_page; reset_local_items( state );
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput8/tests/hid.c | 2 -- dlls/hidparse.sys/main.c | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index 2694391bc4e..d29cad5690f 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -3174,9 +3174,7 @@ static void test_hidp_kdr(void) check_member( kdr->caps[i], expect_caps[i], "%d", string_max ); check_member( kdr->caps[i], expect_caps[i], "%d", designator_min ); check_member( kdr->caps[i], expect_caps[i], "%d", designator_max ); - todo_wine_if( !(kdr->caps[i].bit_field & 2) && !(kdr->caps[i].flags & HIDP_KDR_CAPS_IS_RANGE) ) check_member( kdr->caps[i], expect_caps[i], "%#x", data_index_min ); - todo_wine_if( !(kdr->caps[i].bit_field & 2) && !(kdr->caps[i].flags & HIDP_KDR_CAPS_IS_RANGE) ) check_member( kdr->caps[i], expect_caps[i], "%#x", data_index_max ); todo_wine_if( expect_caps[i].null_value ) check_member( kdr->caps[i], expect_caps[i], "%d", null_value ); diff --git a/dlls/hidparse.sys/main.c b/dlls/hidparse.sys/main.c index ca102765f93..f577ef952c3 100644 --- a/dlls/hidparse.sys/main.c +++ b/dlls/hidparse.sys/main.c @@ -384,9 +384,9 @@ static BOOL parse_new_value_caps( struct hid_parser_state *state, HIDP_REPORT_TY for (i = 0; i < usages_size; ++i) { if (!is_array) start_bit -= state->items.report_count * state->items.bit_size; - else if (i < usages_size - 1) state->items.flags |= HID_VALUE_CAPS_ARRAY_HAS_MORE; + else if (i) state->items.flags |= HID_VALUE_CAPS_ARRAY_HAS_MORE; else state->items.flags &= ~HID_VALUE_CAPS_ARRAY_HAS_MORE; - add_new_value_caps( state, values, i, start_bit ); + add_new_value_caps( state, values, is_array ? usages_size - i - 1 : i, start_bit ); if (!is_array) state->items.report_count = 1; } state->caps_count[type] += usages_size;
Although we don't need them, it fixes a few todo_wine and reduces the test output.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput8/tests/hid.c | 7 ------- dlls/hidparse.sys/main.c | 15 +++++++++++++++ 2 files changed, 15 insertions(+), 7 deletions(-)
diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index d29cad5690f..371edc99251 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -3151,10 +3151,8 @@ static void test_hidp_kdr(void) check_member( kdr->caps[i], expect_caps[i], "%d", bit_size ); check_member( kdr->caps[i], expect_caps[i], "%d", report_count ); check_member( kdr->caps[i], expect_caps[i], "%d", start_byte ); - todo_wine check_member( kdr->caps[i], expect_caps[i], "%d", total_bits ); check_member( kdr->caps[i], expect_caps[i], "%#x", bit_field ); - todo_wine_if( expect_caps[i].end_byte ) check_member( kdr->caps[i], expect_caps[i], "%d", end_byte ); check_member( kdr->caps[i], expect_caps[i], "%d", link_collection ); check_member( kdr->caps[i], expect_caps[i], "%04x", link_usage_page ); @@ -3176,16 +3174,11 @@ static void test_hidp_kdr(void) check_member( kdr->caps[i], expect_caps[i], "%d", designator_max ); check_member( kdr->caps[i], expect_caps[i], "%#x", data_index_min ); check_member( kdr->caps[i], expect_caps[i], "%#x", data_index_max ); - todo_wine_if( expect_caps[i].null_value ) check_member( kdr->caps[i], expect_caps[i], "%d", null_value ); check_member( kdr->caps[i], expect_caps[i], "%d", unknown ); - todo_wine_if( !(kdr->caps[i].bit_field & 2) ) check_member( kdr->caps[i], expect_caps[i], "%d", logical_min ); - todo_wine_if( kdr->caps[i].flags & HIDP_KDR_CAPS_IS_BUTTON ) check_member( kdr->caps[i], expect_caps[i], "%d", logical_max ); - todo_wine_if( kdr->caps[i].flags & HIDP_KDR_CAPS_IS_BUTTON ) check_member( kdr->caps[i], expect_caps[i], "%d", physical_min ); - todo_wine_if( kdr->caps[i].flags & HIDP_KDR_CAPS_IS_BUTTON ) check_member( kdr->caps[i], expect_caps[i], "%d", physical_max ); check_member( kdr->caps[i], expect_caps[i], "%#x", units ); check_member( kdr->caps[i], expect_caps[i], "%#x", units_exp ); diff --git a/dlls/hidparse.sys/main.c b/dlls/hidparse.sys/main.c index f577ef952c3..ca15a91c75a 100644 --- a/dlls/hidparse.sys/main.c +++ b/dlls/hidparse.sys/main.c @@ -335,6 +335,8 @@ static void add_new_value_caps( struct hid_parser_state *state, struct hid_value
state->items.start_byte = start_bit / 8; state->items.start_bit = start_bit % 8; + state->items.total_bits = state->items.report_count * state->items.bit_size; + state->items.end_byte = (start_bit + state->items.total_bits + 7) / 8; state->items.usage_page = state->usages_page[usages_size - 1 - i]; state->items.usage_min = state->usages_min[usages_size - 1 - i]; state->items.usage_max = state->usages_max[usages_size - 1 - i]; @@ -343,6 +345,15 @@ static void add_new_value_caps( struct hid_parser_state *state, struct hid_value state->items.data_index_min = state->items.data_index_max + 1; state->items.data_index_max = state->items.data_index_min + count; values[i] = state->items; + + if (values[i].flags & HID_VALUE_CAPS_IS_BUTTON) + { + if (!HID_VALUE_CAPS_IS_ARRAY( values + i )) values[i].logical_min = 0; + else values[i].logical_min = values[i].logical_max; + values[i].logical_max = 0; + values[i].physical_min = 0; + values[i].physical_max = 0; + } }
static BOOL parse_new_value_caps( struct hid_parser_state *state, HIDP_REPORT_TYPE type ) @@ -380,6 +391,10 @@ static BOOL parse_new_value_caps( struct hid_parser_state *state, HIDP_REPORT_TY if (state->items.bit_field & INPUT_DATA_CONST) state->items.flags |= HID_VALUE_CAPS_IS_CONSTANT; if (state->items.bit_size == 1 || is_array) state->items.flags |= HID_VALUE_CAPS_IS_BUTTON;
+ if (is_array) state->items.null_value = state->items.logical_min; + else if (!(state->items.bit_field & INPUT_NULL)) state->items.null_value = 0; + else state->items.null_value = 1; + state->items.data_index_max = state->data_count[type] - 1; for (i = 0; i < usages_size; ++i) {