1 /* 2 * PROJECT: ReactOS kernel-mode tests 3 * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory 4 * PURPOSE: HidParser description test 5 * PROGRAMMER: Thomas Faber <thomas.faber@reactos.org> 6 */ 7 8 #include <kmt_test.h> 9 #include <hidpddi.h> 10 11 #define NDEBUG 12 #include <debug.h> 13 14 #include "HidP.h" 15 16 static UCHAR ExampleKeyboardDescriptor[] = { 17 0x05, 0x01, /* Usage Page (Generic Desktop), */ 18 0x09, 0x06, /* Usage (Keyboard), */ 19 0xA1, 0x01, /* Collection (Application), */ 20 0x05, 0x07, /* Usage Page (Key Codes); */ 21 0x19, 0xE0, /* Usage Minimum (224), */ 22 0x29, 0xE7, /* Usage Maximum (231), */ 23 0x15, 0x00, /* Logical Minimum (0), */ 24 0x25, 0x01, /* Logical Maximum (1), */ 25 0x75, 0x01, /* Report Size (1), */ 26 0x95, 0x08, /* Report Count (8), */ 27 0x81, 0x02, /* Input (Data, Variable, Absolute), ;Modifier byte */ 28 0x95, 0x01, /* Report Count (1), */ 29 0x75, 0x08, /* Report Size (8), */ 30 0x81, 0x01, /* Input (Constant), ;Reserved byte */ 31 0x95, 0x05, /* Report Count (5), */ 32 0x75, 0x01, /* Report Size (1), */ 33 0x05, 0x08, /* Usage Page (Page# for LEDs), */ 34 0x19, 0x01, /* Usage Minimum (1), */ 35 0x29, 0x05, /* Usage Maximum (5), */ 36 0x91, 0x02, /* Output (Data, Variable, Absolute), ;LED report */ 37 0x95, 0x01, /* Report Count (1), */ 38 0x75, 0x03, /* Report Size (3), */ 39 0x91, 0x01, /* Output (Constant), ;LED report padding */ 40 0x95, 0x06, /* Report Count (6), */ 41 0x75, 0x08, /* Report Size (8), */ 42 0x15, 0x00, /* Logical Minimum (0), */ 43 0x25, 0x65, /* Logical Maximum (101), */ 44 0x05, 0x07, /* Usage Page (Key Codes), */ 45 0x19, 0x00, /* Usage Minimum (0), */ 46 0x29, 0x65, /* Usage Maximum (101) */ 47 0x81, 0x00, /* Input (Data, Array), ;Key arrays (6 bytes) */ 48 0xC0 /* End Collection */ 49 }; 50 51 static UCHAR PowerProEliteDescriptor[] = { 52 0x05, 0x01, /* Usage Page (Generic Desktop), */ 53 0x09, 0x04, /* Usage (Joystick), */ 54 0xa1, 0x01, /* Collection (Application), */ 55 0xa1, 0x02, /* Collection (Logical), */ 56 0x85, 0x01, /* Report ID (1) */ 57 0x75, 0x08, /* Report Size (8), */ 58 0x95, 0x01, /* Report Count (1), */ 59 0x15, 0x00, /* Logical Minimum (0), */ 60 0x26, 0xff, 0x00, /* Logical Maximum (255), */ 61 0x81, 0x03, /* Input (Constant, Variable, Absolute), */ 62 0x75, 0x01, /* Report Size (1), */ 63 0x95, 0x13, /* Report Count (19), */ 64 0x15, 0x00, /* Logical Minimum (0), */ 65 0x25, 0x01, /* Logical Maximum (1), */ 66 0x35, 0x00, /* Physical Minimum (0), */ 67 0x45, 0x01, /* Physical Maximum (1), */ 68 0x05, 0x09, /* Usage Page (Button), */ 69 0x19, 0x01, /* Usage Minimum (1), */ 70 0x29, 0x13, /* Usage Maximum (19), */ 71 0x81, 0x02, /* Input (Data, Variable, Absolute), */ 72 0x75, 0x01, /* Report Size (1), */ 73 0x95, 0x0d, /* Report Count (13), */ 74 0x06, 0x00, 0xff, /* Usage Page (Vendor-defined FF00), */ 75 0x81, 0x03, /* Input (Constant, Variable, Absolute), */ 76 0x15, 0x00, /* Logical Minimum (0), */ 77 0x26, 0xff, 0x00, /* Logical Maximum (255), */ 78 0x05, 0x01, /* Usage Page (Generic Desktop), */ 79 0x09, 0x01, /* Usage (Pointer), */ 80 0xa1, 0x00, /* Collection (Physical), */ 81 0x75, 0x08, /* Report Size (8), */ 82 0x95, 0x04, /* Report Count (4), */ 83 0x35, 0x00, /* Physical Minimum (0), */ 84 0x46, 0xff, 0x00, /* Physical Maximum (255), */ 85 0x09, 0x30, /* Usage (X), */ 86 0x09, 0x31, /* Usage (Y), */ 87 0x09, 0x32, /* Usage (Z), */ 88 0x09, 0x35, /* Usage (Rz), */ 89 0x81, 0x02, /* Input (Data, Variable, Absolute), */ 90 0xc0, /* End Collection */ 91 0x05, 0x01, /* Usage Page (Generic Desktop), */ 92 0x75, 0x08, /* Report Size (8), */ 93 0x95, 0x27, /* Report Count (39), */ 94 0x09, 0x01, /* Usage (Pointer), */ 95 0x81, 0x02, /* Input (Data, Variable, Absolute), */ 96 0x75, 0x08, /* Report Size (8), */ 97 0x95, 0x30, /* Report Count (48), */ 98 0x09, 0x01, /* Usage (Pointer), */ 99 0x91, 0x02, /* Output (Data, Variable, Absolute), */ 100 0x75, 0x08, /* Report Size (8), */ 101 0x95, 0x30, /* Report Count (48), */ 102 0x09, 0x01, /* Usage (Pointer), */ 103 0xb1, 0x02, /* Feature (Data, Variable, Absolute), */ 104 0xc0, /* End Collection */ 105 106 0xa1, 0x02, /* Collection (Logical), */ 107 0x85, 0x02, /* Report ID (2) */ 108 0x75, 0x08, /* Report Size (8), */ 109 0x95, 0x30, /* Report Count (48), */ 110 0x09, 0x01, /* Usage (Pointer), */ 111 0xb1, 0x02, /* Feature (Data, Variable, Absolute), */ 112 0xc0, /* End Collection */ 113 0xa1, 0x02, /* Collection (Logical), */ 114 0x85, 0xee, /* Report ID (238) */ 115 0x75, 0x08, /* Report Size (8), */ 116 0x95, 0x30, /* Report Count (48), */ 117 0x09, 0x01, /* Usage (Pointer), */ 118 0xb1, 0x02, /* Feature (Data, Variable, Absolute), */ 119 0xc0, /* End Collection */ 120 0xa1, 0x02, /* Collection (Logical), */ 121 0x85, 0xef, /* Report ID (239) */ 122 0x75, 0x08, /* Report Size (8), */ 123 0x95, 0x30, /* Report Count (48), */ 124 0x09, 0x01, /* Usage (Pointer), */ 125 0xb1, 0x02, /* Feature (Data, Variable, Absolute), */ 126 0xc0, /* End Collection */ 127 0xc0, /* End Collection */ 128 }; 129 C_ASSERT(sizeof(PowerProEliteDescriptor) == 148); 130 131 static 132 VOID 133 TestGetCollectionDescription(VOID) 134 { 135 NTSTATUS Status; 136 HIDP_DEVICE_DESC DeviceDescription; 137 138 /* Empty report descriptor */ 139 RtlFillMemory(&DeviceDescription, sizeof(DeviceDescription), 0x55); 140 Status = HidP_GetCollectionDescription(NULL, 141 0, 142 NonPagedPool, 143 &DeviceDescription); 144 ok_eq_hex(Status, STATUS_NO_DATA_DETECTED); 145 ok_eq_pointer(DeviceDescription.CollectionDesc, NULL); 146 ok_eq_ulong(DeviceDescription.CollectionDescLength, 0); 147 ok_eq_pointer(DeviceDescription.ReportIDs, NULL); 148 ok_eq_ulong(DeviceDescription.ReportIDsLength, 0); 149 if (NT_SUCCESS(Status)) HidP_FreeCollectionDescription(&DeviceDescription); 150 151 /* Sample keyboard report descriptor from the HID spec */ 152 Status = HidP_GetCollectionDescription(ExampleKeyboardDescriptor, 153 sizeof(ExampleKeyboardDescriptor), 154 NonPagedPool, 155 &DeviceDescription); 156 ok_eq_hex(Status, STATUS_SUCCESS); 157 ok_eq_ulong(DeviceDescription.CollectionDescLength, 1); 158 ok_eq_ulong(DeviceDescription.ReportIDsLength, 1); 159 if (!skip(NT_SUCCESS(Status), "Parsing failure\n")) 160 { 161 if (!skip(DeviceDescription.CollectionDescLength >= 1, "No collection\n")) 162 { 163 ok_eq_uint(DeviceDescription.CollectionDesc[0].UsagePage, HID_USAGE_PAGE_GENERIC); 164 ok_eq_uint(DeviceDescription.CollectionDesc[0].Usage, HID_USAGE_GENERIC_KEYBOARD); 165 ok_eq_uint(DeviceDescription.CollectionDesc[0].CollectionNumber, 1); 166 ok_eq_uint(DeviceDescription.CollectionDesc[0].InputLength, 9); 167 ok_eq_uint(DeviceDescription.CollectionDesc[0].OutputLength, 2); 168 ok_eq_uint(DeviceDescription.CollectionDesc[0].FeatureLength, 0); 169 ok_eq_uint(DeviceDescription.CollectionDesc[0].PreparsedDataLength, 476); 170 } 171 if (!skip(DeviceDescription.ReportIDsLength >= 1, "No report IDs\n")) 172 { 173 ok_eq_uint(DeviceDescription.ReportIDs[0].ReportID, 0); 174 ok_eq_uint(DeviceDescription.ReportIDs[0].CollectionNumber, 1); 175 ok_eq_uint(DeviceDescription.ReportIDs[0].InputLength, 8); 176 ok_eq_uint(DeviceDescription.ReportIDs[0].OutputLength, 1); 177 ok_eq_uint(DeviceDescription.ReportIDs[0].FeatureLength, 0); 178 } 179 HidP_FreeCollectionDescription(&DeviceDescription); 180 } 181 182 /* Regression test for CORE-11538 */ 183 Status = HidP_GetCollectionDescription(PowerProEliteDescriptor, 184 sizeof(PowerProEliteDescriptor), 185 NonPagedPool, 186 &DeviceDescription); 187 ok_eq_hex(Status, STATUS_SUCCESS); 188 ok_eq_ulong(DeviceDescription.CollectionDescLength, 1); 189 ok_eq_ulong(DeviceDescription.ReportIDsLength, 4); 190 if (!skip(NT_SUCCESS(Status), "Parsing failure\n")) 191 { 192 if (!skip(DeviceDescription.CollectionDescLength >= 1, "No collection\n")) 193 { 194 ok_eq_uint(DeviceDescription.CollectionDesc[0].UsagePage, HID_USAGE_PAGE_GENERIC); 195 ok_eq_uint(DeviceDescription.CollectionDesc[0].Usage, HID_USAGE_GENERIC_JOYSTICK); 196 ok_eq_uint(DeviceDescription.CollectionDesc[0].CollectionNumber, 1); 197 ok_eq_uint(DeviceDescription.CollectionDesc[0].InputLength, 49); 198 ok_eq_uint(DeviceDescription.CollectionDesc[0].OutputLength, 49); 199 ok_eq_uint(DeviceDescription.CollectionDesc[0].FeatureLength, 49); 200 ok_eq_uint(DeviceDescription.CollectionDesc[0].PreparsedDataLength, 1388); 201 } 202 if (!skip(DeviceDescription.ReportIDsLength >= 1, "No first report ID\n")) 203 { 204 ok_eq_uint(DeviceDescription.ReportIDs[0].ReportID, 1); 205 ok_eq_uint(DeviceDescription.ReportIDs[0].CollectionNumber, 1); 206 ok_eq_uint(DeviceDescription.ReportIDs[0].InputLength, 49); 207 ok_eq_uint(DeviceDescription.ReportIDs[0].OutputLength, 49); 208 ok_eq_uint(DeviceDescription.ReportIDs[0].FeatureLength, 49); 209 } 210 if (!skip(DeviceDescription.ReportIDsLength >= 2, "No second report ID\n")) 211 { 212 ok_eq_uint(DeviceDescription.ReportIDs[1].ReportID, 2); 213 ok_eq_uint(DeviceDescription.ReportIDs[1].CollectionNumber, 1); 214 ok_eq_uint(DeviceDescription.ReportIDs[1].InputLength, 0); 215 ok_eq_uint(DeviceDescription.ReportIDs[1].OutputLength, 0); 216 ok_eq_uint(DeviceDescription.ReportIDs[1].FeatureLength, 49); 217 } 218 if (!skip(DeviceDescription.ReportIDsLength >= 3, "No third report ID\n")) 219 { 220 ok_eq_uint(DeviceDescription.ReportIDs[2].ReportID, 238); 221 ok_eq_uint(DeviceDescription.ReportIDs[2].CollectionNumber, 1); 222 ok_eq_uint(DeviceDescription.ReportIDs[2].InputLength, 0); 223 ok_eq_uint(DeviceDescription.ReportIDs[2].OutputLength, 0); 224 ok_eq_uint(DeviceDescription.ReportIDs[2].FeatureLength, 49); 225 } 226 if (!skip(DeviceDescription.ReportIDsLength >= 4, "No fourth report ID\n")) 227 { 228 ok_eq_uint(DeviceDescription.ReportIDs[3].ReportID, 239); 229 ok_eq_uint(DeviceDescription.ReportIDs[3].CollectionNumber, 1); 230 ok_eq_uint(DeviceDescription.ReportIDs[3].InputLength, 0); 231 ok_eq_uint(DeviceDescription.ReportIDs[3].OutputLength, 0); 232 ok_eq_uint(DeviceDescription.ReportIDs[3].FeatureLength, 49); 233 } 234 HidP_FreeCollectionDescription(&DeviceDescription); 235 } 236 } 237 238 NTSTATUS 239 TestHidPDescription( 240 IN PDEVICE_OBJECT DeviceObject, 241 IN ULONG ControlCode, 242 IN PVOID Buffer OPTIONAL, 243 IN SIZE_T InLength, 244 IN OUT PSIZE_T OutLength) 245 { 246 UNREFERENCED_PARAMETER(DeviceObject); 247 UNREFERENCED_PARAMETER(Buffer); 248 UNREFERENCED_PARAMETER(InLength); 249 UNREFERENCED_PARAMETER(OutLength); 250 251 PAGED_CODE(); 252 253 NT_VERIFY(ControlCode == IOCTL_TEST_DESCRIPTION); 254 255 TestGetCollectionDescription(); 256 257 return STATUS_SUCCESS; 258 } 259