Atlas - hid_report_reconstructor_test.c

Home / ext / SDL / src / hidapi / windows / test Lines: 105 | Size: 23480 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)]
[FILE BEGIN]
1#if defined(__MINGW32__) 2 // Needed for %zu 3 #define __USE_MINGW_ANSI_STDIO 1 4#endif 5 6#include "../hidapi_descriptor_reconstruct.h" 7 8#include <stddef.h> 9#include <stdio.h> 10#include <string.h> 11 12static hidp_preparsed_data * alloc_preparsed_data_from_file(char* filename) 13{ 14 FILE* file; 15 errno_t err = fopen_s(&file, filename, "r"); 16 17 if (err != 0) { 18 fprintf(stderr, "ERROR: Couldn't open file '%s' for reading: %s\n", filename, strerror(err)); 19 return NULL; 20 } 21 22 char line[256]; 23 24 { 25 unsigned short vendor_id = 0; 26 unsigned short product_id = 0; 27 unsigned short usage = 0; 28 unsigned short usage_page = 0; 29 unsigned short release_number = 0; 30 int interface_number = -1; 31 BOOLEAN header_read_success = FALSE; 32 char manufacturer_string[128]; 33 manufacturer_string[0] = '\0'; 34 char product_string[128]; 35 product_string[0] = '\0'; 36 // char path[128]; 37 // path[0] = '\0'; 38 39 while (fgets(line, sizeof(line), file) != NULL) { 40 if (line[0] == '\r' || line[0] == '\n') { 41 line[0] = '\0'; 42 } 43 if (line[0] == '\0') { 44 // read the 'metadata' only until the first empty line 45 header_read_success = TRUE; 46 break; 47 } 48 if (sscanf(line, "dev->vendor_id = 0x%04hX\n", &vendor_id)) continue; 49 if (sscanf(line, "dev->product_id = 0x%04hX\n", &product_id)) continue; 50 if (sscanf(line, "dev->usage_page = 0x%04hX\n", &usage_page)) continue; 51 if (sscanf(line, "dev->usage = 0x%04hX\n", &usage)) continue; 52 if (sscanf(line, "dev->manufacturer_string = \"%127[^\"\n]", manufacturer_string)) continue; 53 if (sscanf(line, "dev->product_string = \"%127[^\"\n]", product_string)) continue; 54 if (sscanf(line, "dev->release_number = 0x%04hX\n", &release_number)) continue; 55 if (sscanf(line, "dev->interface_number = %d\n", &interface_number)) continue; 56 // if (sscanf(line, "dev->path = \"%127[^\"]\n", path)) continue; 57 } 58 if (!header_read_success) { 59 fprintf(stderr, "ERROR: Couldn't read PP Data header (missing newline)\n"); 60 fclose(file); 61 return NULL; 62 } 63 printf("'Virtual' Device Read: %04hx %04hx\n", vendor_id, product_id); 64 if (manufacturer_string[0] != '\0') { 65 printf(" Manufacturer: %s\n", manufacturer_string); 66 } 67 if (product_string[0] != '\0') { 68 printf(" Product: %s\n", product_string); 69 } 70 printf(" Release: %hx\n", release_number); 71 printf(" Interface: %d\n", interface_number); 72 printf(" Usage (page): 0x%hx (0x%hx)\n", usage, usage_page); 73 } 74 75 hidp_preparsed_data static_pp_data; 76 memset(&static_pp_data, 0, sizeof(static_pp_data)); 77 hidp_preparsed_data *pp_data = &static_pp_data; 78 79 unsigned int rt_idx; 80 unsigned int caps_idx; 81 unsigned int token_idx; 82 unsigned int coll_idx; 83 USAGE temp_usage; 84 BOOLEAN temp_boolean[3]; 85 UCHAR temp_uchar[3]; 86 USHORT temp_ushort; 87 ULONG temp_ulong; 88 LONG temp_long; 89 90 USHORT FirstByteOfLinkCollectionArray = 0; 91 USHORT NumberLinkCollectionNodes = 0; 92 93 while (fgets(line, sizeof(line), file) != NULL) { 94 if (line[0] == '#') 95 continue; 96 97 if (FirstByteOfLinkCollectionArray != 0 && NumberLinkCollectionNodes != 0) { 98 size_t size_of_preparsed_data = offsetof(hidp_preparsed_data, caps) + FirstByteOfLinkCollectionArray + (NumberLinkCollectionNodes * sizeof(hid_pp_link_collection_node)); 99 pp_data->FirstByteOfLinkCollectionArray = FirstByteOfLinkCollectionArray; 100 pp_data->NumberLinkCollectionNodes = NumberLinkCollectionNodes; 101 FirstByteOfLinkCollectionArray = 0; 102 NumberLinkCollectionNodes = 0; 103 pp_data = malloc(size_of_preparsed_data); 104 memcpy(pp_data, &static_pp_data, sizeof(static_pp_data)); 105 } 106 107 if (sscanf(line, "pp_data->MagicKey = 0x%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX\n", &pp_data->MagicKey[0], &pp_data->MagicKey[1], &pp_data->MagicKey[2], &pp_data->MagicKey[3], &pp_data->MagicKey[4], &pp_data->MagicKey[5], &pp_data->MagicKey[6], &pp_data->MagicKey[7])) continue; 108 if (sscanf(line, "pp_data->Usage = 0x%04hX\n", &pp_data->Usage)) continue; 109 if (sscanf(line, "pp_data->UsagePage = 0x%04hX\n", &pp_data->UsagePage)) continue; 110 if (sscanf(line, "pp_data->Reserved = 0x%04hX%04hX\n", &pp_data->Reserved[0], &pp_data->Reserved[1])) continue; 111 112 if (sscanf(line, "pp_data->caps_info[%u]", &rt_idx) == 1) { 113 const size_t caps_info_count = sizeof(pp_data->caps_info) / sizeof(pp_data->caps_info[0]); 114 if (rt_idx >= caps_info_count) { 115 fprintf(stderr, "Broken pp_data file, pp_data->caps_info[<idx>] can have at most %zu elements, accessing %ud, (%s)", caps_info_count, rt_idx, line); 116 continue; 117 } 118 if (sscanf(line, "pp_data->caps_info[%u]->FirstCap = %hu\n", &rt_idx, &temp_ushort) == 2) { 119 pp_data->caps_info[rt_idx].FirstCap = temp_ushort; 120 continue; 121 } 122 if (sscanf(line, "pp_data->caps_info[%u]->LastCap = %hu\n", &rt_idx, &temp_ushort) == 2) { 123 pp_data->caps_info[rt_idx].LastCap = temp_ushort; 124 continue; 125 } 126 if (sscanf(line, "pp_data->caps_info[%u]->NumberOfCaps = %hu\n", &rt_idx, &temp_ushort) == 2) { 127 pp_data->caps_info[rt_idx].NumberOfCaps = temp_ushort; 128 continue; 129 } 130 if (sscanf(line, "pp_data->caps_info[%u]->ReportByteLength = %hu\n", &rt_idx, &temp_ushort) == 2) { 131 pp_data->caps_info[rt_idx].ReportByteLength = temp_ushort; 132 continue; 133 } 134 fprintf(stderr, "Ignoring unimplemented caps_info field: %s", line); 135 continue; 136 } 137 138 if (sscanf(line, "pp_data->FirstByteOfLinkCollectionArray = 0x%04hX\n", &FirstByteOfLinkCollectionArray)) { 139 continue; 140 } 141 if (sscanf(line, "pp_data->NumberLinkCollectionNodes = %hu\n", &NumberLinkCollectionNodes)) { 142 continue; 143 } 144 145 if (sscanf(line, "pp_data->cap[%u]", &caps_idx) == 1) { 146 if (pp_data->FirstByteOfLinkCollectionArray == 0) { 147 fprintf(stderr, "Error reading pp_data file (%s): FirstByteOfLinkCollectionArray is 0 or not reported yet\n", line); 148 continue; 149 } 150 if ((caps_idx + 1) * sizeof(hid_pp_cap) > pp_data->FirstByteOfLinkCollectionArray) { 151 fprintf(stderr, "Error reading pp_data file (%s): the caps index (%u) is out of pp_data bytes boundary (%hu vs %hu)\n", line, caps_idx, (unsigned short) ((caps_idx + 1) * sizeof(hid_pp_cap)), pp_data->FirstByteOfLinkCollectionArray); 152 continue; 153 } 154 if (sscanf(line, "pp_data->cap[%u]->UsagePage = 0x%04hX\n", &caps_idx, &temp_usage) == 2) { 155 pp_data->caps[caps_idx].UsagePage = temp_usage; 156 continue; 157 } 158 if (sscanf(line, "pp_data->cap[%u]->ReportID = 0x%02hhX\n", &caps_idx, &temp_uchar[0]) == 2) { 159 pp_data->caps[caps_idx].ReportID = temp_uchar[0]; 160 continue; 161 } 162 if (sscanf(line, "pp_data->cap[%u]->BitPosition = %hhu\n", &caps_idx, &temp_uchar[0]) == 2) { 163 pp_data->caps[caps_idx].BitPosition = temp_uchar[0]; 164 continue; 165 } 166 if (sscanf(line, "pp_data->cap[%u]->BitSize = %hu\n", &caps_idx, &temp_ushort) == 2) { 167 pp_data->caps[caps_idx].ReportSize = temp_ushort; 168 continue; 169 } 170 if (sscanf(line, "pp_data->cap[%u]->ReportCount = %hu\n", &caps_idx, &temp_ushort) == 2) { 171 pp_data->caps[caps_idx].ReportCount = temp_ushort; 172 continue; 173 } 174 if (sscanf(line, "pp_data->cap[%u]->BytePosition = 0x%04hX\n", &caps_idx, &temp_ushort) == 2) { 175 pp_data->caps[caps_idx].BytePosition = temp_ushort; 176 continue; 177 } 178 if (sscanf(line, "pp_data->cap[%u]->BitCount = %hu\n", &caps_idx, &temp_ushort) == 2) { 179 pp_data->caps[caps_idx].BitCount = temp_ushort; 180 continue; 181 } 182 if (sscanf(line, "pp_data->cap[%u]->BitField = 0x%02lX\n", &caps_idx, &temp_ulong) == 2) { 183 pp_data->caps[caps_idx].BitField = temp_ulong; 184 continue; 185 } 186 if (sscanf(line, "pp_data->cap[%u]->NextBytePosition = 0x%04hX\n", &caps_idx, &temp_ushort) == 2) { 187 pp_data->caps[caps_idx].NextBytePosition = temp_ushort; 188 continue; 189 } 190 if (sscanf(line, "pp_data->cap[%u]->LinkCollection = 0x%04hX\n", &caps_idx, &temp_ushort) == 2) { 191 pp_data->caps[caps_idx].LinkCollection = temp_ushort; 192 continue; 193 } 194 if (sscanf(line, "pp_data->cap[%u]->LinkUsagePage = 0x%04hX\n", &caps_idx, &temp_usage) == 2) { 195 pp_data->caps[caps_idx].LinkUsagePage = temp_usage; 196 continue; 197 } 198 if (sscanf(line, "pp_data->cap[%u]->LinkUsage = 0x%04hX\n", &caps_idx, &temp_usage) == 2) { 199 pp_data->caps[caps_idx].LinkUsage = temp_usage; 200 continue; 201 } 202 203 // 8 Flags in one byte 204 if (sscanf(line, "pp_data->cap[%u]->IsMultipleItemsForArray = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) { 205 pp_data->caps[caps_idx].IsMultipleItemsForArray = temp_boolean[0]; 206 continue; 207 } 208 if (sscanf(line, "pp_data->cap[%u]->IsButtonCap = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) { 209 pp_data->caps[caps_idx].IsButtonCap = temp_boolean[0]; 210 continue; 211 } 212 if (sscanf(line, "pp_data->cap[%u]->IsPadding = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) { 213 pp_data->caps[caps_idx].IsPadding = temp_boolean[0]; 214 continue; 215 } 216 if (sscanf(line, "pp_data->cap[%u]->IsAbsolute = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) { 217 pp_data->caps[caps_idx].IsAbsolute = temp_boolean[0]; 218 continue; 219 } 220 if (sscanf(line, "pp_data->cap[%u]->IsRange = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) { 221 pp_data->caps[caps_idx].IsRange = temp_boolean[0]; 222 continue; 223 } 224 if (sscanf(line, "pp_data->cap[%u]->IsAlias = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) { 225 pp_data->caps[caps_idx].IsAlias = temp_boolean[0]; 226 continue; 227 } 228 if (sscanf(line, "pp_data->cap[%u]->IsStringRange = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) { 229 pp_data->caps[caps_idx].IsStringRange = temp_boolean[0]; 230 continue; 231 } 232 if (sscanf(line, "pp_data->cap[%u]->IsDesignatorRange = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) { 233 pp_data->caps[caps_idx].IsDesignatorRange = temp_boolean[0]; 234 continue; 235 } 236 237 if (sscanf(line, "pp_data->cap[%u]->Reserved1 = 0x%hhu%hhu%hhu\n", &caps_idx, &temp_uchar[0], &temp_uchar[1], &temp_uchar[2]) == 4) { 238 pp_data->caps[caps_idx].Reserved1[0] = temp_uchar[0]; 239 pp_data->caps[caps_idx].Reserved1[1] = temp_uchar[1]; 240 pp_data->caps[caps_idx].Reserved1[2] = temp_uchar[2]; 241 continue; 242 } 243 244 if (sscanf(line, "pp_data->cap[%u]->pp_cap->UnknownTokens[%u]", &caps_idx, &token_idx) == 2) { 245 const size_t unknown_tokens_count = sizeof(pp_data->caps[0].UnknownTokens) / sizeof(pp_data->caps[0].UnknownTokens[0]); 246 if (token_idx >= unknown_tokens_count) { 247 fprintf(stderr, "Broken pp_data file, pp_data->caps[<idx>].UnknownTokens[<idx>] can have at most %zu elements, accessing %ud, (%s)", unknown_tokens_count, token_idx, line); 248 continue; 249 } 250 if (sscanf(line, "pp_data->cap[%u]->pp_cap->UnknownTokens[%u].Token = 0x%02hhX\n", &caps_idx, &token_idx, &temp_uchar[0]) == 3) { 251 pp_data->caps[caps_idx].UnknownTokens[token_idx].Token = temp_uchar[0]; 252 continue; 253 } 254 if (sscanf(line, "pp_data->cap[%u]->pp_cap->UnknownTokens[%u].Reserved = 0x%02hhX%02hhX%02hhX\n", &caps_idx, &token_idx, &temp_uchar[0], &temp_uchar[1], &temp_uchar[2]) == 5) { 255 pp_data->caps[caps_idx].UnknownTokens[token_idx].Reserved[0] = temp_uchar[0]; 256 pp_data->caps[caps_idx].UnknownTokens[token_idx].Reserved[1] = temp_uchar[1]; 257 pp_data->caps[caps_idx].UnknownTokens[token_idx].Reserved[2] = temp_uchar[2]; 258 continue; 259 } 260 if (sscanf(line, "pp_data->cap[%u]->pp_cap->UnknownTokens[%u].BitField = 0x%08lX\n", &caps_idx, &token_idx, &temp_ulong) == 3) { 261 pp_data->caps[caps_idx].UnknownTokens[token_idx].BitField = temp_ulong; 262 continue; 263 } 264 fprintf(stderr, "Ignoring unimplemented pp_data->cap[]->pp_cap->UnknownTokens field: %s", line); 265 continue; 266 } 267 268 // Range 269 if (sscanf(line, "pp_data->cap[%u]->Range.UsageMin = 0x%04hX\n", &caps_idx, &temp_usage) == 2) { 270 pp_data->caps[caps_idx].Range.UsageMin = temp_usage; 271 continue; 272 } 273 if (sscanf(line, "pp_data->cap[%u]->Range.UsageMax = 0x%04hX\n", &caps_idx, &temp_usage) == 2) { 274 pp_data->caps[caps_idx].Range.UsageMax = temp_usage; 275 continue; 276 } 277 if (sscanf(line, "pp_data->cap[%u]->Range.StringMin = %hu\n", &caps_idx, &temp_ushort) == 2) { 278 pp_data->caps[caps_idx].Range.StringMin = temp_ushort; 279 continue; 280 } 281 if (sscanf(line, "pp_data->cap[%u]->Range.StringMax = %hu\n", &caps_idx, &temp_ushort) == 2) { 282 pp_data->caps[caps_idx].Range.StringMax = temp_ushort; 283 continue; 284 } 285 if (sscanf(line, "pp_data->cap[%u]->Range.DesignatorMin = %hu\n", &caps_idx, &temp_ushort) == 2) { 286 pp_data->caps[caps_idx].Range.DesignatorMin = temp_ushort; 287 continue; 288 } 289 if (sscanf(line, "pp_data->cap[%u]->Range.DesignatorMax = %hu\n", &caps_idx, &temp_ushort) == 2) { 290 pp_data->caps[caps_idx].Range.DesignatorMax = temp_ushort; 291 continue; 292 } 293 if (sscanf(line, "pp_data->cap[%u]->Range.DataIndexMin = %hu\n", &caps_idx, &temp_ushort) == 2) { 294 pp_data->caps[caps_idx].Range.DataIndexMin = temp_ushort; 295 continue; 296 } 297 if (sscanf(line, "pp_data->cap[%u]->Range.DataIndexMax = %hu\n", &caps_idx, &temp_ushort) == 2) { 298 pp_data->caps[caps_idx].Range.DataIndexMax = temp_ushort; 299 continue; 300 } 301 302 // NotRange 303 if (sscanf(line, "pp_data->cap[%u]->NotRange.Usage = 0x%04hX\n", &caps_idx, &temp_usage) == 2) { 304 pp_data->caps[caps_idx].NotRange.Usage = temp_usage; 305 continue; 306 } 307 if (sscanf(line, "pp_data->cap[%u]->NotRange.Reserved1 = 0x%04hX\n", &caps_idx, &temp_usage) == 2) { 308 pp_data->caps[caps_idx].NotRange.Reserved1 = temp_usage; 309 continue; 310 } 311 if (sscanf(line, "pp_data->cap[%u]->NotRange.StringIndex = %hu\n", &caps_idx, &temp_ushort) == 2) { 312 pp_data->caps[caps_idx].NotRange.StringIndex = temp_ushort; 313 continue; 314 } 315 if (sscanf(line, "pp_data->cap[%u]->NotRange.Reserved2 = %hu\n", &caps_idx, &temp_ushort) == 2) { 316 pp_data->caps[caps_idx].NotRange.Reserved2 = temp_ushort; 317 continue; 318 } 319 if (sscanf(line, "pp_data->cap[%u]->NotRange.DesignatorIndex = %hu\n", &caps_idx, &temp_ushort) == 2) { 320 pp_data->caps[caps_idx].NotRange.DesignatorIndex = temp_ushort; 321 continue; 322 } 323 if (sscanf(line, "pp_data->cap[%u]->NotRange.Reserved3 = %hu\n", &caps_idx, &temp_ushort) == 2) { 324 pp_data->caps[caps_idx].NotRange.Reserved3 = temp_ushort; 325 continue; 326 } 327 if (sscanf(line, "pp_data->cap[%u]->NotRange.DataIndex = %hu\n", &caps_idx, &temp_ushort) == 2) { 328 pp_data->caps[caps_idx].NotRange.DataIndex = temp_ushort; 329 continue; 330 } 331 if (sscanf(line, "pp_data->cap[%u]->NotRange.Reserved4 = %hu\n", &caps_idx, &temp_ushort) == 2) { 332 pp_data->caps[caps_idx].NotRange.Reserved4 = temp_ushort; 333 continue; 334 } 335 336 // Button 337 if (sscanf(line, "pp_data->cap[%u]->Button.LogicalMin = %ld\n", &caps_idx, &temp_long) == 2) { 338 pp_data->caps[caps_idx].Button.LogicalMin = temp_long; 339 continue; 340 } 341 if (sscanf(line, "pp_data->cap[%u]->Button.LogicalMax = %ld\n", &caps_idx, &temp_long) == 2) { 342 pp_data->caps[caps_idx].Button.LogicalMax = temp_long; 343 continue; 344 } 345 346 // NotButton 347 if (sscanf(line, "pp_data->cap[%u]->NotButton.HasNull = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) { 348 pp_data->caps[caps_idx].NotButton.HasNull = temp_boolean[0]; 349 continue; 350 } 351 if (sscanf(line, "pp_data->cap[%u]->NotButton.Reserved4 = 0x%02hhX%02hhX%02hhX\n", &caps_idx, &temp_uchar[0], &temp_uchar[1], &temp_uchar[2]) == 4) { 352 pp_data->caps[caps_idx].NotButton.Reserved4[0] = temp_uchar[0]; 353 pp_data->caps[caps_idx].NotButton.Reserved4[1] = temp_uchar[1]; 354 pp_data->caps[caps_idx].NotButton.Reserved4[2] = temp_uchar[2]; 355 continue; 356 } 357 if (sscanf(line, "pp_data->cap[%u]->NotButton.LogicalMin = %ld\n", &caps_idx, &temp_long) == 2) { 358 pp_data->caps[caps_idx].NotButton.LogicalMin = temp_long; 359 continue; 360 } 361 if (sscanf(line, "pp_data->cap[%u]->NotButton.LogicalMax = %ld\n", &caps_idx, &temp_long) == 2) { 362 pp_data->caps[caps_idx].NotButton.LogicalMax = temp_long; 363 continue; 364 } 365 if (sscanf(line, "pp_data->cap[%u]->NotButton.PhysicalMin = %ld\n", &caps_idx, &temp_long) == 2) { 366 pp_data->caps[caps_idx].NotButton.PhysicalMin = temp_long; 367 continue; 368 } 369 if (sscanf(line, "pp_data->cap[%u]->NotButton.PhysicalMax = %ld\n", &caps_idx, &temp_long) == 2) { 370 pp_data->caps[caps_idx].NotButton.PhysicalMax = temp_long; 371 continue; 372 } 373 374 if (sscanf(line, "pp_data->cap[%u]->Units = %lu\n", &caps_idx, &temp_ulong) == 2) { 375 pp_data->caps[caps_idx].Units = temp_ulong; 376 continue; 377 } 378 if (sscanf(line, "pp_data->cap[%u]->UnitsExp = %lu\n", &caps_idx, &temp_ulong) == 2) { 379 pp_data->caps[caps_idx].UnitsExp = temp_ulong; 380 continue; 381 } 382 if (sscanf(line, "pp_data->cap[%u]->Reserved1 = 0x%02hhu%02hhu%02hhu\n", &coll_idx, &temp_uchar[0], &temp_uchar[1], &temp_uchar[2]) == 4) { 383 pp_data->caps[caps_idx].Reserved1[0] = temp_uchar[0]; 384 pp_data->caps[caps_idx].Reserved1[1] = temp_uchar[1]; 385 pp_data->caps[caps_idx].Reserved1[2] = temp_uchar[2]; 386 continue; 387 } 388 fprintf(stderr, "Ignoring unimplemented cap field: %s", line); 389 continue; 390 } 391 392 if (sscanf(line, "pp_data->LinkCollectionArray[%u]", &coll_idx) == 1) { 393 if (pp_data->FirstByteOfLinkCollectionArray == 0 || pp_data->NumberLinkCollectionNodes == 0) { 394 fprintf(stderr, "Error reading pp_data file (%s): FirstByteOfLinkCollectionArray or NumberLinkCollectionNodes is 0 or not reported yet\n", line); 395 continue; 396 } 397 if (coll_idx >= pp_data->NumberLinkCollectionNodes) { 398 fprintf(stderr, "Error reading pp_data file (%s): the LinkCollection index (%u) is out of boundary (%hu)\n", line, coll_idx, pp_data->NumberLinkCollectionNodes); 399 continue; 400 } 401 phid_pp_link_collection_node pcoll = (phid_pp_link_collection_node)(((unsigned char*)&pp_data->caps[0]) + pp_data->FirstByteOfLinkCollectionArray); 402 if (sscanf(line, "pp_data->LinkCollectionArray[%u]->LinkUsage = 0x%04hX\n", &coll_idx, &temp_usage) == 2) { 403 pcoll[coll_idx].LinkUsage = temp_usage; 404 continue; 405 } 406 if (sscanf(line, "pp_data->LinkCollectionArray[%u]->LinkUsagePage = 0x%04hX\n", &coll_idx, &temp_usage) == 2) { 407 pcoll[coll_idx].LinkUsagePage = temp_usage; 408 continue; 409 } 410 if (sscanf(line, "pp_data->LinkCollectionArray[%u]->Parent = %hu\n", &coll_idx, &temp_ushort) == 2) { 411 pcoll[coll_idx].Parent = temp_ushort; 412 continue; 413 } 414 if (sscanf(line, "pp_data->LinkCollectionArray[%u]->NumberOfChildren = %hu\n", &coll_idx, &temp_ushort) == 2) { 415 pcoll[coll_idx].NumberOfChildren = temp_ushort; 416 continue; 417 } 418 if (sscanf(line, "pp_data->LinkCollectionArray[%u]->NextSibling = %hu\n", &coll_idx, &temp_ushort) == 2) { 419 pcoll[coll_idx].NextSibling = temp_ushort; 420 continue; 421 } 422 if (sscanf(line, "pp_data->LinkCollectionArray[%u]->FirstChild = %hu\n", &coll_idx, &temp_ushort) == 2) { 423 pcoll[coll_idx].FirstChild = temp_ushort; 424 continue; 425 } 426 if (sscanf(line, "pp_data->LinkCollectionArray[%u]->CollectionType = %lu\n", &coll_idx, &temp_ulong) == 2) { 427 pcoll[coll_idx].CollectionType = temp_ulong; 428 continue; 429 } 430 if (sscanf(line, "pp_data->LinkCollectionArray[%u]->IsAlias = %lu\n", &coll_idx, &temp_ulong) == 2) { 431 pcoll[coll_idx].IsAlias = temp_ulong; 432 continue; 433 } 434 if (sscanf(line, "pp_data->LinkCollectionArray[%u]->Reserved = %lu\n", &coll_idx, &temp_ulong) == 2) { 435 pcoll[coll_idx].Reserved = temp_ulong; 436 continue; 437 } 438 fprintf(stderr, "Ignoring unimplemented LinkCollectionArray field: %s", line); 439 continue; 440 } 441 } 442 443//end: 444 fclose(file); 445 446 if (pp_data == &static_pp_data) { 447 return NULL; 448 } 449 450 return pp_data; 451} 452 453static BOOLEAN read_hex_data_from_text_file(const char *filename, unsigned char *data_out, size_t data_size, size_t *actual_read) 454{ 455 size_t read_index = 0; 456 FILE* file = NULL; 457 errno_t err = fopen_s(&file, filename, "r"); 458 if (err != 0) { 459 fprintf(stderr, "ERROR: Couldn't open file '%s' for reading: %s\n", filename, strerror(err)); 460 return FALSE; 461 } 462 463 BOOLEAN result = TRUE; 464 unsigned int val; 465 char buf[16]; 466 while (fscanf(file, "%15s", buf) == 1) { 467 if (sscanf(buf, "0x%X", &val) != 1) { 468 fprintf(stderr, "Invalid HEX text ('%s') file, got %s\n", filename, buf); 469 result = FALSE; 470 goto end; 471 } 472 473 if (read_index >= data_size) { 474 fprintf(stderr, "Buffer for file read is too small. Got only %zu bytes to read '%s'\n", data_size, filename); 475 result = FALSE; 476 goto end; 477 } 478 479 if (val > (unsigned char)-1) { 480 fprintf(stderr, "Invalid HEX text ('%s') file, got a value of: %u\n", filename, val); 481 result = FALSE; 482 goto end; 483 } 484 485 data_out[read_index] = (unsigned char) val; 486 487 read_index++; 488 } 489 490 if (!feof(file)) { 491 fprintf(stderr, "Invalid HEX text ('%s') file - failed to read all values\n", filename); 492 result = FALSE; 493 goto end; 494 } 495 496 *actual_read = read_index; 497 498end: 499 fclose(file); 500 return result; 501} 502 503 504int main(int argc, char* argv[]) 505{ 506 if (argc != 3) { 507 fprintf(stderr, "Expected 2 arguments for the test ('<>.pp_data' and '<>_expected.rpt_desc'), got: %d\n", argc - 1); 508 return EXIT_FAILURE; 509 } 510 511 printf("Checking: '%s' / '%s'\n", argv[1], argv[2]); 512 513 hidp_preparsed_data *pp_data = alloc_preparsed_data_from_file(argv[1]); 514 if (pp_data == NULL) { 515 return EXIT_FAILURE; 516 } 517 518 int result = EXIT_SUCCESS; 519 520 unsigned char report_descriptor[HID_API_MAX_REPORT_DESCRIPTOR_SIZE]; 521 522 int res = hid_winapi_descriptor_reconstruct_pp_data(pp_data, report_descriptor, sizeof(report_descriptor)); 523 524 if (res < 0) { 525 result = EXIT_FAILURE; 526 fprintf(stderr, "Failed to reconstruct descriptor"); 527 goto end; 528 } 529 size_t report_descriptor_size = (size_t) res; 530 531 unsigned char expected_report_descriptor[HID_API_MAX_REPORT_DESCRIPTOR_SIZE]; 532 size_t expected_report_descriptor_size = 0; 533 if (!read_hex_data_from_text_file(argv[2], expected_report_descriptor, sizeof(expected_report_descriptor), &expected_report_descriptor_size)) { 534 result = EXIT_FAILURE; 535 goto end; 536 } 537 538 if (report_descriptor_size == expected_report_descriptor_size) { 539 if (memcmp(report_descriptor, expected_report_descriptor, report_descriptor_size) == 0) { 540 printf("Reconstructed Report Descriptor matches the expected descriptor\n"); 541 goto end; 542 } 543 else { 544 result = EXIT_FAILURE; 545 fprintf(stderr, "Reconstructed Report Descriptor has different content than expected\n"); 546 } 547 } 548 else { 549 result = EXIT_FAILURE; 550 fprintf(stderr, "Reconstructed Report Descriptor has different size: %zu when expected %zu\n", report_descriptor_size, expected_report_descriptor_size); 551 } 552 553 printf(" Reconstructed Report Descriptor:\n"); 554 for (int i = 0; i < res; i++) { 555 printf("0x%02X, ", report_descriptor[i]); 556 } 557 printf("\n"); 558 fflush(stdout); 559 560end: 561 free(pp_data); 562 return result; 563} 564
[FILE END]
(C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.