2 * PROJECT: ReactOS HID Parser Library
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: lib/drivers/hidparser/parser.c
7 * Michael Martin (michael.martin@reactos.org)
8 * Johannes Anderwald (johannes.anderwald@reactos.org)
16 static UCHAR ItemSize
[4] = { 0, 1, 2, 4 };
19 HidParser_DeleteReport(
20 IN PHID_REPORT Report
)
28 HidParser_FreeCollection(
29 IN PHID_COLLECTION Collection
)
37 HidParser_AllocateCollection(
38 IN PHID_COLLECTION ParentCollection
,
40 IN PLOCAL_ITEM_STATE LocalItemState
,
41 OUT PHID_COLLECTION
* OutCollection
)
43 PHID_COLLECTION Collection
;
44 USAGE_VALUE UsageValue
;
47 // first allocate the collection
49 Collection
= (PHID_COLLECTION
)AllocFunction(sizeof(HID_COLLECTION
));
55 return HIDP_STATUS_INTERNAL_ERROR
;
61 Collection
->Root
= ParentCollection
;
62 Collection
->Type
= Type
;
63 Collection
->StringID
= LocalItemState
->StringIndex
;
64 Collection
->PhysicalID
= LocalItemState
->DesignatorIndex
;
69 ASSERT(LocalItemState
);
70 ASSERT(LocalItemState
->UsageStack
);
72 if (LocalItemState
->UsageStackUsed
> 0)
75 // usage value from first local stack item
77 UsageValue
.u
.Extended
= LocalItemState
->UsageStack
[0].u
.Extended
;
79 else if (LocalItemState
->UsageMinimumSet
)
82 // use value from minimum
84 UsageValue
.u
.Extended
= LocalItemState
->UsageMinimum
.u
.Extended
;
86 else if (LocalItemState
->UsageMaximumSet
)
89 // use value from maximum
91 UsageValue
.u
.Extended
= LocalItemState
->UsageMaximum
.u
.Extended
;
93 else if (Type
== COLLECTION_LOGICAL
)
98 UsageValue
.u
.Extended
= 0;
105 DebugFunction("HIDPARSE] No usage set\n");
106 UsageValue
.u
.Extended
= 0;
112 Collection
->Usage
= UsageValue
.u
.Extended
;
117 *OutCollection
= Collection
;
122 return HIDP_STATUS_SUCCESS
;
126 HidParser_AddCollection(
127 IN PHID_COLLECTION CurrentCollection
,
128 IN PHID_COLLECTION NewCollection
)
130 PHID_COLLECTION
* NewAllocCollection
;
131 ULONG CollectionCount
;
134 // increment collection array
136 CollectionCount
= CurrentCollection
->NodeCount
+ 1;
139 // allocate new collection
141 NewAllocCollection
= (PHID_COLLECTION
*)AllocFunction(sizeof(PHID_COLLECTION
) * CollectionCount
);
142 if (!NewAllocCollection
)
147 return HIDP_STATUS_INTERNAL_ERROR
;
150 if (CurrentCollection
->NodeCount
)
155 CopyFunction(NewAllocCollection
, CurrentCollection
->Nodes
, CurrentCollection
->NodeCount
* sizeof(PHID_COLLECTION
));
160 FreeFunction(CurrentCollection
->Nodes
);
166 NewAllocCollection
[CurrentCollection
->NodeCount
] = (struct __HID_COLLECTION__
*)NewCollection
;
172 CurrentCollection
->Nodes
= NewAllocCollection
;
173 CurrentCollection
->NodeCount
++;
178 return HIDP_STATUS_SUCCESS
;
182 HidParser_FindReportInCollection(
183 IN PHID_COLLECTION Collection
,
186 OUT PHID_REPORT
*OutReport
)
192 // search in local list
194 for(Index
= 0; Index
< Collection
->ReportCount
; Index
++)
196 if (Collection
->Reports
[Index
]->Type
== ReportType
&& Collection
->Reports
[Index
]->ReportID
== ReportID
)
201 *OutReport
= Collection
->Reports
[Index
];
202 return HIDP_STATUS_SUCCESS
;
207 // search in sub collections
209 for(Index
= 0; Index
< Collection
->NodeCount
; Index
++)
211 Status
= HidParser_FindReportInCollection(Collection
->Nodes
[Index
], ReportType
, ReportID
, OutReport
);
212 if (Status
== HIDP_STATUS_SUCCESS
)
217 // no such report found
220 return HIDP_STATUS_REPORT_DOES_NOT_EXIST
;
225 HidParser_FindReport(
226 IN PHID_PARSER_CONTEXT ParserContext
,
229 OUT PHID_REPORT
*OutReport
)
232 // search in current top level collection
234 return HidParser_FindReportInCollection(ParserContext
->RootCollection
->Nodes
[ParserContext
->RootCollection
->NodeCount
-1], ReportType
, ReportID
, OutReport
);
238 HidParser_AllocateReport(
241 OUT PHID_REPORT
*OutReport
)
248 Report
= (PHID_REPORT
)AllocFunction(sizeof(HID_REPORT
));
254 return HIDP_STATUS_INTERNAL_ERROR
;
260 Report
->ReportID
= ReportID
;
261 Report
->Type
= ReportType
;
267 return HIDP_STATUS_SUCCESS
;
271 HidParser_AddReportToCollection(
272 IN PHID_PARSER_CONTEXT ParserContext
,
273 IN PHID_COLLECTION CurrentCollection
,
274 IN PHID_REPORT NewReport
)
276 PHID_REPORT
* NewReportArray
;
279 // allocate new report array
281 NewReportArray
= (PHID_REPORT
*)AllocFunction(sizeof(PHID_REPORT
) * (CurrentCollection
->ReportCount
+ 1));
287 return HIDP_STATUS_INTERNAL_ERROR
;
290 if (CurrentCollection
->ReportCount
)
293 // copy old array contents
295 CopyFunction(NewReportArray
, CurrentCollection
->Reports
, sizeof(PHID_REPORT
) * CurrentCollection
->ReportCount
);
300 FreeFunction(CurrentCollection
->Reports
);
306 NewReportArray
[CurrentCollection
->ReportCount
] = NewReport
;
307 CurrentCollection
->Reports
= NewReportArray
;
308 CurrentCollection
->ReportCount
++;
311 // completed successfully
313 return HIDP_STATUS_SUCCESS
;
318 IN PHID_PARSER_CONTEXT ParserContext
,
319 IN PHID_COLLECTION Collection
,
322 IN UCHAR CreateIfNotExists
,
323 OUT PHID_REPORT
*OutReport
)
328 // try finding existing report
330 Status
= HidParser_FindReport(ParserContext
, ReportType
, ReportID
, OutReport
);
331 if (Status
== HIDP_STATUS_SUCCESS
|| CreateIfNotExists
== FALSE
)
340 // allocate new report
342 Status
= HidParser_AllocateReport(ReportType
, ReportID
, OutReport
);
343 if (Status
!= HIDP_STATUS_SUCCESS
)
346 // failed to allocate report
354 Status
= HidParser_AddReportToCollection(ParserContext
, Collection
, *OutReport
);
355 if (Status
!= HIDP_STATUS_SUCCESS
)
358 // failed to allocate report
360 FreeFunction(*OutReport
);
370 HidParser_ReserveReportItems(
371 IN PHID_REPORT Report
,
372 IN ULONG ReportCount
,
373 OUT PHID_REPORT
*OutReport
)
375 PHID_REPORT NewReport
;
378 if (Report
->ItemCount
+ ReportCount
<= Report
->ItemAllocated
)
381 // space is already allocated
384 return HIDP_STATUS_SUCCESS
;
390 OldSize
= sizeof(HID_REPORT
) + (Report
->ItemCount
) * sizeof(HID_REPORT_ITEM
);
391 Size
= ReportCount
* sizeof(HID_REPORT_ITEM
);
396 NewReport
= (PHID_REPORT
)AllocFunction(Size
+ OldSize
);
402 return HIDP_STATUS_INTERNAL_ERROR
;
409 CopyFunction(NewReport
, Report
, OldSize
);
412 // increase array size
414 NewReport
->ItemAllocated
+= ReportCount
;
419 *OutReport
= NewReport
;
422 // completed sucessfully
424 return HIDP_STATUS_SUCCESS
;
431 OUT PULONG NewMinimum
,
432 OUT PULONG NewMaximum
)
434 ULONG Mask
= 0x80000000;
437 for (Index
= 0; Index
< 4; Index
++)
451 *NewMinimum
= Minimum
;
452 *NewMaximum
= Maximum
;
456 HidParser_InitReportItem(
457 IN PHID_REPORT Report
,
458 IN PHID_REPORT_ITEM ReportItem
,
459 IN PGLOBAL_ITEM_STATE GlobalItemState
,
460 IN PLOCAL_ITEM_STATE LocalItemState
,
461 IN PMAIN_ITEM_DATA ItemData
,
462 IN ULONG ReportItemIndex
)
464 ULONG LogicalMinimum
;
465 ULONG LogicalMaximum
;
466 ULONG PhysicalMinimum
;
467 ULONG PhysicalMaximum
;
470 USAGE_VALUE UsageValue
;
473 // get logical bounds
475 LogicalMinimum
= GlobalItemState
->LogicalMinimum
;
476 LogicalMaximum
= GlobalItemState
->LogicialMaximum
;
477 if (LogicalMinimum
> LogicalMaximum
)
482 HidParser_SignRange(LogicalMinimum
, LogicalMaximum
, &LogicalMinimum
, &LogicalMaximum
);
484 //ASSERT(LogicalMinimum <= LogicalMaximum);
487 // get physical bounds
489 PhysicalMinimum
= GlobalItemState
->PhysicalMinimum
;
490 PhysicalMaximum
= GlobalItemState
->PhysicalMaximum
;
491 if (PhysicalMinimum
> PhysicalMaximum
)
496 HidParser_SignRange(PhysicalMinimum
, PhysicalMaximum
, &PhysicalMinimum
, &PhysicalMaximum
);
498 //ASSERT(PhysicalMinimum <= PhysicalMaximum);
505 if (ItemData
->ArrayVariable
== FALSE
)
510 UsageMinimum
= LocalItemState
->UsageMinimum
.u
.Extended
;
511 UsageMaximum
= LocalItemState
->UsageMaximum
.u
.Extended
;
516 // get usage value from stack
518 if (ReportItemIndex
< LocalItemState
->UsageStackUsed
)
523 UsageValue
= LocalItemState
->UsageStack
[ReportItemIndex
];
528 // get usage minimum from local state
530 UsageValue
= LocalItemState
->UsageMinimum
;
535 UsageValue
.u
.Extended
+= ReportItemIndex
;
537 if (LocalItemState
->UsageMaximumSet
)
539 if (UsageValue
.u
.Extended
> LocalItemState
->UsageMaximum
.u
.Extended
)
544 UsageValue
.u
.Extended
= LocalItemState
->UsageMaximum
.u
.Extended
;
550 // usage usage bounds
552 UsageMinimum
= UsageMaximum
= UsageValue
.u
.Extended
;
556 // now store all values
558 ReportItem
->ByteOffset
= (Report
->ReportSize
/ 8);
559 ReportItem
->Shift
= (Report
->ReportSize
% 8);
560 ReportItem
->Mask
= ~(0xFFFFFFFF << GlobalItemState
->ReportSize
);
561 ReportItem
->BitCount
= GlobalItemState
->ReportSize
;
562 ReportItem
->HasData
= (ItemData
->DataConstant
== FALSE
);
563 ReportItem
->Array
= (ItemData
->ArrayVariable
== 0);
564 ReportItem
->Relative
= (ItemData
->Relative
!= FALSE
);
565 ReportItem
->Minimum
= LogicalMinimum
;
566 ReportItem
->Maximum
= LogicalMaximum
;
567 ReportItem
->UsageMinimum
= UsageMinimum
;
568 ReportItem
->UsageMaximum
= UsageMaximum
;
571 // increment report size
573 Report
->ReportSize
+= GlobalItemState
->ReportSize
;
576 // completed successfully
578 return HIDP_STATUS_SUCCESS
;
582 HidParser_UpdateCurrentCollectionReport(
583 IN PHID_COLLECTION Collection
,
584 IN PHID_REPORT Report
,
585 IN PHID_REPORT NewReport
)
588 BOOLEAN Found
= FALSE
, TempFound
;
591 // search in local list
593 for(Index
= 0; Index
< Collection
->ReportCount
; Index
++)
595 if (Collection
->Reports
[Index
] == Report
)
600 Collection
->Reports
[Index
] = NewReport
;
606 // search in sub collections
608 for(Index
= 0; Index
< Collection
->NodeCount
; Index
++)
613 TempFound
= HidParser_UpdateCurrentCollectionReport(Collection
->Nodes
[Index
], Report
, NewReport
);
617 // the same report should not be found in different collections
619 ASSERT(Found
== FALSE
);
631 HidParser_UpdateCollectionReport(
632 IN PHID_PARSER_CONTEXT ParserContext
,
633 IN PHID_REPORT Report
,
634 IN PHID_REPORT NewReport
)
637 // update in current collection
639 return HidParser_UpdateCurrentCollectionReport(ParserContext
->RootCollection
->Nodes
[ParserContext
->RootCollection
->NodeCount
-1], Report
, NewReport
);
644 HidParser_AddMainItem(
645 IN PHID_PARSER_CONTEXT ParserContext
,
646 IN PHID_REPORT Report
,
647 IN PGLOBAL_ITEM_STATE GlobalItemState
,
648 IN PLOCAL_ITEM_STATE LocalItemState
,
649 IN PMAIN_ITEM_DATA ItemData
,
650 IN PHID_COLLECTION Collection
)
654 PHID_REPORT NewReport
;
658 // first grow report item array
660 Status
= HidParser_ReserveReportItems(Report
, GlobalItemState
->ReportCount
, &NewReport
);
661 if (Status
!= HIDP_STATUS_SUCCESS
)
664 // failed to allocate memory
669 if (NewReport
!= Report
)
672 // update current top level collection
674 Found
= HidParser_UpdateCollectionReport(ParserContext
, Report
, NewReport
);
681 ASSERT(NewReport
->ItemCount
+ GlobalItemState
->ReportCount
<= NewReport
->ItemAllocated
);
683 for(Index
= 0; Index
< GlobalItemState
->ReportCount
; Index
++)
685 Status
= HidParser_InitReportItem(NewReport
, &NewReport
->Items
[NewReport
->ItemCount
], GlobalItemState
, LocalItemState
, ItemData
, Index
);
686 if (Status
!= HIDP_STATUS_SUCCESS
)
689 // failed to init report item
695 // increment report item count
697 NewReport
->ItemCount
++;
703 return HIDP_STATUS_SUCCESS
;
707 HidParser_ParseReportDescriptor(
708 IN PUCHAR ReportDescriptor
,
709 IN ULONG ReportLength
,
710 OUT PVOID
*OutParser
)
712 PGLOBAL_ITEM_STATE LinkedGlobalItemState
, NextLinkedGlobalItemState
;
714 PUSAGE_VALUE NewUsageStack
, UsageValue
;
716 PHID_COLLECTION CurrentCollection
, NewCollection
;
717 PUCHAR CurrentOffset
, ReportEnd
;
718 PITEM_PREFIX CurrentItem
;
719 ULONG CurrentItemSize
;
720 PLONG_ITEM CurrentLongItem
;
721 PSHORT_ITEM CurrentShortItem
;
725 PMAIN_ITEM_DATA MainItemData
;
726 PHID_PARSER_CONTEXT ParserContext
;
728 CurrentOffset
= ReportDescriptor
;
729 ReportEnd
= ReportDescriptor
+ ReportLength
;
731 if (ReportDescriptor
>= ReportEnd
)
732 return HIDP_STATUS_USAGE_NOT_FOUND
;
737 ParserContext
= AllocFunction(sizeof(HID_PARSER_CONTEXT
));
739 return HIDP_STATUS_INTERNAL_ERROR
;
743 // allocate usage stack
745 ParserContext
->LocalItemState
.UsageStackAllocated
= 10;
746 ParserContext
->LocalItemState
.UsageStack
= (PUSAGE_VALUE
)AllocFunction(ParserContext
->LocalItemState
.UsageStackAllocated
* sizeof(USAGE_VALUE
));
747 if (!ParserContext
->LocalItemState
.UsageStack
)
752 FreeFunction(ParserContext
);
753 return HIDP_STATUS_INTERNAL_ERROR
;
757 // now allocate root collection
759 Status
= HidParser_AllocateCollection(NULL
, COLLECTION_LOGICAL
, &ParserContext
->LocalItemState
, &ParserContext
->RootCollection
);
760 if (Status
!= HIDP_STATUS_SUCCESS
)
765 FreeFunction(ParserContext
->LocalItemState
.UsageStack
);
766 ParserContext
->LocalItemState
.UsageStack
= NULL
;
767 FreeFunction(ParserContext
);
768 return HIDP_STATUS_INTERNAL_ERROR
;
774 CurrentCollection
= ParserContext
->RootCollection
;
781 CurrentItem
= (PITEM_PREFIX
)CurrentOffset
;
786 CurrentItemSize
= ItemSize
[CurrentItem
->Size
];
789 if (CurrentItem
->Type
== ITEM_TYPE_LONG
)
792 // increment item size with size of data item
794 CurrentLongItem
= (PLONG_ITEM
)CurrentItem
;
795 CurrentItemSize
+= CurrentLongItem
->DataSize
;
802 CurrentShortItem
= (PSHORT_ITEM
)CurrentItem
;
805 // get associated data
807 //ASSERT(CurrentItemSize == 1 || CurrentItemSize == 2 || CurrentItemSize == 4);
808 if (CurrentItemSize
== 1)
809 Data
= CurrentShortItem
->Data
.UData8
[0];
810 else if (CurrentItemSize
== 2)
811 Data
= CurrentShortItem
->Data
.UData16
[0];
812 else if (CurrentItemSize
== 4)
813 Data
= CurrentShortItem
->Data
.UData32
;
819 //DebugFunction("CurrentItem invalid item size %lu\n", CurrentItemSize);
823 DebugFunction("Tag %x Type %x Size %x Offset %lu Length %lu\n", CurrentItem
->Tag
, CurrentItem
->Type
, CurrentItem
->Size
, ((ULONG_PTR
)CurrentItem
- (ULONG_PTR
)ReportDescriptor
), ReportLength
);
827 ASSERT(CurrentItem
->Type
>= ITEM_TYPE_MAIN
&& CurrentItem
->Type
<= ITEM_TYPE_LONG
);
828 switch(CurrentItem
->Type
)
832 // preprocess the local state if relevant (usages for
833 // collections and report items)
834 if (CurrentItem
->Tag
!= ITEM_TAG_MAIN_END_COLLECTION
)
836 // make all usages extended for easier later processing
837 for (Index
= 0; Index
< ParserContext
->LocalItemState
.UsageStackUsed
; Index
++)
840 // is it already extended
842 if (ParserContext
->LocalItemState
.UsageStack
[Index
].IsExtended
)
848 ParserContext
->LocalItemState
.UsageStack
[Index
].u
.s
.UsagePage
= ParserContext
->GlobalItemState
.UsagePage
;
849 ParserContext
->LocalItemState
.UsageStack
[Index
].IsExtended
= TRUE
;
852 if (!ParserContext
->LocalItemState
.UsageMinimum
.IsExtended
) {
853 // the specs say if one of them is extended they must
854 // both be extended, so if the minimum isn't, the
855 // maximum mustn't either.
856 ParserContext
->LocalItemState
.UsageMinimum
.u
.s
.UsagePage
857 = ParserContext
->LocalItemState
.UsageMaximum
.u
.s
.UsagePage
858 = ParserContext
->GlobalItemState
.UsagePage
;
859 ParserContext
->LocalItemState
.UsageMinimum
.IsExtended
860 = ParserContext
->LocalItemState
.UsageMaximum
.IsExtended
= TRUE
;
863 //LocalItemState.usage_stack = usageStack;
864 //ParserContext->LocalItemState.UsageStackUsed = UsageStackUsed;
867 if (CurrentItem
->Tag
== ITEM_TAG_MAIN_COLLECTION
) {
870 // allocate new collection
872 Status
= HidParser_AllocateCollection(CurrentCollection
, (UCHAR
)Data
, &ParserContext
->LocalItemState
, &NewCollection
);
873 ASSERT(Status
== HIDP_STATUS_SUCCESS
);
876 // add new collection to current collection
878 Status
= HidParser_AddCollection(CurrentCollection
, NewCollection
);
879 ASSERT(Status
== HIDP_STATUS_SUCCESS
);
882 // make new collection current
884 CurrentCollection
= NewCollection
;
886 else if (CurrentItem
->Tag
== ITEM_TAG_MAIN_END_COLLECTION
)
889 // assert on ending the root collection
891 ASSERT(CurrentCollection
!= ParserContext
->RootCollection
);
894 // use parent of current collection
896 CurrentCollection
= CurrentCollection
->Root
;
897 ASSERT(CurrentCollection
);
901 ReportType
= HID_REPORT_TYPE_ANY
;
903 switch (CurrentItem
->Tag
) {
904 case ITEM_TAG_MAIN_INPUT
:
905 ReportType
= HID_REPORT_TYPE_INPUT
;
908 case ITEM_TAG_MAIN_OUTPUT
:
909 ReportType
= HID_REPORT_TYPE_OUTPUT
;
912 case ITEM_TAG_MAIN_FEATURE
:
913 ReportType
= HID_REPORT_TYPE_FEATURE
;
917 DebugFunction("[HIDPARSE] Unknown ReportType Tag %x Type %x Size %x CurrentItemSize %x\n", CurrentItem
->Tag
, CurrentItem
->Type
, CurrentItem
->Size
, CurrentItemSize
);
922 if (ReportType
== HID_REPORT_TYPE_ANY
)
928 Status
= HidParser_GetReport(ParserContext
, CurrentCollection
, ReportType
, ParserContext
->GlobalItemState
.ReportId
, TRUE
, &Report
);
929 ASSERT(Status
== HIDP_STATUS_SUCCESS
);
931 // fill in a sensible default if the index isn't set
932 if (!ParserContext
->LocalItemState
.DesignatorIndexSet
) {
933 ParserContext
->LocalItemState
.DesignatorIndex
934 = ParserContext
->LocalItemState
.DesignatorMinimum
;
937 if (!ParserContext
->LocalItemState
.StringIndexSet
)
938 ParserContext
->LocalItemState
.StringIndex
= ParserContext
->LocalItemState
.StringMinimum
;
941 // get main item data
943 MainItemData
= (PMAIN_ITEM_DATA
)&Data
;
946 // add states & data to the report
948 Status
= HidParser_AddMainItem(ParserContext
, Report
, &ParserContext
->GlobalItemState
, &ParserContext
->LocalItemState
, MainItemData
, CurrentCollection
);
949 ASSERT(Status
== HIDP_STATUS_SUCCESS
);
955 Index
= ParserContext
->LocalItemState
.UsageStackAllocated
;
956 NewUsageStack
= ParserContext
->LocalItemState
.UsageStack
;
959 // reset the local item state and clear the usage stack
961 ZeroFunction(&ParserContext
->LocalItemState
, sizeof(LOCAL_ITEM_STATE
));
966 ParserContext
->LocalItemState
.UsageStack
= NewUsageStack
;
967 ParserContext
->LocalItemState
.UsageStackAllocated
= Index
;
970 case ITEM_TYPE_GLOBAL
:
972 switch (CurrentItem
->Tag
) {
973 case ITEM_TAG_GLOBAL_USAGE_PAGE
:
974 DebugFunction("[HIDPARSE] ITEM_TAG_GLOBAL_USAGE_PAGE %x\n", Data
);
975 ParserContext
->GlobalItemState
.UsagePage
= Data
;
977 case ITEM_TAG_GLOBAL_LOGICAL_MINIMUM
:
978 DebugFunction("[HIDPARSE] ITEM_TAG_GLOBAL_LOGICAL_MINIMUM %x\n", Data
);
979 ParserContext
->GlobalItemState
.LogicalMinimum
= Data
;
982 case ITEM_TAG_GLOBAL_LOGICAL_MAXIMUM
:
983 DebugFunction("[HIDPARSE] ITEM_TAG_GLOBAL_LOCAL_MAXIMUM %x\n", Data
);
984 ParserContext
->GlobalItemState
.LogicialMaximum
= Data
;
987 case ITEM_TAG_GLOBAL_PHYSICAL_MINIMUM
:
988 DebugFunction("[HIDPARSE] ITEM_TAG_GLOBAL_PHYSICAL_MINIMUM %x\n", Data
);
989 ParserContext
->GlobalItemState
.PhysicalMinimum
= Data
;
992 case ITEM_TAG_GLOBAL_PHYSICAL_MAXIMUM
:
993 DebugFunction("[HIDPARSE] ITEM_TAG_GLOBAL_PHYSICAL_MAXIMUM %x\n", Data
);
994 ParserContext
->GlobalItemState
.PhysicalMaximum
= Data
;
997 case ITEM_TAG_GLOBAL_UNIT_EXPONENT
:
998 DebugFunction("[HIDPARSE] ITEM_TAG_GLOBAL_REPORT_UNIT_EXPONENT %x\n", Data
);
999 ParserContext
->GlobalItemState
.UnitExponent
= Data
;
1002 case ITEM_TAG_GLOBAL_UNIT
:
1003 DebugFunction("[HIDPARSE] ITEM_TAG_GLOBAL_REPORT_UNIT %x\n", Data
);
1004 ParserContext
->GlobalItemState
.Unit
= Data
;
1007 case ITEM_TAG_GLOBAL_REPORT_SIZE
:
1008 DebugFunction("[HIDPARSE] ITEM_TAG_GLOBAL_REPORT_SIZE %x\n", Data
);
1009 ParserContext
->GlobalItemState
.ReportSize
= Data
;
1012 case ITEM_TAG_GLOBAL_REPORT_ID
:
1013 DebugFunction("[HIDPARSE] ITEM_TAG_GLOBAL_REPORT_ID %x\n", Data
);
1014 ParserContext
->GlobalItemState
.ReportId
= Data
;
1015 ParserContext
->UseReportIDs
= TRUE
;
1018 case ITEM_TAG_GLOBAL_REPORT_COUNT
:
1019 DebugFunction("[HIDPARSE] ITEM_TAG_GLOBAL_REPORT_COUNT %x\n", Data
);
1020 ParserContext
->GlobalItemState
.ReportCount
= Data
;
1023 case ITEM_TAG_GLOBAL_PUSH
:
1025 DebugFunction("[HIDPARSE] ITEM_TAG_GLOBAL_PUSH\n");
1027 // allocate global item state
1029 LinkedGlobalItemState
= (PGLOBAL_ITEM_STATE
)AllocFunction(sizeof(GLOBAL_ITEM_STATE
));
1030 ASSERT(LinkedGlobalItemState
);
1033 // copy global item state
1035 CopyFunction(LinkedGlobalItemState
, &ParserContext
->GlobalItemState
, sizeof(GLOBAL_ITEM_STATE
));
1038 // store pushed item in link member
1040 ParserContext
->GlobalItemState
.Next
= (struct __GLOBAL_ITEM_STATE__
*)LinkedGlobalItemState
;
1043 case ITEM_TAG_GLOBAL_POP
:
1045 DebugFunction("[HIDPARSE] ITEM_TAG_GLOBAL_POP\n");
1046 if (ParserContext
->GlobalItemState
.Next
== NULL
)
1058 LinkedGlobalItemState
= (PGLOBAL_ITEM_STATE
)ParserContext
->GlobalItemState
.Next
;
1061 // replace current item with linked one
1063 CopyFunction(&ParserContext
->GlobalItemState
, LinkedGlobalItemState
, sizeof(GLOBAL_ITEM_STATE
));
1068 FreeFunction(LinkedGlobalItemState
);
1074 // unknown / unsupported tag
1082 case ITEM_TYPE_LOCAL
:
1084 switch (CurrentItem
->Tag
)
1086 case ITEM_TAG_LOCAL_USAGE
:
1088 if (ParserContext
->LocalItemState
.UsageStackUsed
>= ParserContext
->LocalItemState
.UsageStackAllocated
)
1091 // increment stack size
1093 ParserContext
->LocalItemState
.UsageStackAllocated
+= 10;
1096 // build new usage stack
1098 NewUsageStack
= (PUSAGE_VALUE
)AllocFunction(sizeof(USAGE_VALUE
) * ParserContext
->LocalItemState
.UsageStackAllocated
);
1099 ASSERT(NewUsageStack
);
1102 // copy old usage stack
1104 CopyFunction(NewUsageStack
, ParserContext
->LocalItemState
.UsageStack
, sizeof(USAGE_VALUE
) * (ParserContext
->LocalItemState
.UsageStackAllocated
- 10));
1107 // free old usage stack
1109 FreeFunction(ParserContext
->LocalItemState
.UsageStack
);
1112 // replace with new usage stack
1114 ParserContext
->LocalItemState
.UsageStack
= NewUsageStack
;
1118 // get fresh usage value
1120 UsageValue
= &ParserContext
->LocalItemState
.UsageStack
[ParserContext
->LocalItemState
.UsageStackUsed
];
1125 UsageValue
->IsExtended
= CurrentItemSize
== sizeof(ULONG
);
1126 UsageValue
->u
.Extended
= Data
;
1129 // increment usage stack usage count
1131 ParserContext
->LocalItemState
.UsageStackUsed
++;
1135 case ITEM_TAG_LOCAL_USAGE_MINIMUM
:
1136 DebugFunction("[HIDPARSE] ITEM_TAG_LOCAL_USAGE_MINIMUM Data %x\n", Data
);
1137 ParserContext
->LocalItemState
.UsageMinimum
.u
.Extended
= Data
;
1138 ParserContext
->LocalItemState
.UsageMinimum
.IsExtended
1139 = CurrentItemSize
== sizeof(ULONG
);
1140 ParserContext
->LocalItemState
.UsageMinimumSet
= TRUE
;
1143 case ITEM_TAG_LOCAL_USAGE_MAXIMUM
:
1144 DebugFunction("[HIDPARSE] ITEM_TAG_LOCAL_USAGE_MAXIMUM Data %x ItemSize %x %x\n", Data
, CurrentItemSize
, CurrentItem
->Size
);
1145 ParserContext
->LocalItemState
.UsageMaximum
.u
.Extended
= Data
;
1146 ParserContext
->LocalItemState
.UsageMaximum
.IsExtended
1147 = CurrentItemSize
== sizeof(ULONG
);
1148 ParserContext
->LocalItemState
.UsageMaximumSet
= TRUE
;
1151 case ITEM_TAG_LOCAL_DESIGNATOR_INDEX
:
1152 DebugFunction("[HIDPARSE] ITEM_TAG_LOCAL_DESIGNATOR_INDEX Data %x\n", Data
);
1153 ParserContext
->LocalItemState
.DesignatorIndex
= Data
;
1154 ParserContext
->LocalItemState
.DesignatorIndexSet
= TRUE
;
1157 case ITEM_TAG_LOCAL_DESIGNATOR_MINIMUM
:
1158 DebugFunction("[HIDPARSE] ITEM_TAG_LOCAL_DESIGNATOR_MINIMUM Data %x\n", Data
);
1159 ParserContext
->LocalItemState
.DesignatorMinimum
= Data
;
1162 case ITEM_TAG_LOCAL_DESIGNATOR_MAXIMUM
:
1163 DebugFunction("[HIDPARSE] ITEM_TAG_LOCAL_DESIGNATOR_MAXIMUM Data %x\n", Data
);
1164 ParserContext
->LocalItemState
.DesignatorMaximum
= Data
;
1167 case ITEM_TAG_LOCAL_STRING_INDEX
:
1168 DebugFunction("[HIDPARSE] ITEM_TAG_LOCAL_STRING_INDEX Data %x\n", Data
);
1169 ParserContext
->LocalItemState
.StringIndex
= Data
;
1170 ParserContext
->LocalItemState
.StringIndexSet
= TRUE
;
1173 case ITEM_TAG_LOCAL_STRING_MINIMUM
:
1174 DebugFunction("[HIDPARSE] ITEM_TAG_LOCAL_STRING_MINIMUM Data %x\n", Data
);
1175 ParserContext
->LocalItemState
.StringMinimum
= Data
;
1178 case ITEM_TAG_LOCAL_STRING_MAXIMUM
:
1179 DebugFunction("[HIDPARSE] ITEM_TAG_LOCAL_STRING_MAXIMUM Data %x\n", Data
);
1180 ParserContext
->LocalItemState
.StringMaximum
= Data
;
1184 DebugFunction("Unknown Local Item Tag %x\n", CurrentItem
->Tag
);
1191 case ITEM_TYPE_LONG
:
1193 CurrentLongItem
= (PLONG_ITEM
)CurrentItem
;
1194 DebugFunction("Unsupported ITEM_TYPE_LONG Tag %x\n", CurrentLongItem
->LongItemTag
);
1200 // move to next item
1202 CurrentOffset
+= CurrentItemSize
+ sizeof(ITEM_PREFIX
);
1204 }while (CurrentOffset
< ReportEnd
);
1208 // cleanup global stack
1210 LinkedGlobalItemState
= (PGLOBAL_ITEM_STATE
)ParserContext
->GlobalItemState
.Next
;
1211 while(LinkedGlobalItemState
!= NULL
)
1213 DebugFunction("[HIDPARSE] Freeing GlobalState %p\n", LinkedGlobalItemState
);
1215 // free global item state
1217 NextLinkedGlobalItemState
= (PGLOBAL_ITEM_STATE
)LinkedGlobalItemState
->Next
;
1222 FreeFunction(LinkedGlobalItemState
);
1225 // move to next global state
1227 LinkedGlobalItemState
= NextLinkedGlobalItemState
;
1233 FreeFunction(ParserContext
->LocalItemState
.UsageStack
);
1234 ParserContext
->LocalItemState
.UsageStack
= NULL
;
1239 *OutParser
= ParserContext
;
1244 return HIDP_STATUS_SUCCESS
;
1248 HidParser_GetCollection(
1249 PHID_PARSER_CONTEXT ParserContext
,
1250 IN ULONG CollectionNumber
)
1255 ASSERT(ParserContext
);
1256 ASSERT(ParserContext
->RootCollection
);
1257 ASSERT(ParserContext
->RootCollection
->NodeCount
);
1260 // is collection index out of bounds
1262 if (CollectionNumber
< ParserContext
->RootCollection
->NodeCount
)
1267 return ParserContext
->RootCollection
->Nodes
[CollectionNumber
];
1271 // no such collection
1273 DebugFunction("HIDPARSE] No such collection %lu\n", CollectionNumber
);
1279 HidParser_NumberOfTopCollections(
1282 PHID_PARSER_CONTEXT ParserContext
;
1285 // get parser context
1287 ParserContext
= (PHID_PARSER_CONTEXT
)ParserCtx
;
1292 ASSERT(ParserContext
);
1293 ASSERT(ParserContext
->RootCollection
);
1294 ASSERT(ParserContext
->RootCollection
->NodeCount
);
1297 // number of top collections
1299 return ParserContext
->RootCollection
->NodeCount
;
1303 HidParser_BuildContext(
1304 IN PVOID ParserContext
,
1305 IN ULONG CollectionIndex
,
1306 IN ULONG ContextSize
,
1307 OUT PVOID
*CollectionContext
)
1309 PHID_COLLECTION Collection
;
1314 // lets get the collection
1316 Collection
= HidParser_GetCollection((PHID_PARSER_CONTEXT
)ParserContext
, CollectionIndex
);
1320 // lets allocate the context
1322 Context
= AllocFunction(ContextSize
);
1323 if (Context
== NULL
)
1328 return HIDP_STATUS_INTERNAL_ERROR
;
1332 // lets build the context
1334 Status
= HidParser_BuildCollectionContext(Collection
, Context
, ContextSize
);
1335 if (Status
== HIDP_STATUS_SUCCESS
)
1340 *CollectionContext
= Context
;
1351 HidParser_GetContextSize(
1352 IN PVOID ParserContext
,
1353 IN ULONG CollectionIndex
)
1355 PHID_COLLECTION Collection
;
1359 // lets get the collection
1361 Collection
= HidParser_GetCollection((PHID_PARSER_CONTEXT
)ParserContext
, CollectionIndex
);
1366 Size
= HidParser_CalculateContextSize(Collection
);