[PATCH v2 3/6] ntoskrnl.exe/tests: Add more reports with complex HID syntax.

Rémi Bernon rbernon at codeweavers.com
Mon Jun 14 02:15:52 CDT 2021


Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
 dlls/ntoskrnl.exe/tests/driver_hid.c | 124 +++++++++++++-
 dlls/ntoskrnl.exe/tests/ntoskrnl.c   | 246 ++++++++++++++++++++++++---
 2 files changed, 335 insertions(+), 35 deletions(-)

diff --git a/dlls/ntoskrnl.exe/tests/driver_hid.c b/dlls/ntoskrnl.exe/tests/driver_hid.c
index 3a9f4867de4..74e9029a476 100644
--- a/dlls/ntoskrnl.exe/tests/driver_hid.c
+++ b/dlls/ntoskrnl.exe/tests/driver_hid.c
@@ -90,7 +90,7 @@ static NTSTATUS WINAPI driver_internal_ioctl(DEVICE_OBJECT *device, IRP *irp)
 {
 #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)
+#define REPORT_ID_OR_USAGE_PAGE(size, id, off) SHORT_ITEM_1((id ? 8 : 0), 1, (id + off))
     const unsigned char report_descriptor[] =
     {
         USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
@@ -98,7 +98,7 @@ static NTSTATUS WINAPI driver_internal_ioctl(DEVICE_OBJECT *device, IRP *irp)
         COLLECTION(1, Application),
             USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
             COLLECTION(1, Logical),
-                REPORT_ID_OR_USAGE_PAGE(1, report_id),
+                REPORT_ID_OR_USAGE_PAGE(1, report_id, 0),
                 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
                 USAGE(1, HID_USAGE_GENERIC_X),
                 USAGE(1, HID_USAGE_GENERIC_Y),
@@ -113,22 +113,132 @@ static NTSTATUS WINAPI driver_internal_ioctl(DEVICE_OBJECT *device, IRP *irp)
                 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_MINIMUM(1, 0x18),
+                USAGE_MAXIMUM(1, 0x1f),
+                LOGICAL_MINIMUM(1, 0),
+                LOGICAL_MAXIMUM(1, 1),
+                REPORT_COUNT(1, 8),
+                REPORT_SIZE(1, 1),
+                INPUT(1, Cnst|Var|Abs),
+                REPORT_COUNT(1, 8),
+                REPORT_SIZE(1, 1),
+                INPUT(1, Cnst|Var|Abs),
+                /* needs to be 8 bit aligned as next has Buff */
+
+                USAGE_MINIMUM(4, (HID_USAGE_PAGE_KEYBOARD<<16)|0x8),
+                USAGE_MAXIMUM(4, (HID_USAGE_PAGE_KEYBOARD<<16)|0xf),
+                LOGICAL_MINIMUM(1, 0),
+                LOGICAL_MAXIMUM(1, 8),
+                REPORT_COUNT(1, 2),
+                REPORT_SIZE(1, 8),
+                INPUT(2, Data|Ary|Rel|Wrap|Lin|Pref|Null|Vol|Buff),
+
+                /* needs to be 8 bit aligned as previous has Buff */
+                USAGE(1, 0x20),
+                LOGICAL_MINIMUM(1, 0),
+                LOGICAL_MAXIMUM(1, 1),
+                REPORT_COUNT(1, 8),
+                REPORT_SIZE(1, 1),
+                INPUT(1, Data|Var|Abs),
+                USAGE_MINIMUM(1, 0x21),
+                USAGE_MAXIMUM(1, 0x22),
+                REPORT_COUNT(1, 2),
+                REPORT_SIZE(1, 0),
+                INPUT(1, Data|Var|Abs),
+                USAGE(1, 0x23),
+                REPORT_COUNT(1, 0),
+                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,
+
+            USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
+            USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
+            COLLECTION(1, Report),
+                REPORT_ID_OR_USAGE_PAGE(1, report_id, 1),
+                USAGE_PAGE(1, HID_USAGE_PAGE_BUTTON),
+                USAGE_MINIMUM(1, 9),
+                USAGE_MAXIMUM(1, 10),
+                LOGICAL_MINIMUM(1, 0),
+                LOGICAL_MAXIMUM(1, 1),
+                REPORT_COUNT(1, 8),
+                REPORT_SIZE(1, 1),
+                INPUT(1, Data|Var|Abs),
+            END_COLLECTION,
+
+            USAGE_PAGE(2, HID_USAGE_PAGE_HAPTICS),
+            USAGE(1, HID_USAGE_HAPTICS_SIMPLE_CONTROLLER),
+            COLLECTION(1, Logical),
+                REPORT_ID_OR_USAGE_PAGE(1, report_id, 0),
+                USAGE_PAGE(2, HID_USAGE_PAGE_HAPTICS),
+
+                USAGE(1, HID_USAGE_HAPTICS_WAVEFORM_LIST),
+                COLLECTION(1, NamedArray),
+                    USAGE_PAGE(1, HID_USAGE_PAGE_ORDINAL),
+                    USAGE(1, 3), /* HID_USAGE_HAPTICS_WAVEFORM_RUMBLE */
+                    USAGE(1, 4), /* HID_USAGE_HAPTICS_WAVEFORM_BUZZ */
+                    LOGICAL_MINIMUM(2, 0x0000),
+                    LOGICAL_MAXIMUM(2, 0xffff),
+                    REPORT_COUNT(1, 2),
+                    REPORT_SIZE(1, 16),
+                    FEATURE(1, Data|Var|Abs|Null),
+                END_COLLECTION,
+
+                USAGE_PAGE(2, HID_USAGE_PAGE_HAPTICS),
+                USAGE(1, HID_USAGE_HAPTICS_DURATION_LIST),
+                COLLECTION(1, NamedArray),
+                    USAGE_PAGE(1, HID_USAGE_PAGE_ORDINAL),
+                    USAGE(1, 3), /* 0 (HID_USAGE_HAPTICS_WAVEFORM_RUMBLE) */
+                    USAGE(1, 4), /* 0 (HID_USAGE_HAPTICS_WAVEFORM_BUZZ) */
+                    LOGICAL_MINIMUM(2, 0x0000),
+                    LOGICAL_MAXIMUM(2, 0xffff),
+                    REPORT_COUNT(1, 2),
+                    REPORT_SIZE(1, 16),
+                    FEATURE(1, Data|Var|Abs|Null),
+                END_COLLECTION,
+
+                USAGE_PAGE(2, HID_USAGE_PAGE_HAPTICS),
+                USAGE(1, HID_USAGE_HAPTICS_WAVEFORM_CUTOFF_TIME),
+                UNIT(2, 0x1001), /* seconds */
+                UNIT_EXPONENT(1, -3), /* 10^-3 */
+                LOGICAL_MINIMUM(2, 0x8000),
+                LOGICAL_MAXIMUM(2, 0x7fff),
+                PHYSICAL_MINIMUM(4, 0x00000000),
+                PHYSICAL_MAXIMUM(4, 0xffffffff),
+                REPORT_SIZE(1, 32),
+                REPORT_COUNT(1, 1),
+                FEATURE(1, Data|Var|Abs),
+                /* reset global items */
+                UNIT(1, 0), /* None */
+                UNIT_EXPONENT(1, 0),
+            END_COLLECTION,
+
+            USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
+            USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
+            COLLECTION(1, Report),
+                REPORT_ID_OR_USAGE_PAGE(1, report_id, 1),
+                USAGE_PAGE(1, HID_USAGE_PAGE_BUTTON),
+                USAGE_MINIMUM(1, 9),
+                USAGE_MAXIMUM(1, 10),
+                LOGICAL_MINIMUM(1, 0),
+                LOGICAL_MAXIMUM(1, 1),
+                PHYSICAL_MINIMUM(1, 0),
+                PHYSICAL_MAXIMUM(1, 1),
+                REPORT_COUNT(1, 8),
+                REPORT_SIZE(1, 1),
+                FEATURE(1, Data|Var|Abs),
+            END_COLLECTION,
         END_COLLECTION,
     };
 #undef REPORT_ID_OR_USAGE_PAGE
@@ -208,7 +318,7 @@ static NTSTATUS WINAPI driver_internal_ioctl(DEVICE_OBJECT *device, IRP *irp)
 
         case IOCTL_HID_READ_REPORT:
         {
-            ULONG expected_size = report_id ? 5 : 4;
+            ULONG expected_size = 10;
             ok(!in_size, "got input size %u\n", in_size);
             if (!test_failed)
             {
diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c
index 578c8057dd7..497c9a10adf 100644
--- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c
+++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c
@@ -1640,15 +1640,36 @@ static inline void check_hidp_value_caps_(int line, HIDP_VALUE_CAPS *caps, const
 
 static void test_hidp(HANDLE file, int report_id)
 {
-    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 = 2,
-        .NumberInputButtonCaps = 1,
-        .NumberInputValueCaps = 3,
-        .NumberInputDataIndices = 11,
+        /* without report id */
+        {
+            .Usage = HID_USAGE_GENERIC_JOYSTICK,
+            .UsagePage = HID_USAGE_PAGE_GENERIC,
+            .InputReportByteLength = 11,
+            .FeatureReportByteLength = 14,
+            .NumberLinkCollectionNodes = 7,
+            .NumberInputButtonCaps = 5,
+            .NumberInputValueCaps = 4,
+            .NumberInputDataIndices = 32,
+            .NumberFeatureButtonCaps = 1,
+            .NumberFeatureValueCaps = 5,
+            .NumberFeatureDataIndices = 7,
+        },
+        /* with report id */
+        {
+            .Usage = HID_USAGE_GENERIC_JOYSTICK,
+            .UsagePage = HID_USAGE_PAGE_GENERIC,
+            .InputReportByteLength = 10,
+            .FeatureReportByteLength = 13,
+            .NumberLinkCollectionNodes = 7,
+            .NumberInputButtonCaps = 5,
+            .NumberInputValueCaps = 4,
+            .NumberInputDataIndices = 32,
+            .NumberFeatureButtonCaps = 1,
+            .NumberFeatureValueCaps = 5,
+            .NumberFeatureDataIndices = 7,
+        },
     };
     const HIDP_BUTTON_CAPS expect_button_caps[] =
     {
@@ -1666,6 +1687,48 @@ static void test_hidp(HANDLE file, int report_id)
             .Range.DataIndexMin = 2,
             .Range.DataIndexMax = 9,
         },
+        {
+            .UsagePage = HID_USAGE_PAGE_BUTTON,
+            .ReportID = report_id,
+            .BitField = 3,
+            .LinkCollection = 1,
+            .LinkUsage = HID_USAGE_GENERIC_JOYSTICK,
+            .LinkUsagePage = HID_USAGE_PAGE_GENERIC,
+            .IsRange = TRUE,
+            .IsAbsolute = TRUE,
+            .Range.UsageMin = 0x18,
+            .Range.UsageMax = 0x1f,
+            .Range.DataIndexMin = 10,
+            .Range.DataIndexMax = 17,
+        },
+        {
+            .UsagePage = HID_USAGE_PAGE_KEYBOARD,
+            .ReportID = report_id,
+            .BitField = 0x1fc,
+            .LinkCollection = 1,
+            .LinkUsage = HID_USAGE_GENERIC_JOYSTICK,
+            .LinkUsagePage = HID_USAGE_PAGE_GENERIC,
+            .IsRange = TRUE,
+            .IsAbsolute = FALSE,
+            .Range.UsageMin = 0x8,
+            .Range.UsageMax = 0xf,
+            .Range.DataIndexMin = 18,
+            .Range.DataIndexMax = 25,
+        },
+        {
+            .UsagePage = HID_USAGE_PAGE_BUTTON,
+            .ReportID = report_id,
+            .BitField = 2,
+            .LinkCollection = 1,
+            .LinkUsage = HID_USAGE_GENERIC_JOYSTICK,
+            .LinkUsagePage = HID_USAGE_PAGE_GENERIC,
+            .IsRange = FALSE,
+            .IsAbsolute = TRUE,
+            .NotRange.Usage = 0x20,
+            .NotRange.Reserved1 = 0x20,
+            .NotRange.DataIndex = 26,
+            .NotRange.Reserved4 = 26,
+        },
     };
     const HIDP_VALUE_CAPS expect_value_caps[] =
     {
@@ -1682,6 +1745,7 @@ static void test_hidp(HANDLE file, int report_id)
             .LogicalMin = -128,
             .LogicalMax = 127,
             .NotRange.Usage = HID_USAGE_GENERIC_Y,
+            .NotRange.Reserved1 = HID_USAGE_GENERIC_Y,
         },
         {
             .UsagePage = HID_USAGE_PAGE_GENERIC,
@@ -1696,7 +1760,25 @@ static void test_hidp(HANDLE file, int report_id)
             .LogicalMin = -128,
             .LogicalMax = 127,
             .NotRange.Usage = HID_USAGE_GENERIC_X,
+            .NotRange.Reserved1 = HID_USAGE_GENERIC_X,
             .NotRange.DataIndex = 1,
+            .NotRange.Reserved4 = 1,
+        },
+        {
+            .UsagePage = HID_USAGE_PAGE_BUTTON,
+            .ReportID = report_id,
+            .BitField = 2,
+            .LinkUsage = HID_USAGE_GENERIC_JOYSTICK,
+            .LinkUsagePage = HID_USAGE_PAGE_GENERIC,
+            .LinkCollection = 1,
+            .IsAbsolute = TRUE,
+            .ReportCount = 1,
+            .LogicalMax = 1,
+            .IsRange = TRUE,
+            .Range.UsageMin = 0x21,
+            .Range.UsageMax = 0x22,
+            .Range.DataIndexMin = 27,
+            .Range.DataIndexMax = 28,
         },
         {
             .UsagePage = HID_USAGE_PAGE_GENERIC,
@@ -1710,9 +1792,10 @@ static void test_hidp(HANDLE file, int report_id)
             .ReportCount = 2,
             .LogicalMin = 1,
             .LogicalMax = 8,
-            .PhysicalMax = 8,
             .NotRange.Usage = HID_USAGE_GENERIC_HATSWITCH,
-            .NotRange.DataIndex = 10,
+            .NotRange.Reserved1 = HID_USAGE_GENERIC_HATSWITCH,
+            .NotRange.DataIndex = 29,
+            .NotRange.Reserved4 = 29,
         },
     };
     static const HIDP_LINK_COLLECTION_NODE expect_collections[] =
@@ -1721,8 +1804,8 @@ static void test_hidp(HANDLE file, int report_id)
             .LinkUsage = HID_USAGE_GENERIC_JOYSTICK,
             .LinkUsagePage = HID_USAGE_PAGE_GENERIC,
             .CollectionType = 1,
-            .NumberOfChildren = 1,
-            .FirstChild = 1,
+            .NumberOfChildren = 4,
+            .FirstChild = 6,
         },
         {
             .LinkUsage = HID_USAGE_GENERIC_JOYSTICK,
@@ -1751,7 +1834,25 @@ static void test_hidp(HANDLE file, int report_id)
     ok(status == HIDP_STATUS_INVALID_PREPARSED_DATA, "HidP_GetCaps returned %#x\n", status);
     status = HidP_GetCaps(preparsed_data, &caps);
     ok(status == HIDP_STATUS_SUCCESS, "HidP_GetCaps returned %#x\n", status);
-    check_hidp_caps(&caps, &expect_hidp_caps);
+    check_member(caps, expect_hidp_caps[report_id], "%04x", Usage);
+    check_member(caps, expect_hidp_caps[report_id], "%04x", UsagePage);
+    check_member(caps, expect_hidp_caps[report_id], "%d", InputReportByteLength);
+    check_member(caps, expect_hidp_caps[report_id], "%d", OutputReportByteLength);
+    check_member(caps, expect_hidp_caps[report_id], "%d", FeatureReportByteLength);
+    check_member(caps, expect_hidp_caps[report_id], "%d", NumberLinkCollectionNodes);
+    todo_wine
+    check_member(caps, expect_hidp_caps[report_id], "%d", NumberInputButtonCaps);
+    todo_wine
+    check_member(caps, expect_hidp_caps[report_id], "%d", NumberInputValueCaps);
+    todo_wine
+    check_member(caps, expect_hidp_caps[report_id], "%d", NumberInputDataIndices);
+    check_member(caps, expect_hidp_caps[report_id], "%d", NumberOutputButtonCaps);
+    check_member(caps, expect_hidp_caps[report_id], "%d", NumberOutputValueCaps);
+    check_member(caps, expect_hidp_caps[report_id], "%d", NumberOutputDataIndices);
+    check_member(caps, expect_hidp_caps[report_id], "%d", NumberFeatureButtonCaps);
+    check_member(caps, expect_hidp_caps[report_id], "%d", NumberFeatureValueCaps);
+    todo_wine
+    check_member(caps, expect_hidp_caps[report_id], "%d", NumberFeatureDataIndices);
 
     collection_count = 0;
     status = HidP_GetLinkCollectionNodes(collections, &collection_count, preparsed_data);
@@ -1770,7 +1871,16 @@ static void test_hidp(HANDLE file, int report_id)
     for (i = 0; i < ARRAY_SIZE(expect_collections); ++i)
     {
         winetest_push_context("collections[%d]", i);
-        check_hidp_link_collection_node(collections + i, expect_collections + i);
+        check_member(collections[i], expect_collections[i], "%04x", LinkUsage);
+        check_member(collections[i], expect_collections[i], "%04x", LinkUsagePage);
+        check_member(collections[i], expect_collections[i], "%d", Parent);
+        check_member(collections[i], expect_collections[i], "%d", NumberOfChildren);
+        todo_wine_if(i == 1)
+        check_member(collections[i], expect_collections[i], "%d", NextSibling);
+        todo_wine_if(i == 0)
+        check_member(collections[i], expect_collections[i], "%d", FirstChild);
+        check_member(collections[i], expect_collections[i], "%d", CollectionType);
+        check_member(collections[i], expect_collections[i], "%d", IsAlias);
         winetest_pop_context();
     }
 
@@ -1790,6 +1900,7 @@ static void test_hidp(HANDLE file, int report_id)
     count = ARRAY_SIZE(button_caps);
     status = HidP_GetButtonCaps(HidP_Input, button_caps, &count, (PHIDP_PREPARSED_DATA)buffer);
     ok(status == HIDP_STATUS_INVALID_PREPARSED_DATA, "HidP_GetButtonCaps returned %#x\n", status);
+    memset(button_caps, 0, sizeof(button_caps));
     status = HidP_GetButtonCaps(HidP_Input, button_caps, &count, preparsed_data);
     ok(status == HIDP_STATUS_SUCCESS, "HidP_GetButtonCaps returned %#x\n", status);
     ok(count == caps.NumberInputButtonCaps, "HidP_GetButtonCaps returned count %d, expected %d\n",
@@ -1798,25 +1909,36 @@ static void test_hidp(HANDLE file, int report_id)
     for (i = 0; i < ARRAY_SIZE(expect_button_caps); ++i)
     {
         winetest_push_context("button_caps[%d]", i);
+        todo_wine_if(i >= 2)
         check_member(button_caps[i], expect_button_caps[i], "%04x", UsagePage);
+        todo_wine_if(i >= 2 && report_id)
         check_member(button_caps[i], expect_button_caps[i], "%d", ReportID);
         check_member(button_caps[i], expect_button_caps[i], "%d", IsAlias);
         todo_wine
         check_member(button_caps[i], expect_button_caps[i], "%d", BitField);
+        todo_wine_if(i >= 2)
         check_member(button_caps[i], expect_button_caps[i], "%d", LinkCollection);
+        todo_wine_if(i >= 3)
         check_member(button_caps[i], expect_button_caps[i], "%04x", LinkUsage);
+        todo_wine_if(i >= 3)
         check_member(button_caps[i], expect_button_caps[i], "%04x", LinkUsagePage);
+        todo_wine_if(i == 1)
         check_member(button_caps[i], expect_button_caps[i], "%d", IsRange);
         check_member(button_caps[i], expect_button_caps[i], "%d", IsStringRange);
         check_member(button_caps[i], expect_button_caps[i], "%d", IsDesignatorRange);
+        todo_wine_if(i >= 2)
         check_member(button_caps[i], expect_button_caps[i], "%d", IsAbsolute);
+        todo_wine_if(i >= 1)
         check_member(button_caps[i], expect_button_caps[i], "%04x", Range.UsageMin);
+        todo_wine_if(i >= 1)
         check_member(button_caps[i], expect_button_caps[i], "%04x", Range.UsageMax);
         check_member(button_caps[i], expect_button_caps[i], "%d", Range.StringMin);
         check_member(button_caps[i], expect_button_caps[i], "%d", Range.StringMax);
         check_member(button_caps[i], expect_button_caps[i], "%d", Range.DesignatorMin);
         check_member(button_caps[i], expect_button_caps[i], "%d", Range.DesignatorMax);
+        todo_wine_if(i >= 1)
         check_member(button_caps[i], expect_button_caps[i], "%d", Range.DataIndexMin);
+        todo_wine_if(i >= 1)
         check_member(button_caps[i], expect_button_caps[i], "%d", Range.DataIndexMax);
         winetest_pop_context();
     }
@@ -1890,6 +2012,7 @@ static void test_hidp(HANDLE file, int report_id)
     for (i = 0; i < ARRAY_SIZE(expect_value_caps); ++i)
     {
         winetest_push_context("value_caps[%d]", i);
+        todo_wine_if(i == 3)
         check_member(value_caps[i], expect_value_caps[i], "%04x", UsagePage);
         check_member(value_caps[i], expect_value_caps[i], "%d", ReportID);
         check_member(value_caps[i], expect_value_caps[i], "%d", IsAlias);
@@ -1898,28 +2021,42 @@ static void test_hidp(HANDLE file, int report_id)
         check_member(value_caps[i], expect_value_caps[i], "%d", LinkCollection);
         check_member(value_caps[i], expect_value_caps[i], "%04x", LinkUsage);
         check_member(value_caps[i], expect_value_caps[i], "%04x", LinkUsagePage);
+        todo_wine_if(i == 3)
         check_member(value_caps[i], expect_value_caps[i], "%d", IsRange);
         check_member(value_caps[i], expect_value_caps[i], "%d", IsStringRange);
         check_member(value_caps[i], expect_value_caps[i], "%d", IsDesignatorRange);
+        todo_wine_if(i == 2)
         check_member(value_caps[i], expect_value_caps[i], "%d", IsAbsolute);
+        todo_wine_if(i == 2)
         check_member(value_caps[i], expect_value_caps[i], "%d", HasNull);
+        todo_wine_if(i >= 2)
         check_member(value_caps[i], expect_value_caps[i], "%d", BitSize);
+        todo_wine_if(i == 2)
         check_member(value_caps[i], expect_value_caps[i], "%d", ReportCount);
         check_member(value_caps[i], expect_value_caps[i], "%d", UnitsExp);
         check_member(value_caps[i], expect_value_caps[i], "%d", Units);
+        todo_wine_if(i >= 3)
         check_member(value_caps[i], expect_value_caps[i], "%d", LogicalMin);
+        todo_wine_if(i >= 2)
         check_member(value_caps[i], expect_value_caps[i], "%d", LogicalMax);
         check_member(value_caps[i], expect_value_caps[i], "%d", PhysicalMin);
         check_member(value_caps[i], expect_value_caps[i], "%d", PhysicalMax);
-        todo_wine_if(i != 2)
-        check_member(value_caps[i], expect_value_caps[i], "%04x", NotRange.Usage);
-        check_member(value_caps[i], expect_value_caps[i], "%d", NotRange.StringIndex);
-        check_member(value_caps[i], expect_value_caps[i], "%d", NotRange.DesignatorIndex);
-        check_member(value_caps[i], expect_value_caps[i], "%d", NotRange.DataIndex);
+        todo_wine
+        check_member(value_caps[i], expect_value_caps[i], "%04x", Range.UsageMin);
+        todo_wine
+        check_member(value_caps[i], expect_value_caps[i], "%04x", Range.UsageMax);
+        check_member(value_caps[i], expect_value_caps[i], "%d", Range.StringMin);
+        check_member(value_caps[i], expect_value_caps[i], "%d", Range.StringMax);
+        check_member(value_caps[i], expect_value_caps[i], "%d", Range.DesignatorMin);
+        check_member(value_caps[i], expect_value_caps[i], "%d", Range.DesignatorMax);
+        todo_wine_if(i >= 2)
+        check_member(value_caps[i], expect_value_caps[i], "%d", Range.DataIndexMin);
+        todo_wine_if(i >= 2)
+        check_member(value_caps[i], expect_value_caps[i], "%d", Range.DataIndexMax);
         winetest_pop_context();
     }
 
-    count = ARRAY_SIZE(value_caps) - 3;
+    count = ARRAY_SIZE(value_caps) - 4;
     status = HidP_GetSpecificValueCaps(HidP_Output, 0, 0, 0, value_caps, &count, preparsed_data);
     todo_wine
     ok(status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_GetSpecificValueCaps returned %#x\n", status);
@@ -1932,24 +2069,61 @@ static void test_hidp(HANDLE file, int report_id)
     todo_wine
     ok(count == caps.NumberInputValueCaps, "HidP_GetSpecificValueCaps returned count %d, expected %d\n",
        count, caps.NumberInputValueCaps);
-    count = ARRAY_SIZE(value_caps) - 3;
-    status = HidP_GetSpecificValueCaps(HidP_Input, 0, 0, 0, value_caps + 3, &count, (PHIDP_PREPARSED_DATA)buffer);
+    count = ARRAY_SIZE(value_caps) - 4;
+    status = HidP_GetSpecificValueCaps(HidP_Input, 0, 0, 0, value_caps + 4, &count, (PHIDP_PREPARSED_DATA)buffer);
     ok(status == HIDP_STATUS_INVALID_PREPARSED_DATA, "HidP_GetSpecificValueCaps returned %#x\n", status);
 
-    status = HidP_GetSpecificValueCaps(HidP_Input, 0, 0, 0, value_caps + 3, &count, preparsed_data);
+    status = HidP_GetSpecificValueCaps(HidP_Input, 0, 0, 0, value_caps + 4, &count, preparsed_data);
     ok(status == HIDP_STATUS_SUCCESS, "HidP_GetSpecificValueCaps returned %#x\n", status);
     ok(count == caps.NumberInputValueCaps, "HidP_GetSpecificValueCaps returned count %d, expected %d\n",
        count, caps.NumberInputValueCaps);
-    check_hidp_value_caps(&value_caps[3], &value_caps[0]);
-    check_hidp_value_caps(&value_caps[4], &value_caps[1]);
-    check_hidp_value_caps(&value_caps[5], &value_caps[2]);
+    check_hidp_value_caps(&value_caps[4], &value_caps[0]);
+    check_hidp_value_caps(&value_caps[5], &value_caps[1]);
+    check_hidp_value_caps(&value_caps[6], &value_caps[2]);
+    check_hidp_value_caps(&value_caps[7], &value_caps[3]);
 
     count = 1;
     status = HidP_GetSpecificValueCaps(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_HATSWITCH,
-                                       value_caps + 3, &count, preparsed_data);
+                                       value_caps + 4, &count, preparsed_data);
     ok(status == HIDP_STATUS_SUCCESS, "HidP_GetSpecificValueCaps returned %#x\n", status);
     ok(count == 1, "HidP_GetSpecificValueCaps returned count %d, expected %d\n", count, 1);
-    check_hidp_value_caps(&value_caps[3], &value_caps[2]);
+
+    todo_wine
+    check_member(value_caps[4], value_caps[3], "%04x", UsagePage);
+    check_member(value_caps[4], value_caps[3], "%d", ReportID);
+    check_member(value_caps[4], value_caps[3], "%d", IsAlias);
+    check_member(value_caps[4], value_caps[3], "%d", BitField);
+    check_member(value_caps[4], value_caps[3], "%d", LinkCollection);
+    check_member(value_caps[4], value_caps[3], "%04x", LinkUsage);
+    check_member(value_caps[4], value_caps[3], "%04x", LinkUsagePage);
+    todo_wine
+    check_member(value_caps[4], value_caps[3], "%d", IsRange);
+    check_member(value_caps[4], value_caps[3], "%d", IsStringRange);
+    check_member(value_caps[4], value_caps[3], "%d", IsDesignatorRange);
+    check_member(value_caps[4], value_caps[3], "%d", IsAbsolute);
+    check_member(value_caps[4], value_caps[3], "%d", HasNull);
+    todo_wine
+    check_member(value_caps[4], value_caps[3], "%d", BitSize);
+    check_member(value_caps[4], value_caps[3], "%d", ReportCount);
+    check_member(value_caps[4], value_caps[3], "%d", UnitsExp);
+    check_member(value_caps[4], value_caps[3], "%d", Units);
+    todo_wine
+    check_member(value_caps[4], value_caps[3], "%d", LogicalMin);
+    todo_wine
+    check_member(value_caps[4], value_caps[3], "%d", LogicalMax);
+    check_member(value_caps[4], value_caps[3], "%d", PhysicalMin);
+    check_member(value_caps[4], value_caps[3], "%d", PhysicalMax);
+    todo_wine
+    check_member(value_caps[4], value_caps[3], "%04x", Range.UsageMin);
+    check_member(value_caps[4], value_caps[3], "%04x", Range.UsageMax);
+    check_member(value_caps[4], value_caps[3], "%d", Range.StringMin);
+    check_member(value_caps[4], value_caps[3], "%d", Range.StringMax);
+    check_member(value_caps[4], value_caps[3], "%d", Range.DesignatorMin);
+    check_member(value_caps[4], value_caps[3], "%d", Range.DesignatorMax);
+    todo_wine
+    check_member(value_caps[4], value_caps[3], "%d", Range.DataIndexMin);
+    todo_wine
+    check_member(value_caps[4], value_caps[3], "%d", Range.DataIndexMax);
 
     count = 0xdead;
     status = HidP_GetSpecificValueCaps(HidP_Input, 0xfffe, 0, 0, value_caps, &count, preparsed_data);
@@ -1990,6 +2164,22 @@ static void test_hidp(HANDLE file, int report_id)
     todo_wine_if(report_id)
     ok(!memcmp(buffer, report, sizeof(buffer)), "unexpected report data\n");
 
+    memset(report, 0xcd, sizeof(report));
+    status = HidP_InitializeReportForID(HidP_Feature, 3, preparsed_data, report, caps.FeatureReportByteLength);
+    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_Feature, report_id, preparsed_data, report, caps.FeatureReportByteLength);
+    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.FeatureReportByteLength);
+    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);
 }
-- 
2.31.0




More information about the wine-devel mailing list