[PATCH 5/5] dinput/tests: Add a test for multiple top-level collections.
Rémi Bernon
wine at gitlab.winehq.org
Thu Jun 2 02:39:14 CDT 2022
From: Rémi Bernon <rbernon at codeweavers.com>
Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
dlls/dinput/tests/hid.c | 384 ++++++++++++++++++++++++++++++----------
1 file changed, 292 insertions(+), 92 deletions(-)
diff --git a/dlls/dinput/tests/hid.c b/dlls/dinput/tests/hid.c
index 81bf8ed46f8..2d7199fa3e5 100644
--- a/dlls/dinput/tests/hid.c
+++ b/dlls/dinput/tests/hid.c
@@ -3021,6 +3021,106 @@ struct hidp_kdr
/* struct hidp_kdr_node nodes[1] */
};
+static void check_preparsed_data( HANDLE file, const struct hidp_kdr *expect_kdr,
+ UINT expect_caps_count, const struct hidp_kdr_caps *expect_caps,
+ UINT expect_nodes_count, const struct hidp_kdr_node *expect_nodes )
+{
+ PHIDP_PREPARSED_DATA preparsed_data;
+ struct hidp_kdr *kdr;
+ BOOL ret;
+ UINT i;
+
+ ret = HidD_GetPreparsedData( file, &preparsed_data );
+ ok( ret, "HidD_GetPreparsedData failed with error %lu\n", GetLastError() );
+
+ kdr = (struct hidp_kdr *)preparsed_data;
+ ok( !strncmp( kdr->magic, expect_kdr->magic, 8 ), "got %s expected %s\n",
+ debugstr_an(kdr->magic, 8), debugstr_an(expect_kdr->magic, 8) );
+
+ if (!strncmp( kdr->magic, expect_kdr->magic, 8 ))
+ {
+ check_member( *kdr, *expect_kdr, "%04x", usage );
+ check_member( *kdr, *expect_kdr, "%04x", usage_page );
+ check_member( *kdr, *expect_kdr, "%#x", unknown[0] );
+ check_member( *kdr, *expect_kdr, "%#x", unknown[1] );
+ check_member( *kdr, *expect_kdr, "%d", input_caps_start );
+ check_member( *kdr, *expect_kdr, "%d", input_caps_count );
+ check_member( *kdr, *expect_kdr, "%d", input_caps_end );
+ check_member( *kdr, *expect_kdr, "%d", input_report_byte_length );
+ check_member( *kdr, *expect_kdr, "%d", output_caps_start );
+ check_member( *kdr, *expect_kdr, "%d", output_caps_count );
+ 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 < min( expect_caps_count, kdr->caps_size / sizeof(struct hidp_kdr_caps) ); ++i)
+ {
+ winetest_push_context( "caps[%u]", i );
+ check_member( kdr->caps[i], expect_caps[i], "%04x", usage_page );
+ check_member( kdr->caps[i], expect_caps[i], "%d", report_id );
+ check_member( kdr->caps[i], expect_caps[i], "%d", start_bit );
+ 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 );
+ check_member( kdr->caps[i], expect_caps[i], "%d", total_bits );
+ check_member( kdr->caps[i], expect_caps[i], "%#lx", bit_field );
+ 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 );
+ check_member( kdr->caps[i], expect_caps[i], "%04x", link_usage );
+ check_member( kdr->caps[i], expect_caps[i], "%#lx", flags );
+ check_member( kdr->caps[i], expect_caps[i], "%#lx", padding[0] );
+ check_member( kdr->caps[i], expect_caps[i], "%#lx", padding[1] );
+ check_member( kdr->caps[i], expect_caps[i], "%#lx", padding[2] );
+ check_member( kdr->caps[i], expect_caps[i], "%#lx", padding[3] );
+ check_member( kdr->caps[i], expect_caps[i], "%#lx", padding[4] );
+ check_member( kdr->caps[i], expect_caps[i], "%#lx", padding[5] );
+ check_member( kdr->caps[i], expect_caps[i], "%#lx", padding[6] );
+ check_member( kdr->caps[i], expect_caps[i], "%#lx", padding[7] );
+ check_member( kdr->caps[i], expect_caps[i], "%04x", usage_min );
+ check_member( kdr->caps[i], expect_caps[i], "%04x", usage_max );
+ check_member( kdr->caps[i], expect_caps[i], "%d", string_min );
+ 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 );
+ check_member( kdr->caps[i], expect_caps[i], "%#x", data_index_min );
+ check_member( kdr->caps[i], expect_caps[i], "%#x", data_index_max );
+ check_member( kdr->caps[i], expect_caps[i], "%d", null_value );
+ check_member( kdr->caps[i], expect_caps[i], "%d", unknown );
+ check_member( kdr->caps[i], expect_caps[i], "%ld", logical_min );
+ check_member( kdr->caps[i], expect_caps[i], "%ld", logical_max );
+ check_member( kdr->caps[i], expect_caps[i], "%ld", physical_min );
+ check_member( kdr->caps[i], expect_caps[i], "%ld", physical_max );
+ check_member( kdr->caps[i], expect_caps[i], "%#lx", units );
+ check_member( kdr->caps[i], expect_caps[i], "%#lx", units_exp );
+ winetest_pop_context();
+ }
+
+ for (i = 0; i < expect_nodes_count; ++i)
+ {
+ struct hidp_kdr_node *nodes = (struct hidp_kdr_node *)((char *)kdr->caps + kdr->caps_size);
+ winetest_push_context( "nodes[%u]", i );
+ check_member( nodes[i], expect_nodes[i], "%04x", usage );
+ check_member( nodes[i], expect_nodes[i], "%04x", usage_page );
+ check_member( nodes[i], expect_nodes[i], "%d", parent );
+ check_member( nodes[i], expect_nodes[i], "%d", number_of_children );
+ check_member( nodes[i], expect_nodes[i], "%d", next_sibling );
+ check_member( nodes[i], expect_nodes[i], "%d", first_child );
+ check_member( nodes[i], expect_nodes[i], "%#lx", collection_type );
+ winetest_pop_context();
+ }
+ }
+
+ HidD_FreePreparsedData( preparsed_data );
+}
+
static void test_hidp_kdr(void)
{
#include "psh_hid_macros.h"
@@ -3240,12 +3340,9 @@ static void test_hidp_kdr(void)
},
};
- PHIDP_PREPARSED_DATA preparsed_data;
WCHAR device_path[MAX_PATH];
- struct hidp_kdr *kdr;
HANDLE file;
BOOL ret;
- DWORD i;
desc.report_descriptor_len = sizeof(report_desc);
memcpy( desc.report_descriptor_buf, report_desc, sizeof(report_desc) );
@@ -3262,95 +3359,8 @@ static void test_hidp_kdr(void)
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL );
ok( file != INVALID_HANDLE_VALUE, "got error %lu\n", GetLastError() );
- ret = HidD_GetPreparsedData( file, &preparsed_data );
- ok( ret, "HidD_GetPreparsedData failed with error %lu\n", GetLastError() );
-
- kdr = (struct hidp_kdr *)preparsed_data;
- ok( !strncmp( kdr->magic, expect_kdr.magic, 8 ), "got %s expected %s\n",
- debugstr_an(kdr->magic, 8), debugstr_an(expect_kdr.magic, 8) );
-
- if (!strncmp( kdr->magic, expect_kdr.magic, 8 ))
- {
- check_member( *kdr, expect_kdr, "%04x", usage );
- check_member( *kdr, expect_kdr, "%04x", usage_page );
- check_member( *kdr, expect_kdr, "%#x", unknown[0] );
- check_member( *kdr, expect_kdr, "%#x", unknown[1] );
- check_member( *kdr, expect_kdr, "%d", input_caps_start );
- check_member( *kdr, expect_kdr, "%d", input_caps_count );
- check_member( *kdr, expect_kdr, "%d", input_caps_end );
- check_member( *kdr, expect_kdr, "%d", input_report_byte_length );
- check_member( *kdr, expect_kdr, "%d", output_caps_start );
- check_member( *kdr, expect_kdr, "%d", output_caps_count );
- 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 < min( ARRAY_SIZE(expect_caps), kdr->caps_size / sizeof(struct hidp_kdr_caps) ); ++i)
- {
- winetest_push_context( "caps[%ld]", i );
- check_member( kdr->caps[i], expect_caps[i], "%04x", usage_page );
- check_member( kdr->caps[i], expect_caps[i], "%d", report_id );
- check_member( kdr->caps[i], expect_caps[i], "%d", start_bit );
- 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 );
- check_member( kdr->caps[i], expect_caps[i], "%d", total_bits );
- check_member( kdr->caps[i], expect_caps[i], "%#lx", bit_field );
- 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 );
- check_member( kdr->caps[i], expect_caps[i], "%04x", link_usage );
- check_member( kdr->caps[i], expect_caps[i], "%#lx", flags );
- check_member( kdr->caps[i], expect_caps[i], "%#lx", padding[0] );
- check_member( kdr->caps[i], expect_caps[i], "%#lx", padding[1] );
- check_member( kdr->caps[i], expect_caps[i], "%#lx", padding[2] );
- check_member( kdr->caps[i], expect_caps[i], "%#lx", padding[3] );
- check_member( kdr->caps[i], expect_caps[i], "%#lx", padding[4] );
- check_member( kdr->caps[i], expect_caps[i], "%#lx", padding[5] );
- check_member( kdr->caps[i], expect_caps[i], "%#lx", padding[6] );
- check_member( kdr->caps[i], expect_caps[i], "%#lx", padding[7] );
- check_member( kdr->caps[i], expect_caps[i], "%04x", usage_min );
- check_member( kdr->caps[i], expect_caps[i], "%04x", usage_max );
- check_member( kdr->caps[i], expect_caps[i], "%d", string_min );
- 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 );
- check_member( kdr->caps[i], expect_caps[i], "%#x", data_index_min );
- check_member( kdr->caps[i], expect_caps[i], "%#x", data_index_max );
- check_member( kdr->caps[i], expect_caps[i], "%d", null_value );
- check_member( kdr->caps[i], expect_caps[i], "%d", unknown );
- check_member( kdr->caps[i], expect_caps[i], "%ld", logical_min );
- check_member( kdr->caps[i], expect_caps[i], "%ld", logical_max );
- check_member( kdr->caps[i], expect_caps[i], "%ld", physical_min );
- check_member( kdr->caps[i], expect_caps[i], "%ld", physical_max );
- check_member( kdr->caps[i], expect_caps[i], "%#lx", units );
- check_member( kdr->caps[i], expect_caps[i], "%#lx", units_exp );
- winetest_pop_context();
- }
-
- for (i = 0; i < ARRAY_SIZE(expect_nodes); ++i)
- {
- struct hidp_kdr_node *nodes = (struct hidp_kdr_node *)((char *)kdr->caps + kdr->caps_size);
- winetest_push_context( "nodes[%ld]", i );
- check_member( nodes[i], expect_nodes[i], "%04x", usage );
- check_member( nodes[i], expect_nodes[i], "%04x", usage_page );
- check_member( nodes[i], expect_nodes[i], "%d", parent );
- check_member( nodes[i], expect_nodes[i], "%d", number_of_children );
- check_member( nodes[i], expect_nodes[i], "%d", next_sibling );
- check_member( nodes[i], expect_nodes[i], "%d", first_child );
- check_member( nodes[i], expect_nodes[i], "%#lx", collection_type );
- winetest_pop_context();
- }
- }
-
- HidD_FreePreparsedData( preparsed_data );
+ check_preparsed_data( file, &expect_kdr, ARRAY_SIZE(expect_caps), expect_caps,
+ ARRAY_SIZE(expect_nodes), expect_nodes );
CloseHandle( file );
@@ -3730,6 +3740,195 @@ done:
bus_device_stop();
}
+static void test_hid_multiple_tlc(void)
+{
+#include "psh_hid_macros.h"
+ const unsigned char report_desc[] =
+ {
+ USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
+ USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
+ COLLECTION(1, Application),
+ USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
+ COLLECTION(1, Physical),
+ REPORT_ID(1, 1),
+
+ USAGE_PAGE(1, HID_USAGE_PAGE_BUTTON),
+ USAGE_MINIMUM(1, 1),
+ USAGE_MAXIMUM(1, 2),
+ LOGICAL_MINIMUM(1, 0),
+ LOGICAL_MAXIMUM(1, 1),
+ REPORT_SIZE(1, 1),
+ REPORT_COUNT(1, 8),
+ INPUT(1, Data|Var|Abs),
+
+ USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
+ USAGE(1, HID_USAGE_GENERIC_X),
+ USAGE(1, HID_USAGE_GENERIC_Y),
+ REPORT_SIZE(1, 16),
+ REPORT_COUNT(1, 2),
+ LOGICAL_MINIMUM(2, -10),
+ LOGICAL_MAXIMUM(2, +10),
+ INPUT(1, Data|Var|Rel),
+ END_COLLECTION,
+ END_COLLECTION,
+
+ USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
+ USAGE(1, HID_USAGE_GENERIC_GAMEPAD),
+ COLLECTION(1, Application),
+ USAGE(1, HID_USAGE_GENERIC_GAMEPAD),
+ COLLECTION(1, Physical),
+ REPORT_ID(1, 2),
+
+ USAGE_PAGE(1, HID_USAGE_PAGE_BUTTON),
+ USAGE_MINIMUM(1, 1),
+ USAGE_MAXIMUM(1, 40),
+ LOGICAL_MINIMUM(1, 0),
+ LOGICAL_MAXIMUM(1, 1),
+ REPORT_SIZE(1, 1),
+ REPORT_COUNT(1, 40),
+ INPUT(1, Data|Var|Abs),
+ END_COLLECTION,
+ END_COLLECTION,
+ };
+ C_ASSERT(sizeof(report_desc) < MAX_HID_DESCRIPTOR_LEN);
+#include "pop_hid_macros.h"
+
+ struct hid_device_desc desc =
+ {
+ .caps = { .InputReportByteLength = 7 },
+ .attributes = default_attributes,
+ };
+
+ static const struct hidp_kdr expect_kdr_joystick =
+ {
+ .magic = "HidP KDR",
+ .usage = 0x04,
+ .usage_page = 0x01,
+ .input_caps_count = 3,
+ .input_caps_end = 3,
+ .input_report_byte_length = 6,
+ .output_caps_start = 3,
+ .output_caps_end = 3,
+ .feature_caps_start = 3,
+ .feature_caps_end = 3,
+ .caps_size = 312,
+ .number_link_collection_nodes = 2,
+ };
+ static const struct hidp_kdr expect_kdr_gamepad =
+ {
+ .magic = "HidP KDR",
+ .usage = 0x05,
+ .usage_page = 0x01,
+ .input_caps_count = 1,
+ .input_caps_end = 1,
+ .input_report_byte_length = 6,
+ .output_caps_start = 1,
+ .output_caps_end = 1,
+ .feature_caps_start = 1,
+ .feature_caps_end = 1,
+ .caps_size = 104,
+ .number_link_collection_nodes = 2,
+ };
+ static const struct hidp_kdr_caps expect_caps_joystick[] =
+ {
+ {
+ .usage_page = 9, .report_id = 1, .bit_size = 1, .report_count = 8, .start_byte = 1, .total_bits = 8,
+ .bit_field = 2, .end_byte = 2, .link_collection = 1, .link_usage_page = 0x01, .link_usage = 0x04, .flags = 0x1c,
+ .usage_min = 1, .usage_max = 2, .data_index_max = 1,
+ },
+ {
+ .usage_page = 1, .report_id = 1, .bit_size = 16, .report_count = 1, .start_byte = 4, .total_bits = 16,
+ .bit_field = 6, .end_byte = 6, .link_collection = 1, .link_usage_page = 0x01, .link_usage = 0x04,
+ .usage_min = 0x31, .usage_max = 0x31, .data_index_min = 2, .data_index_max = 2, .logical_min = -10, .logical_max = +10,
+ },
+ {
+ .usage_page = 1, .report_id = 1, .bit_size = 16, .report_count = 1, .start_byte = 2, .total_bits = 16,
+ .bit_field = 6, .end_byte = 4, .link_collection = 1, .link_usage_page = 0x01, .link_usage = 0x04,
+ .usage_min = 0x30, .usage_max = 0x30, .data_index_min = 3, .data_index_max = 3, .logical_min = -10, .logical_max = +10,
+ },
+ };
+ static const struct hidp_kdr_caps expect_caps_gamepad[] =
+ {
+ {
+ .usage_page = 9, .report_id = 2, .bit_size = 1, .report_count = 40, .start_byte = 1, .total_bits = 40,
+ .bit_field = 2, .end_byte = 6, .link_collection = 1, .link_usage_page = 0x01, .link_usage = 0x05, .flags = 0x1c,
+ .usage_min = 0x01, .usage_max = 0x28, .data_index_max = 0x27,
+ },
+ };
+ static const struct hidp_kdr_node expect_nodes_joystick[] =
+ {
+ {
+ .usage = 0x04,
+ .usage_page = 0x01,
+ .number_of_children = 1,
+ .first_child = 1,
+ .collection_type = 0x1,
+ },
+ {
+ .usage = 0x04,
+ .usage_page = 0x01,
+ },
+ };
+ static const struct hidp_kdr_node expect_nodes_gamepad[] =
+ {
+ {
+ .usage = 0x05,
+ .usage_page = 0x01,
+ .number_of_children = 1,
+ .first_child = 1,
+ .collection_type = 1,
+ },
+ {
+ .usage = 0x05,
+ .usage_page = 0x01,
+ },
+ };
+
+ WCHAR device_path[MAX_PATH];
+ HANDLE file;
+ BOOL ret;
+
+ desc.report_descriptor_len = sizeof(report_desc);
+ memcpy( desc.report_descriptor_buf, report_desc, sizeof(report_desc) );
+ fill_context( desc.context, ARRAY_SIZE(desc.context) );
+
+ if (!hid_device_start( &desc )) goto done;
+
+ swprintf( device_path, MAX_PATH, L"\\\\?\\hid#vid_%04x&pid_%04x&col01", desc.attributes.VendorID,
+ desc.attributes.ProductID );
+ ret = find_hid_device_path( device_path );
+ todo_wine
+ ok( ret, "Failed to find HID device matching %s\n", debugstr_w( device_path ) );
+ if (!ret) goto done;
+
+ file = CreateFileW( device_path, FILE_READ_ACCESS | FILE_WRITE_ACCESS,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL );
+ ok( file != INVALID_HANDLE_VALUE, "got error %lu\n", GetLastError() );
+ check_preparsed_data( file, &expect_kdr_joystick, ARRAY_SIZE(expect_caps_joystick), expect_caps_joystick,
+ ARRAY_SIZE(expect_nodes_joystick), expect_nodes_joystick );
+ CloseHandle( file );
+
+ swprintf( device_path, MAX_PATH, L"\\\\?\\hid#vid_%04x&pid_%04x&col02", desc.attributes.VendorID,
+ desc.attributes.ProductID );
+ ret = find_hid_device_path( device_path );
+ ok( ret, "Failed to find HID device matching %s\n", debugstr_w( device_path ) );
+
+ file = CreateFileW( device_path, FILE_READ_ACCESS | FILE_WRITE_ACCESS,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL );
+ ok( file != INVALID_HANDLE_VALUE, "got error %lu\n", GetLastError() );
+ check_preparsed_data( file, &expect_kdr_gamepad, ARRAY_SIZE(expect_caps_gamepad), expect_caps_gamepad,
+ ARRAY_SIZE(expect_nodes_gamepad), expect_nodes_gamepad );
+ CloseHandle( file );
+
+ swprintf( device_path, MAX_PATH, L"\\\\?\\hid#vid_%04x&pid_%04x&col03", desc.attributes.VendorID,
+ desc.attributes.ProductID );
+ ret = find_hid_device_path( device_path );
+ ok( !ret, "Failed to find HID device matching %s\n", debugstr_w( device_path ) );
+
+done:
+ hid_device_stop( &desc );
+}
+
START_TEST( hid )
{
if (!dinput_test_init()) return;
@@ -3742,6 +3941,7 @@ START_TEST( hid )
test_hid_driver( 1, FALSE );
test_hid_driver( 0, TRUE );
test_hid_driver( 1, TRUE );
+ test_hid_multiple_tlc();
done:
bus_device_stop();
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/171
More information about the wine-devel
mailing list