Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/ntoskrnl.exe/tests/driver_hid.c | 97 ++++++++++++++++------------ dlls/ntoskrnl.exe/tests/ntoskrnl.c | 54 ++++++++++++---- 2 files changed, 97 insertions(+), 54 deletions(-)
diff --git a/dlls/ntoskrnl.exe/tests/driver_hid.c b/dlls/ntoskrnl.exe/tests/driver_hid.c index 1fe644250f7..7260adeb172 100644 --- a/dlls/ntoskrnl.exe/tests/driver_hid.c +++ b/dlls/ntoskrnl.exe/tests/driver_hid.c @@ -40,6 +40,7 @@ static UNICODE_STRING control_symlink;
static unsigned int got_start_device; +static unsigned int report_id;
static NTSTATUS WINAPI driver_pnp(DEVICE_OBJECT *device, IRP *irp) { @@ -85,49 +86,54 @@ static NTSTATUS WINAPI driver_power(DEVICE_OBJECT *device, IRP *irp) return PoCallDriver(ext->NextDeviceObject, irp); }
-#include "psh_hid_macros.h" - -static const unsigned char report_descriptor[] = +static NTSTATUS WINAPI driver_internal_ioctl(DEVICE_OBJECT *device, IRP *irp) { - USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC), - USAGE(1, HID_USAGE_GENERIC_JOYSTICK), - COLLECTION(1, Application), - USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC), - USAGE(1, HID_USAGE_GENERIC_X), - USAGE(1, HID_USAGE_GENERIC_Y), - LOGICAL_MINIMUM(1, -128), - LOGICAL_MAXIMUM(1, 127), - REPORT_SIZE(1, 8), - REPORT_COUNT(1, 2), - INPUT(1, Data|Var|Abs), - - USAGE_PAGE(1, HID_USAGE_PAGE_BUTTON), - USAGE_MINIMUM(1, 1), - USAGE_MAXIMUM(1, 8), - LOGICAL_MINIMUM(1, 0), - LOGICAL_MAXIMUM(1, 1), - PHYSICAL_MINIMUM(1, 0), - PHYSICAL_MAXIMUM(1, 1), - REPORT_COUNT(1, 8), - REPORT_SIZE(1, 1), - INPUT(1, Data|Var|Abs), - +#include "psh_hid_macros.h" +/* Replace REPORT_ID with USAGE_PAGE when id is 0 */ +#define REPORT_ID_OR_USAGE_PAGE(size, id) SHORT_ITEM_1((id ? 8 : 0), 1, id) + const unsigned char report_descriptor[] = + { USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC), - USAGE(1, HID_USAGE_GENERIC_HATSWITCH), - LOGICAL_MINIMUM(1, 1), - LOGICAL_MAXIMUM(1, 8), - PHYSICAL_MINIMUM(1, 0), - PHYSICAL_MAXIMUM(1, 8), - REPORT_SIZE(1, 4), - REPORT_COUNT(1, 2), - INPUT(1, Data|Var|Abs), - END_COLLECTION, -}; - + USAGE(1, HID_USAGE_GENERIC_JOYSTICK), + COLLECTION(1, Application), + USAGE(1, HID_USAGE_GENERIC_JOYSTICK), + COLLECTION(1, Logical), + REPORT_ID_OR_USAGE_PAGE(1, report_id), + USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC), + USAGE(1, HID_USAGE_GENERIC_X), + USAGE(1, HID_USAGE_GENERIC_Y), + LOGICAL_MINIMUM(1, -128), + LOGICAL_MAXIMUM(1, 127), + REPORT_SIZE(1, 8), + REPORT_COUNT(1, 2), + INPUT(1, Data|Var|Abs), + + USAGE_PAGE(1, HID_USAGE_PAGE_BUTTON), + USAGE_MINIMUM(1, 1), + USAGE_MAXIMUM(1, 8), + LOGICAL_MINIMUM(1, 0), + LOGICAL_MAXIMUM(1, 1), + PHYSICAL_MINIMUM(1, 0), + PHYSICAL_MAXIMUM(1, 1), + REPORT_COUNT(1, 8), + REPORT_SIZE(1, 1), + INPUT(1, Data|Var|Abs), + + USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC), + USAGE(1, HID_USAGE_GENERIC_HATSWITCH), + LOGICAL_MINIMUM(1, 1), + LOGICAL_MAXIMUM(1, 8), + PHYSICAL_MINIMUM(1, 0), + PHYSICAL_MAXIMUM(1, 8), + REPORT_SIZE(1, 4), + REPORT_COUNT(1, 2), + INPUT(1, Data|Var|Abs), + END_COLLECTION, + END_COLLECTION, + }; +#undef REPORT_ID_OR_USAGE_PAGE #include "pop_hid_macros.h"
-static NTSTATUS WINAPI driver_internal_ioctl(DEVICE_OBJECT *device, IRP *irp) -{ static BOOL test_failed; IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp); const ULONG in_size = stack->Parameters.DeviceIoControl.InputBufferLength; @@ -202,9 +208,13 @@ static NTSTATUS WINAPI driver_internal_ioctl(DEVICE_OBJECT *device, IRP *irp)
case IOCTL_HID_READ_REPORT: { - ULONG expected_size = 4; + ULONG expected_size = report_id ? 5 : 4; ok(!in_size, "got input size %u\n", in_size); - if (!test_failed) todo_wine ok(out_size == expected_size, "got output size %u\n", out_size); + if (!test_failed) + { + todo_wine_if(!report_id) + ok(out_size == expected_size, "got output size %u\n", out_size); + } if (out_size != expected_size) test_failed = TRUE;
ret = STATUS_NOT_IMPLEMENTED; @@ -284,11 +294,16 @@ NTSTATUS WINAPI DriverEntry(DRIVER_OBJECT *driver, UNICODE_STRING *registry) .DriverObject = driver, .RegistryPath = registry, }; + WCHAR buffer[MAX_PATH]; NTSTATUS ret;
if ((ret = winetest_init())) return ret;
+ memset(buffer, 0, sizeof(buffer)); + lstrcpynW(buffer, registry->Buffer, min(MAX_PATH, registry->Length / sizeof(WCHAR) + 1)); + if (wcsstr(buffer, L"winetest_hid_report_id")) report_id = 1; + driver->DriverExtension->AddDevice = driver_add_device; driver->DriverUnload = driver_unload; driver->MajorFunction[IRP_MJ_PNP] = driver_pnp; diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index 90d68149c1f..6afc07ef62e 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -1639,25 +1639,27 @@ static inline void check_hidp_value_caps_(int line, HIDP_VALUE_CAPS *caps, const } }
-static void test_hidp(HANDLE file) +static void test_hidp(HANDLE file, int report_id) { - static const HIDP_CAPS expect_hidp_caps = + const HIDP_CAPS expect_hidp_caps = { .Usage = HID_USAGE_GENERIC_JOYSTICK, .UsagePage = HID_USAGE_PAGE_GENERIC, .InputReportByteLength = 5, - .NumberLinkCollectionNodes = 1, + .NumberLinkCollectionNodes = 2, .NumberInputButtonCaps = 1, .NumberInputValueCaps = 3, .NumberInputDataIndices = 11, }; - static const HIDP_BUTTON_CAPS expect_button_caps[] = + const HIDP_BUTTON_CAPS expect_button_caps[] = { { .UsagePage = HID_USAGE_PAGE_BUTTON, + .ReportID = report_id, .BitField = 2, .LinkUsage = HID_USAGE_GENERIC_JOYSTICK, .LinkUsagePage = HID_USAGE_PAGE_GENERIC, + .LinkCollection = 1, .IsRange = TRUE, .IsAbsolute = TRUE, .Range.UsageMin = 1, @@ -1666,13 +1668,15 @@ static void test_hidp(HANDLE file) .Range.DataIndexMax = 9, }, }; - static const HIDP_VALUE_CAPS expect_value_caps[] = + const HIDP_VALUE_CAPS expect_value_caps[] = { { .UsagePage = HID_USAGE_PAGE_GENERIC, + .ReportID = report_id, .BitField = 2, .LinkUsage = HID_USAGE_GENERIC_JOYSTICK, .LinkUsagePage = HID_USAGE_PAGE_GENERIC, + .LinkCollection = 1, .IsAbsolute = TRUE, .BitSize = 8, .ReportCount = 1, @@ -1682,9 +1686,11 @@ static void test_hidp(HANDLE file) }, { .UsagePage = HID_USAGE_PAGE_GENERIC, + .ReportID = report_id, .BitField = 2, .LinkUsage = HID_USAGE_GENERIC_JOYSTICK, .LinkUsagePage = HID_USAGE_PAGE_GENERIC, + .LinkCollection = 1, .IsAbsolute = TRUE, .BitSize = 8, .ReportCount = 1, @@ -1695,9 +1701,11 @@ static void test_hidp(HANDLE file) }, { .UsagePage = HID_USAGE_PAGE_GENERIC, + .ReportID = report_id, .BitField = 2, .LinkUsage = HID_USAGE_GENERIC_JOYSTICK, .LinkUsagePage = HID_USAGE_PAGE_GENERIC, + .LinkCollection = 1, .IsAbsolute = TRUE, .BitSize = 4, .ReportCount = 2, @@ -1714,6 +1722,13 @@ static void test_hidp(HANDLE file) .LinkUsage = HID_USAGE_GENERIC_JOYSTICK, .LinkUsagePage = HID_USAGE_PAGE_GENERIC, .CollectionType = 1, + .NumberOfChildren = 1, + .FirstChild = 1, + }, + { + .LinkUsage = HID_USAGE_GENERIC_JOYSTICK, + .LinkUsagePage = HID_USAGE_PAGE_GENERIC, + .CollectionType = 2, }, };
@@ -1961,34 +1976,45 @@ static void test_hidp(HANDLE file) ok(status == HIDP_STATUS_INVALID_REPORT_LENGTH, "HidP_InitializeReportForID returned %#x\n", status); status = HidP_InitializeReportForID(HidP_Input, 0, preparsed_data, report, caps.InputReportByteLength + 1); ok(status == HIDP_STATUS_INVALID_REPORT_LENGTH, "HidP_InitializeReportForID returned %#x\n", status); + status = HidP_InitializeReportForID(HidP_Input, 1 - report_id, preparsed_data, report, caps.InputReportByteLength); + todo_wine_if(!report_id) + ok(status == HIDP_STATUS_REPORT_DOES_NOT_EXIST, "HidP_InitializeReportForID returned %#x\n", status);
memset(report, 0xcd, sizeof(report)); - status = HidP_InitializeReportForID(HidP_Input, 0, preparsed_data, report, caps.InputReportByteLength); + status = HidP_InitializeReportForID(HidP_Input, report_id, preparsed_data, report, caps.InputReportByteLength); + todo_wine_if(report_id) ok(status == HIDP_STATUS_SUCCESS, "HidP_InitializeReportForID returned %#x\n", status);
memset(buffer, 0xcd, sizeof(buffer)); memset(buffer, 0, caps.InputReportByteLength); + buffer[0] = report_id; + todo_wine_if(report_id) ok(!memcmp(buffer, report, sizeof(buffer)), "unexpected report data\n");
HidD_FreePreparsedData(preparsed_data); CloseHandle(file); }
-static void test_hid_device(void) +static void test_hid_device(char const *service_name) { char buffer[200]; SP_DEVICE_INTERFACE_DETAIL_DATA_A *iface_detail = (void *)buffer; SP_DEVICE_INTERFACE_DATA iface = {sizeof(iface)}; SP_DEVINFO_DATA device = {sizeof(device)}; + unsigned int i, report_id; BOOL ret, found = FALSE; OBJECT_ATTRIBUTES attr; UNICODE_STRING string; IO_STATUS_BLOCK io; NTSTATUS status; - unsigned int i; HDEVINFO set; HANDLE file;
+ if (!strcmp(service_name, "winetest_hid_report_ids")) report_id = 1; + else report_id = 0; + + winetest_push_context("report %d", report_id); + set = SetupDiGetClassDevsA(&GUID_DEVINTERFACE_HID, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); ok(set != INVALID_HANDLE_VALUE, "failed to get device list, error %#x\n", GetLastError());
@@ -2019,7 +2045,7 @@ static void test_hid_device(void) FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); ok(file != INVALID_HANDLE_VALUE, "got error %u\n", GetLastError());
- test_hidp(file); + test_hidp(file, report_id);
CloseHandle(file);
@@ -2027,12 +2053,13 @@ static void test_hid_device(void) InitializeObjectAttributes(&attr, &string, OBJ_CASE_INSENSITIVE, NULL, NULL); status = NtOpenFile(&file, SYNCHRONIZE, &attr, &io, 0, FILE_SYNCHRONOUS_IO_NONALERT); todo_wine ok(status == STATUS_UNSUCCESSFUL, "got %#x\n", status); + + winetest_pop_context(); }
-static void test_hid_driver(struct testsign_context *ctx) +static void test_hid_driver(struct testsign_context *ctx, char const *service_name) { static const char hardware_id[] = "test_hardware_id\0"; - static const char service_name[] = "winetest_hid"; char path[MAX_PATH], dest[MAX_PATH], *filepart; SP_DEVINFO_DATA device = {sizeof(device)}; char cwd[MAX_PATH], tempdir[MAX_PATH]; @@ -2094,7 +2121,7 @@ static void test_hid_driver(struct testsign_context *ctx)
/* Tests. */
- test_hid_device(); + test_hid_device(service_name);
/* Clean up. */
@@ -2225,7 +2252,8 @@ START_TEST(ntoskrnl) test_pnp_driver(&ctx);
subtest("driver_hid"); - test_hid_driver(&ctx); + test_hid_driver(&ctx, "winetest_hid"); + test_hid_driver(&ctx, "winetest_hid_report_ids");
out: testsign_cleanup(&ctx);