1 /* 2 * PROJECT: ReactOS HID Parser Library 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: lib/drivers/hidparser/hidparser.c 5 * PURPOSE: HID Parser 6 * PROGRAMMERS: 7 * Michael Martin (michael.martin@reactos.org) 8 * Johannes Anderwald (johannes.anderwald@reactos.org) 9 */ 10 11 #include "parser.h" 12 13 #define NDEBUG 14 #include <debug.h> 15 16 NTSTATUS 17 NTAPI 18 HidParser_GetCollectionDescription( 19 IN PHIDP_REPORT_DESCRIPTOR ReportDesc, 20 IN ULONG DescLength, 21 IN POOL_TYPE PoolType, 22 OUT PHIDP_DEVICE_DESC DeviceDescription) 23 { 24 NTSTATUS ParserStatus; 25 ULONG CollectionCount; 26 ULONG Index; 27 PVOID ParserContext; 28 29 // 30 // first parse the report descriptor 31 // 32 ParserStatus = HidParser_ParseReportDescriptor(ReportDesc, DescLength, &ParserContext); 33 if (ParserStatus != HIDP_STATUS_SUCCESS) 34 { 35 // 36 // failed to parse report descriptor 37 // 38 DebugFunction("[HIDPARSER] Failed to parse report descriptor with %x\n", ParserStatus); 39 return ParserStatus; 40 } 41 42 // 43 // get collection count 44 // 45 CollectionCount = HidParser_NumberOfTopCollections(ParserContext); 46 if (CollectionCount == 0) 47 { 48 // 49 // no top level collections found 50 // 51 ASSERT(FALSE); 52 return STATUS_NO_DATA_DETECTED; 53 } 54 55 // 56 // zero description 57 // 58 ZeroFunction(DeviceDescription, sizeof(HIDP_DEVICE_DESC)); 59 60 // 61 // allocate collection 62 // 63 DeviceDescription->CollectionDesc = (PHIDP_COLLECTION_DESC)AllocFunction(sizeof(HIDP_COLLECTION_DESC) * CollectionCount); 64 if (!DeviceDescription->CollectionDesc) 65 { 66 // 67 // no memory 68 // 69 return STATUS_INSUFFICIENT_RESOURCES; 70 } 71 72 // 73 // allocate report description 74 // 75 DeviceDescription->ReportIDs = (PHIDP_REPORT_IDS)AllocFunction(sizeof(HIDP_REPORT_IDS) * CollectionCount); 76 if (!DeviceDescription->ReportIDs) 77 { 78 // 79 // no memory 80 // 81 FreeFunction(DeviceDescription->CollectionDesc); 82 return STATUS_INSUFFICIENT_RESOURCES; 83 } 84 85 for(Index = 0; Index < CollectionCount; Index++) 86 { 87 // 88 // set preparsed data length 89 // 90 DeviceDescription->CollectionDesc[Index].PreparsedDataLength = HidParser_GetContextSize(ParserContext, Index); 91 ParserStatus = HidParser_BuildContext(ParserContext, Index, DeviceDescription->CollectionDesc[Index].PreparsedDataLength, (PVOID*)&DeviceDescription->CollectionDesc[Index].PreparsedData); 92 if (ParserStatus != HIDP_STATUS_SUCCESS) 93 { 94 // 95 // no memory 96 // 97 FreeFunction(DeviceDescription->CollectionDesc); 98 FreeFunction(DeviceDescription->ReportIDs); 99 return ParserStatus; 100 } 101 102 // 103 // init report description 104 // 105 DeviceDescription->ReportIDs[Index].CollectionNumber = Index + 1; 106 DeviceDescription->ReportIDs[Index].ReportID = Index; //FIXME 107 DeviceDescription->ReportIDs[Index].InputLength = HidParser_GetReportLength((PVOID)DeviceDescription->CollectionDesc[Index].PreparsedData, HID_REPORT_TYPE_INPUT); 108 DeviceDescription->ReportIDs[Index].OutputLength = HidParser_GetReportLength((PVOID)DeviceDescription->CollectionDesc[Index].PreparsedData, HID_REPORT_TYPE_OUTPUT); 109 DeviceDescription->ReportIDs[Index].FeatureLength = HidParser_GetReportLength((PVOID)DeviceDescription->CollectionDesc[Index].PreparsedData, HID_REPORT_TYPE_FEATURE); 110 111 112 DeviceDescription->ReportIDs[Index].InputLength += (HidParser_UsesReportId((PVOID)DeviceDescription->CollectionDesc[Index].PreparsedData, HID_REPORT_TYPE_INPUT) ? 1 : 0); 113 DeviceDescription->ReportIDs[Index].OutputLength += (HidParser_UsesReportId((PVOID)DeviceDescription->CollectionDesc[Index].PreparsedData, HID_REPORT_TYPE_OUTPUT) ? 1 : 0); 114 DeviceDescription->ReportIDs[Index].FeatureLength += (HidParser_UsesReportId((PVOID)DeviceDescription->CollectionDesc[Index].PreparsedData, HID_REPORT_TYPE_FEATURE) ? 1 : 0); 115 116 117 // 118 // init collection description 119 // 120 DeviceDescription->CollectionDesc[Index].CollectionNumber = Index + 1; 121 122 // 123 // get collection usage page 124 // 125 ParserStatus = HidParser_GetCollectionUsagePage((PVOID)DeviceDescription->CollectionDesc[Index].PreparsedData, &DeviceDescription->CollectionDesc[Index].Usage, &DeviceDescription->CollectionDesc[Index].UsagePage); 126 if (ParserStatus != HIDP_STATUS_SUCCESS) 127 { 128 // collection not found 129 FreeFunction(DeviceDescription->CollectionDesc); 130 FreeFunction(DeviceDescription->ReportIDs); 131 return ParserStatus; 132 } 133 134 // 135 // windows seems to prepend the report id, regardless if it is required 136 // 137 DeviceDescription->CollectionDesc[Index].CollectionNumber = Index + 1; 138 DeviceDescription->CollectionDesc[Index].InputLength = DeviceDescription->ReportIDs[Index].InputLength; 139 DeviceDescription->CollectionDesc[Index].OutputLength = DeviceDescription->ReportIDs[Index].OutputLength; 140 DeviceDescription->CollectionDesc[Index].FeatureLength = DeviceDescription->ReportIDs[Index].FeatureLength; 141 142 DeviceDescription->CollectionDesc[Index].InputLength += (HidParser_UsesReportId((PVOID)DeviceDescription->CollectionDesc[Index].PreparsedData, HID_REPORT_TYPE_INPUT) == FALSE ? 1 : 0); 143 DeviceDescription->CollectionDesc[Index].OutputLength += (HidParser_UsesReportId((PVOID)DeviceDescription->CollectionDesc[Index].PreparsedData, HID_REPORT_TYPE_OUTPUT) == FALSE ? 1 : 0); 144 DeviceDescription->CollectionDesc[Index].FeatureLength += (HidParser_UsesReportId((PVOID)DeviceDescription->CollectionDesc[Index].PreparsedData, HID_REPORT_TYPE_FEATURE) == FALSE ? 1 : 0); 145 146 147 } 148 149 // 150 // store collection & report count 151 // 152 DeviceDescription->CollectionDescLength = CollectionCount; 153 DeviceDescription->ReportIDsLength = CollectionCount; 154 155 // 156 // done 157 // 158 return STATUS_SUCCESS; 159 } 160 161 VOID 162 NTAPI 163 HidParser_FreeCollectionDescription( 164 IN PHIDP_DEVICE_DESC DeviceDescription) 165 { 166 ULONG Index; 167 168 // 169 // first free all context 170 // 171 for(Index = 0; Index < DeviceDescription->CollectionDescLength; Index++) 172 { 173 // 174 // free collection context 175 // 176 FreeFunction(DeviceDescription->CollectionDesc[Index].PreparsedData); 177 } 178 179 // 180 // now free collection description 181 // 182 FreeFunction(DeviceDescription->CollectionDesc); 183 184 // 185 // free report description 186 // 187 FreeFunction(DeviceDescription->ReportIDs); 188 } 189 190 HIDAPI 191 NTSTATUS 192 NTAPI 193 HidParser_GetCaps( 194 IN PVOID CollectionContext, 195 OUT PHIDP_CAPS Capabilities) 196 { 197 // 198 // zero capabilities 199 // 200 ZeroFunction(Capabilities, sizeof(HIDP_CAPS)); 201 202 // 203 // init capabilities 204 // 205 HidParser_GetCollectionUsagePage(CollectionContext, &Capabilities->Usage, &Capabilities->UsagePage); 206 Capabilities->InputReportByteLength = HidParser_GetReportLength(CollectionContext, HID_REPORT_TYPE_INPUT); 207 Capabilities->OutputReportByteLength = HidParser_GetReportLength(CollectionContext, HID_REPORT_TYPE_OUTPUT); 208 Capabilities->FeatureReportByteLength = HidParser_GetReportLength(CollectionContext, HID_REPORT_TYPE_FEATURE); 209 210 // 211 // always pre-prend report id 212 // 213 Capabilities->InputReportByteLength = (Capabilities->InputReportByteLength > 0 ? Capabilities->InputReportByteLength + 1 : 0); 214 Capabilities->OutputReportByteLength = (Capabilities->OutputReportByteLength > 0 ? Capabilities->OutputReportByteLength + 1 : 0); 215 Capabilities->FeatureReportByteLength = (Capabilities->FeatureReportByteLength > 0 ? Capabilities->FeatureReportByteLength + 1 : 0); 216 217 // 218 // get number of link collection nodes 219 // 220 Capabilities->NumberLinkCollectionNodes = HidParser_GetTotalCollectionCount(CollectionContext); 221 222 // 223 // get data indices 224 // 225 Capabilities->NumberInputDataIndices = HidParser_GetReportItemTypeCountFromReportType(CollectionContext, HID_REPORT_TYPE_INPUT, TRUE); 226 Capabilities->NumberOutputDataIndices = HidParser_GetReportItemTypeCountFromReportType(CollectionContext, HID_REPORT_TYPE_OUTPUT, TRUE); 227 Capabilities->NumberFeatureDataIndices = HidParser_GetReportItemTypeCountFromReportType(CollectionContext, HID_REPORT_TYPE_FEATURE, TRUE); 228 229 // 230 // get value caps 231 // 232 Capabilities->NumberInputValueCaps = HidParser_GetReportItemTypeCountFromReportType(CollectionContext, HID_REPORT_TYPE_INPUT, FALSE); 233 Capabilities->NumberOutputValueCaps = HidParser_GetReportItemTypeCountFromReportType(CollectionContext, HID_REPORT_TYPE_OUTPUT, FALSE); 234 Capabilities->NumberFeatureValueCaps = HidParser_GetReportItemTypeCountFromReportType(CollectionContext, HID_REPORT_TYPE_FEATURE, FALSE); 235 236 237 // 238 // get button caps 239 // 240 Capabilities->NumberInputButtonCaps = HidParser_GetReportItemCountFromReportType(CollectionContext, HID_REPORT_TYPE_INPUT); 241 Capabilities->NumberOutputButtonCaps = HidParser_GetReportItemCountFromReportType(CollectionContext, HID_REPORT_TYPE_OUTPUT); 242 Capabilities->NumberFeatureButtonCaps = HidParser_GetReportItemCountFromReportType(CollectionContext, HID_REPORT_TYPE_FEATURE); 243 244 // 245 // done 246 // 247 return HIDP_STATUS_SUCCESS; 248 } 249 250 HIDAPI 251 ULONG 252 NTAPI 253 HidParser_MaxUsageListLength( 254 IN PVOID CollectionContext, 255 IN HIDP_REPORT_TYPE ReportType, 256 IN USAGE UsagePage OPTIONAL) 257 { 258 // 259 // FIXME test what should be returned when usage page is not defined 260 // 261 if (UsagePage == HID_USAGE_PAGE_UNDEFINED) 262 { 263 // 264 // implement me 265 // 266 UNIMPLEMENTED; 267 268 // 269 // invalid report 270 // 271 return 0; 272 } 273 274 if (ReportType == HidP_Input) 275 { 276 // 277 // input report 278 // 279 return HidParser_GetMaxUsageListLengthWithReportAndPage(CollectionContext, HID_REPORT_TYPE_INPUT, UsagePage); 280 } 281 else if (ReportType == HidP_Output) 282 { 283 // 284 // input report 285 // 286 return HidParser_GetMaxUsageListLengthWithReportAndPage(CollectionContext, HID_REPORT_TYPE_OUTPUT, UsagePage); 287 } 288 else if (ReportType == HidP_Feature) 289 { 290 // 291 // input report 292 // 293 return HidParser_GetMaxUsageListLengthWithReportAndPage(CollectionContext, HID_REPORT_TYPE_FEATURE, UsagePage); 294 } 295 else 296 { 297 // 298 // invalid report type 299 // 300 return 0; 301 } 302 } 303 304 #undef HidParser_GetButtonCaps 305 306 HIDAPI 307 NTSTATUS 308 NTAPI 309 HidParser_GetButtonCaps( 310 IN PVOID CollectionContext, 311 IN HIDP_REPORT_TYPE ReportType, 312 IN PHIDP_BUTTON_CAPS ButtonCaps, 313 IN PUSHORT ButtonCapsLength) 314 { 315 return HidParser_GetSpecificButtonCaps(CollectionContext, ReportType, HID_USAGE_PAGE_UNDEFINED, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_PAGE_UNDEFINED, ButtonCaps, (PULONG)ButtonCapsLength); 316 } 317 318 HIDAPI 319 NTSTATUS 320 NTAPI 321 HidParser_GetSpecificValueCaps( 322 IN PVOID CollectionContext, 323 IN HIDP_REPORT_TYPE ReportType, 324 IN USAGE UsagePage, 325 IN USHORT LinkCollection, 326 IN USAGE Usage, 327 OUT PHIDP_VALUE_CAPS ValueCaps, 328 IN OUT PUSHORT ValueCapsLength) 329 { 330 NTSTATUS ParserStatus; 331 332 // 333 // FIXME: implement searching in specific collection 334 // 335 ASSERT(LinkCollection == HIDP_LINK_COLLECTION_UNSPECIFIED); 336 337 if (ReportType == HidP_Input) 338 { 339 // 340 // input report 341 // 342 ParserStatus = HidParser_GetSpecificValueCapsWithReport(CollectionContext, HID_REPORT_TYPE_INPUT, UsagePage, Usage, ValueCaps, ValueCapsLength); 343 } 344 else if (ReportType == HidP_Output) 345 { 346 // 347 // input report 348 // 349 ParserStatus = HidParser_GetSpecificValueCapsWithReport(CollectionContext, HID_REPORT_TYPE_OUTPUT, UsagePage, Usage, ValueCaps, ValueCapsLength); 350 } 351 else if (ReportType == HidP_Feature) 352 { 353 // 354 // input report 355 // 356 ParserStatus = HidParser_GetSpecificValueCapsWithReport(CollectionContext, HID_REPORT_TYPE_FEATURE, UsagePage, Usage, ValueCaps, ValueCapsLength); 357 } 358 else 359 { 360 // 361 // invalid report type 362 // 363 return HIDP_STATUS_INVALID_REPORT_TYPE; 364 } 365 366 // 367 // return status 368 // 369 return ParserStatus; 370 } 371 372 HIDAPI 373 NTSTATUS 374 NTAPI 375 HidParser_UsageListDifference( 376 IN PUSAGE PreviousUsageList, 377 IN PUSAGE CurrentUsageList, 378 OUT PUSAGE BreakUsageList, 379 OUT PUSAGE MakeUsageList, 380 IN ULONG UsageListLength) 381 { 382 ULONG Index, SubIndex, bFound, BreakUsageIndex = 0, MakeUsageIndex = 0; 383 USAGE CurrentUsage, Usage; 384 385 if (UsageListLength) 386 { 387 Index = 0; 388 do 389 { 390 /* get current usage */ 391 CurrentUsage = PreviousUsageList[Index]; 392 393 /* is the end of list reached? */ 394 if (!CurrentUsage) 395 break; 396 397 /* start searching in current usage list */ 398 SubIndex = 0; 399 bFound = FALSE; 400 do 401 { 402 /* get usage of current list */ 403 Usage = CurrentUsageList[SubIndex]; 404 405 /* end of list reached? */ 406 if (!Usage) 407 break; 408 409 /* check if it matches the current one */ 410 if (CurrentUsage == Usage) 411 { 412 /* it does */ 413 bFound = TRUE; 414 break; 415 } 416 417 /* move to next usage */ 418 SubIndex++; 419 }while(SubIndex < UsageListLength); 420 421 /* was the usage found ?*/ 422 if (!bFound) 423 { 424 /* store it in the break usage list */ 425 BreakUsageList[BreakUsageIndex] = CurrentUsage; 426 BreakUsageIndex++; 427 } 428 429 /* move to next usage */ 430 Index++; 431 432 }while(Index < UsageListLength); 433 434 /* now process the new items */ 435 Index = 0; 436 do 437 { 438 /* get current usage */ 439 CurrentUsage = CurrentUsageList[Index]; 440 441 /* is the end of list reached? */ 442 if (!CurrentUsage) 443 break; 444 445 /* start searching in current usage list */ 446 SubIndex = 0; 447 bFound = FALSE; 448 do 449 { 450 /* get usage of previous list */ 451 Usage = PreviousUsageList[SubIndex]; 452 453 /* end of list reached? */ 454 if (!Usage) 455 break; 456 457 /* check if it matches the current one */ 458 if (CurrentUsage == Usage) 459 { 460 /* it does */ 461 bFound = TRUE; 462 break; 463 } 464 465 /* move to next usage */ 466 SubIndex++; 467 }while(SubIndex < UsageListLength); 468 469 /* was the usage found ?*/ 470 if (!bFound) 471 { 472 /* store it in the make usage list */ 473 MakeUsageList[MakeUsageIndex] = CurrentUsage; 474 MakeUsageIndex++; 475 } 476 477 /* move to next usage */ 478 Index++; 479 480 }while(Index < UsageListLength); 481 } 482 483 /* does the break list contain empty entries */ 484 if (BreakUsageIndex < UsageListLength) 485 { 486 /* zeroize entries */ 487 RtlZeroMemory(&BreakUsageList[BreakUsageIndex], sizeof(USAGE) * (UsageListLength - BreakUsageIndex)); 488 } 489 490 /* does the make usage list contain empty entries */ 491 if (MakeUsageIndex < UsageListLength) 492 { 493 /* zeroize entries */ 494 RtlZeroMemory(&MakeUsageList[MakeUsageIndex], sizeof(USAGE) * (UsageListLength - MakeUsageIndex)); 495 } 496 497 /* done */ 498 return HIDP_STATUS_SUCCESS; 499 } 500 501 HIDAPI 502 NTSTATUS 503 NTAPI 504 HidParser_GetUsages( 505 IN PVOID CollectionContext, 506 IN HIDP_REPORT_TYPE ReportType, 507 IN USAGE UsagePage, 508 IN USHORT LinkCollection OPTIONAL, 509 OUT USAGE *UsageList, 510 IN OUT PULONG UsageLength, 511 IN PCHAR Report, 512 IN ULONG ReportLength) 513 { 514 NTSTATUS ParserStatus; 515 516 // 517 // FIXME: implement searching in specific collection 518 // 519 ASSERT(LinkCollection == HIDP_LINK_COLLECTION_UNSPECIFIED); 520 521 if (ReportType == HidP_Input) 522 { 523 // 524 // input report 525 // 526 ParserStatus = HidParser_GetUsagesWithReport(CollectionContext, HID_REPORT_TYPE_INPUT, UsagePage, UsageList, UsageLength, Report, ReportLength); 527 } 528 else if (ReportType == HidP_Output) 529 { 530 // 531 // input report 532 // 533 ParserStatus = HidParser_GetUsagesWithReport(CollectionContext, HID_REPORT_TYPE_OUTPUT, UsagePage, UsageList, UsageLength, Report, ReportLength); 534 } 535 else if (ReportType == HidP_Feature) 536 { 537 // 538 // input report 539 // 540 ParserStatus = HidParser_GetUsagesWithReport(CollectionContext, HID_REPORT_TYPE_FEATURE, UsagePage, UsageList, UsageLength, Report, ReportLength); 541 } 542 else 543 { 544 // 545 // invalid report type 546 // 547 return HIDP_STATUS_INVALID_REPORT_TYPE; 548 } 549 550 // 551 // return status 552 // 553 return ParserStatus; 554 } 555 556 HIDAPI 557 NTSTATUS 558 NTAPI 559 HidParser_GetScaledUsageValue( 560 IN PVOID CollectionContext, 561 IN HIDP_REPORT_TYPE ReportType, 562 IN USAGE UsagePage, 563 IN USHORT LinkCollection OPTIONAL, 564 IN USAGE Usage, 565 OUT PLONG UsageValue, 566 IN PCHAR Report, 567 IN ULONG ReportLength) 568 { 569 NTSTATUS ParserStatus; 570 571 // 572 // FIXME: implement searching in specific collection 573 // 574 ASSERT(LinkCollection == HIDP_LINK_COLLECTION_UNSPECIFIED); 575 576 if (ReportType == HidP_Input) 577 { 578 // 579 // input report 580 // 581 ParserStatus = HidParser_GetScaledUsageValueWithReport(CollectionContext, HID_REPORT_TYPE_INPUT, UsagePage, Usage, UsageValue, Report, ReportLength); 582 } 583 else if (ReportType == HidP_Output) 584 { 585 // 586 // input report 587 // 588 ParserStatus = HidParser_GetScaledUsageValueWithReport(CollectionContext, HID_REPORT_TYPE_OUTPUT, UsagePage, Usage, UsageValue, Report, ReportLength); 589 } 590 else if (ReportType == HidP_Feature) 591 { 592 // 593 // input report 594 // 595 ParserStatus = HidParser_GetScaledUsageValueWithReport(CollectionContext, HID_REPORT_TYPE_FEATURE, UsagePage, Usage, UsageValue, Report, ReportLength); 596 } 597 else 598 { 599 // 600 // invalid report type 601 // 602 return HIDP_STATUS_INVALID_REPORT_TYPE; 603 } 604 605 // 606 // return status 607 // 608 return ParserStatus; 609 } 610 611 HIDAPI 612 NTSTATUS 613 NTAPI 614 HidParser_TranslateUsageAndPagesToI8042ScanCodes( 615 IN PUSAGE_AND_PAGE ChangedUsageList, 616 IN ULONG UsageListLength, 617 IN HIDP_KEYBOARD_DIRECTION KeyAction, 618 IN OUT PHIDP_KEYBOARD_MODIFIER_STATE ModifierState, 619 IN PHIDP_INSERT_SCANCODES InsertCodesProcedure, 620 IN PVOID InsertCodesContext) 621 { 622 ULONG Index; 623 NTSTATUS Status = HIDP_STATUS_SUCCESS; 624 625 for(Index = 0; Index < UsageListLength; Index++) 626 { 627 // 628 // check current usage 629 // 630 if (ChangedUsageList[Index].UsagePage == HID_USAGE_PAGE_KEYBOARD) 631 { 632 // 633 // process keyboard usage 634 // 635 Status = HidParser_TranslateKbdUsage(ChangedUsageList[Index].Usage, KeyAction, ModifierState, InsertCodesProcedure, InsertCodesContext); 636 } 637 else if (ChangedUsageList[Index].UsagePage == HID_USAGE_PAGE_CONSUMER) 638 { 639 // 640 // process consumer usage 641 // 642 Status = HidParser_TranslateCustUsage(ChangedUsageList[Index].Usage, KeyAction, ModifierState, InsertCodesProcedure, InsertCodesContext); 643 } 644 else 645 { 646 // 647 // invalid page / end of usage list page 648 // 649 return HIDP_STATUS_I8042_TRANS_UNKNOWN; 650 } 651 652 // 653 // check status 654 // 655 if (Status != HIDP_STATUS_SUCCESS) 656 { 657 // 658 // failed 659 // 660 return Status; 661 } 662 } 663 664 // 665 // return status 666 // 667 return Status; 668 } 669 670 671 HIDAPI 672 NTSTATUS 673 NTAPI 674 HidParser_GetUsagesEx( 675 IN PVOID CollectionContext, 676 IN HIDP_REPORT_TYPE ReportType, 677 IN USHORT LinkCollection, 678 OUT PUSAGE_AND_PAGE ButtonList, 679 IN OUT ULONG *UsageLength, 680 IN PCHAR Report, 681 IN ULONG ReportLength) 682 { 683 return HidParser_GetUsages(CollectionContext, ReportType, HID_USAGE_PAGE_UNDEFINED, LinkCollection, (PUSAGE)ButtonList, UsageLength, Report, ReportLength); 684 } 685 686 HIDAPI 687 NTSTATUS 688 NTAPI 689 HidParser_UsageAndPageListDifference( 690 IN PUSAGE_AND_PAGE PreviousUsageList, 691 IN PUSAGE_AND_PAGE CurrentUsageList, 692 OUT PUSAGE_AND_PAGE BreakUsageList, 693 OUT PUSAGE_AND_PAGE MakeUsageList, 694 IN ULONG UsageListLength) 695 { 696 ULONG Index, SubIndex, BreakUsageListIndex = 0, MakeUsageListIndex = 0, bFound; 697 PUSAGE_AND_PAGE CurrentUsage, Usage; 698 699 if (UsageListLength) 700 { 701 /* process removed usages */ 702 Index = 0; 703 do 704 { 705 /* get usage from current index */ 706 CurrentUsage = &PreviousUsageList[Index]; 707 708 /* end of list reached? */ 709 if (CurrentUsage->Usage == 0 && CurrentUsage->UsagePage == 0) 710 break; 711 712 /* search in current list */ 713 SubIndex = 0; 714 bFound = FALSE; 715 do 716 { 717 /* get usage */ 718 Usage = &CurrentUsageList[SubIndex]; 719 720 /* end of list reached? */ 721 if (Usage->Usage == 0 && Usage->UsagePage == 0) 722 break; 723 724 /* does it match */ 725 if (Usage->Usage == CurrentUsage->Usage && Usage->UsagePage == CurrentUsage->UsagePage) 726 { 727 /* found match */ 728 bFound = TRUE; 729 } 730 731 /* move to next index */ 732 SubIndex++; 733 734 }while(SubIndex < UsageListLength); 735 736 if (!bFound) 737 { 738 /* store it in break usage list */ 739 BreakUsageList[BreakUsageListIndex].Usage = CurrentUsage->Usage; 740 BreakUsageList[BreakUsageListIndex].UsagePage = CurrentUsage->UsagePage; 741 BreakUsageListIndex++; 742 } 743 744 /* move to next index */ 745 Index++; 746 747 }while(Index < UsageListLength); 748 749 /* process new usages */ 750 Index = 0; 751 do 752 { 753 /* get usage from current index */ 754 CurrentUsage = &CurrentUsageList[Index]; 755 756 /* end of list reached? */ 757 if (CurrentUsage->Usage == 0 && CurrentUsage->UsagePage == 0) 758 break; 759 760 /* search in current list */ 761 SubIndex = 0; 762 bFound = FALSE; 763 do 764 { 765 /* get usage */ 766 Usage = &PreviousUsageList[SubIndex]; 767 768 /* end of list reached? */ 769 if (Usage->Usage == 0 && Usage->UsagePage == 0) 770 break; 771 772 /* does it match */ 773 if (Usage->Usage == CurrentUsage->Usage && Usage->UsagePage == CurrentUsage->UsagePage) 774 { 775 /* found match */ 776 bFound = TRUE; 777 } 778 779 /* move to next index */ 780 SubIndex++; 781 782 }while(SubIndex < UsageListLength); 783 784 if (!bFound) 785 { 786 /* store it in break usage list */ 787 MakeUsageList[MakeUsageListIndex].Usage = CurrentUsage->Usage; 788 MakeUsageList[MakeUsageListIndex].UsagePage = CurrentUsage->UsagePage; 789 MakeUsageListIndex++; 790 } 791 792 /* move to next index */ 793 Index++; 794 }while(Index < UsageListLength); 795 } 796 797 /* are there remaining free list entries */ 798 if (BreakUsageListIndex < UsageListLength) 799 { 800 /* zero them */ 801 RtlZeroMemory(&BreakUsageList[BreakUsageListIndex], (UsageListLength - BreakUsageListIndex) * sizeof(USAGE_AND_PAGE)); 802 } 803 804 /* are there remaining free list entries */ 805 if (MakeUsageListIndex < UsageListLength) 806 { 807 /* zero them */ 808 RtlZeroMemory(&MakeUsageList[MakeUsageListIndex], (UsageListLength - MakeUsageListIndex) * sizeof(USAGE_AND_PAGE)); 809 } 810 811 /* done */ 812 return HIDP_STATUS_SUCCESS; 813 } 814 815 HIDAPI 816 NTSTATUS 817 NTAPI 818 HidParser_GetSpecificButtonCaps( 819 IN PVOID CollectionContext, 820 IN HIDP_REPORT_TYPE ReportType, 821 IN USAGE UsagePage, 822 IN USHORT LinkCollection, 823 IN USAGE Usage, 824 OUT PHIDP_BUTTON_CAPS ButtonCaps, 825 IN OUT PULONG ButtonCapsLength) 826 { 827 UNIMPLEMENTED; 828 ASSERT(FALSE); 829 return STATUS_NOT_IMPLEMENTED; 830 } 831 832 833 HIDAPI 834 NTSTATUS 835 NTAPI 836 HidParser_GetData( 837 IN PVOID CollectionContext, 838 IN HIDP_REPORT_TYPE ReportType, 839 OUT PHIDP_DATA DataList, 840 IN OUT PULONG DataLength, 841 IN PCHAR Report, 842 IN ULONG ReportLength) 843 { 844 UNIMPLEMENTED; 845 ASSERT(FALSE); 846 return STATUS_NOT_IMPLEMENTED; 847 } 848 849 HIDAPI 850 NTSTATUS 851 NTAPI 852 HidParser_GetExtendedAttributes( 853 IN PVOID CollectionContext, 854 IN HIDP_REPORT_TYPE ReportType, 855 IN USHORT DataIndex, 856 OUT PHIDP_EXTENDED_ATTRIBUTES Attributes, 857 IN OUT PULONG LengthAttributes) 858 { 859 UNIMPLEMENTED; 860 ASSERT(FALSE); 861 return STATUS_NOT_IMPLEMENTED; 862 } 863 864 HIDAPI 865 NTSTATUS 866 NTAPI 867 HidParser_GetLinkCollectionNodes( 868 IN PVOID CollectionContext, 869 OUT PHIDP_LINK_COLLECTION_NODE LinkCollectionNodes, 870 IN OUT PULONG LinkCollectionNodesLength) 871 { 872 UNIMPLEMENTED; 873 ASSERT(FALSE); 874 return STATUS_NOT_IMPLEMENTED; 875 } 876 877 HIDAPI 878 NTSTATUS 879 NTAPI 880 HidParser_GetUsageValue( 881 IN PVOID CollectionContext, 882 IN HIDP_REPORT_TYPE ReportType, 883 IN USAGE UsagePage, 884 IN USHORT LinkCollection, 885 IN USAGE Usage, 886 OUT PULONG UsageValue, 887 IN PCHAR Report, 888 IN ULONG ReportLength) 889 { 890 NTSTATUS ParserStatus; 891 892 // 893 // FIXME: implement searching in specific collection 894 // 895 ASSERT(LinkCollection == HIDP_LINK_COLLECTION_UNSPECIFIED); 896 897 if (ReportType == HidP_Input) 898 { 899 // 900 // input report 901 // 902 ParserStatus = HidParser_GetUsageValueWithReport(CollectionContext, HID_REPORT_TYPE_INPUT, UsagePage, Usage, UsageValue, Report, ReportLength); 903 } 904 else if (ReportType == HidP_Output) 905 { 906 // 907 // input report 908 // 909 ParserStatus = HidParser_GetUsageValueWithReport(CollectionContext, HID_REPORT_TYPE_OUTPUT, UsagePage, Usage, UsageValue, Report, ReportLength); 910 } 911 else if (ReportType == HidP_Feature) 912 { 913 // 914 // input report 915 // 916 ParserStatus = HidParser_GetUsageValueWithReport(CollectionContext, HID_REPORT_TYPE_FEATURE, UsagePage, Usage, UsageValue, Report, ReportLength); 917 } 918 else 919 { 920 // 921 // invalid report type 922 // 923 return HIDP_STATUS_INVALID_REPORT_TYPE; 924 } 925 926 // 927 // return status 928 // 929 return ParserStatus; 930 } 931 932 NTSTATUS 933 NTAPI 934 HidParser_SysPowerEvent( 935 IN PVOID CollectionContext, 936 IN PCHAR HidPacket, 937 IN USHORT HidPacketLength, 938 OUT PULONG OutputBuffer) 939 { 940 UNIMPLEMENTED; 941 ASSERT(FALSE); 942 return STATUS_NOT_IMPLEMENTED; 943 } 944 945 NTSTATUS 946 NTAPI 947 HidParser_SysPowerCaps ( 948 IN PVOID CollectionContext, 949 OUT PULONG OutputBuffer) 950 { 951 UNIMPLEMENTED; 952 ASSERT(FALSE); 953 return STATUS_NOT_IMPLEMENTED; 954 } 955 956 HIDAPI 957 NTSTATUS 958 NTAPI 959 HidParser_GetUsageValueArray( 960 IN PVOID CollectionContext, 961 IN HIDP_REPORT_TYPE ReportType, 962 IN USAGE UsagePage, 963 IN USHORT LinkCollection OPTIONAL, 964 IN USAGE Usage, 965 OUT PCHAR UsageValue, 966 IN USHORT UsageValueByteLength, 967 IN PCHAR Report, 968 IN ULONG ReportLength) 969 { 970 UNIMPLEMENTED; 971 ASSERT(FALSE); 972 return STATUS_NOT_IMPLEMENTED; 973 } 974 975 HIDAPI 976 NTSTATUS 977 NTAPI 978 HidParser_UnsetUsages( 979 IN PVOID CollectionContext, 980 IN HIDP_REPORT_TYPE ReportType, 981 IN USAGE UsagePage, 982 IN USHORT LinkCollection, 983 IN PUSAGE UsageList, 984 IN OUT PULONG UsageLength, 985 IN OUT PCHAR Report, 986 IN ULONG ReportLength) 987 { 988 UNIMPLEMENTED; 989 ASSERT(FALSE); 990 return STATUS_NOT_IMPLEMENTED; 991 } 992 993 HIDAPI 994 NTSTATUS 995 NTAPI 996 HidParser_TranslateUsagesToI8042ScanCodes( 997 IN PUSAGE ChangedUsageList, 998 IN ULONG UsageListLength, 999 IN HIDP_KEYBOARD_DIRECTION KeyAction, 1000 IN OUT PHIDP_KEYBOARD_MODIFIER_STATE ModifierState, 1001 IN PHIDP_INSERT_SCANCODES InsertCodesProcedure, 1002 IN PVOID InsertCodesContext) 1003 { 1004 UNIMPLEMENTED; 1005 ASSERT(FALSE); 1006 return STATUS_NOT_IMPLEMENTED; 1007 } 1008 1009 HIDAPI 1010 NTSTATUS 1011 NTAPI 1012 HidParser_SetUsages( 1013 IN PVOID CollectionContext, 1014 IN HIDP_REPORT_TYPE ReportType, 1015 IN USAGE UsagePage, 1016 IN USHORT LinkCollection, 1017 IN PUSAGE UsageList, 1018 IN OUT PULONG UsageLength, 1019 IN OUT PCHAR Report, 1020 IN ULONG ReportLength) 1021 { 1022 UNIMPLEMENTED; 1023 ASSERT(FALSE); 1024 return STATUS_NOT_IMPLEMENTED; 1025 } 1026 1027 HIDAPI 1028 NTSTATUS 1029 NTAPI 1030 HidParser_SetUsageValueArray( 1031 IN PVOID CollectionContext, 1032 IN HIDP_REPORT_TYPE ReportType, 1033 IN USAGE UsagePage, 1034 IN USHORT LinkCollection OPTIONAL, 1035 IN USAGE Usage, 1036 IN PCHAR UsageValue, 1037 IN USHORT UsageValueByteLength, 1038 OUT PCHAR Report, 1039 IN ULONG ReportLength) 1040 { 1041 UNIMPLEMENTED; 1042 ASSERT(FALSE); 1043 return STATUS_NOT_IMPLEMENTED; 1044 } 1045 1046 HIDAPI 1047 NTSTATUS 1048 NTAPI 1049 HidParser_SetUsageValue( 1050 IN PVOID CollectionContext, 1051 IN HIDP_REPORT_TYPE ReportType, 1052 IN USAGE UsagePage, 1053 IN USHORT LinkCollection, 1054 IN USAGE Usage, 1055 IN ULONG UsageValue, 1056 IN OUT PCHAR Report, 1057 IN ULONG ReportLength) 1058 { 1059 UNIMPLEMENTED; 1060 ASSERT(FALSE); 1061 return STATUS_NOT_IMPLEMENTED; 1062 } 1063 1064 HIDAPI 1065 NTSTATUS 1066 NTAPI 1067 HidParser_SetScaledUsageValue( 1068 IN PVOID CollectionContext, 1069 IN HIDP_REPORT_TYPE ReportType, 1070 IN USAGE UsagePage, 1071 IN USHORT LinkCollection OPTIONAL, 1072 IN USAGE Usage, 1073 IN LONG UsageValue, 1074 IN OUT PCHAR Report, 1075 IN ULONG ReportLength) 1076 { 1077 UNIMPLEMENTED; 1078 ASSERT(FALSE); 1079 return STATUS_NOT_IMPLEMENTED; 1080 } 1081 1082 HIDAPI 1083 NTSTATUS 1084 NTAPI 1085 HidParser_SetData( 1086 IN PVOID CollectionContext, 1087 IN HIDP_REPORT_TYPE ReportType, 1088 IN PHIDP_DATA DataList, 1089 IN OUT PULONG DataLength, 1090 IN OUT PCHAR Report, 1091 IN ULONG ReportLength) 1092 { 1093 UNIMPLEMENTED; 1094 ASSERT(FALSE); 1095 return STATUS_NOT_IMPLEMENTED; 1096 } 1097 1098 HIDAPI 1099 ULONG 1100 NTAPI 1101 HidParser_MaxDataListLength( 1102 IN PVOID CollectionContext, 1103 IN HIDP_REPORT_TYPE ReportType) 1104 { 1105 UNIMPLEMENTED; 1106 ASSERT(FALSE); 1107 return 0; 1108 } 1109 1110 HIDAPI 1111 NTSTATUS 1112 NTAPI 1113 HidParser_InitializeReportForID( 1114 IN PVOID CollectionContext, 1115 IN HIDP_REPORT_TYPE ReportType, 1116 IN UCHAR ReportID, 1117 IN OUT PCHAR Report, 1118 IN ULONG ReportLength) 1119 { 1120 UNIMPLEMENTED; 1121 ASSERT(FALSE); 1122 return STATUS_NOT_IMPLEMENTED; 1123 } 1124 1125 #undef HidParser_GetValueCaps 1126 1127 HIDAPI 1128 NTSTATUS 1129 NTAPI 1130 HidParser_GetValueCaps( 1131 IN PVOID CollectionContext, 1132 HIDP_REPORT_TYPE ReportType, 1133 PHIDP_VALUE_CAPS ValueCaps, 1134 PULONG ValueCapsLength) 1135 { 1136 UNIMPLEMENTED; 1137 ASSERT(FALSE); 1138 return STATUS_NOT_IMPLEMENTED; 1139 } 1140