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;