[HIDPARSER]
authorJohannes Anderwald <johannes.anderwald@reactos.org>
Tue, 31 Jan 2012 16:19:33 +0000 (16:19 +0000)
committerJohannes Anderwald <johannes.anderwald@reactos.org>
Tue, 31 Jan 2012 16:19:33 +0000 (16:19 +0000)
- Rewrite hidparser so that it support multiple top level collections
- Add support for flat collection context meaning all context structures are aligned in after each other. The reason this is required is that usermode hid.dll will access the same structure and thus can't use kernel pointers. User mode hid.dll is used to support keyboard with custom keys (for example search key, email key etc)

svn path=/branches/usb-bringup-trunk/; revision=55353

drivers/hid/hidparse/hidparse.c
drivers/usb/usbd/usbd.c
lib/drivers/hidparser/CMakeLists.txt
lib/drivers/hidparser/api.c
lib/drivers/hidparser/context.c [new file with mode: 0644]
lib/drivers/hidparser/hidparser.c
lib/drivers/hidparser/hidparser.h
lib/drivers/hidparser/parser.c
lib/drivers/hidparser/parser.h

index 9e5c6af..0cea35a 100644 (file)
@@ -93,7 +93,7 @@ HidP_FreeCollectionDescription (
     //
     // init parser
     //
-    HidParser_InitParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, NULL, &Parser);
+    HidParser_InitParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, &Parser);
 
     //
     // free collection
@@ -114,12 +114,12 @@ HidP_GetCaps(
     //
     // init parser
     //
-    HidParser_InitParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, PreparsedData, &Parser);
+    HidParser_InitParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, &Parser);
 
     //
     // get caps
     //
-    return HidParser_GetCaps(&Parser, Capabilities);
+    return HidParser_GetCaps(&Parser, PreparsedData, Capabilities);
 }
 
 NTSTATUS
@@ -130,30 +130,17 @@ HidP_GetCollectionDescription(
     IN POOL_TYPE PoolType,
     OUT PHIDP_DEVICE_DESC DeviceDescription)
 {
-    PHID_PARSER Parser;
-    HIDPARSER_STATUS Status;
+    HID_PARSER Parser;
 
     //
-    // first allocate the parser
+    // init parser
     //
-    Status = HidParser_AllocateParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, &Parser);
-    if (Status != HIDPARSER_STATUS_SUCCESS)
-    {
-        //
-        // not enough memory
-        //
-        return STATUS_INSUFFICIENT_RESOURCES;
-    }
+    HidParser_InitParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, &Parser);
 
     //
     // get description;
     //
-    Status = HidParser_GetCollectionDescription(Parser, ReportDesc, DescLength, PoolType, DeviceDescription);
-
-    //
-    // FIXME parser memory leak
-    //
-    return Status;
+    return HidParser_GetCollectionDescription(&Parser, ReportDesc, DescLength, PoolType, DeviceDescription);
 }
 
 HIDAPI
@@ -174,13 +161,13 @@ HidP_MaxUsageListLength(
     //
     // init parser
     //
-    HidParser_InitParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, PreparsedData, &Parser);
+    HidParser_InitParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, &Parser);
 
 
     //
     // get usage length
     //
-    return HidParser_MaxUsageListLength(&Parser, ReportType, UsagePage);
+    return HidParser_MaxUsageListLength(&Parser, PreparsedData, ReportType, UsagePage);
 }
 
 HIDAPI
@@ -205,12 +192,12 @@ HidP_GetSpecificValueCaps(
     //
     // init parser
     //
-    HidParser_InitParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, PreparsedData, &Parser);
+    HidParser_InitParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, &Parser);
 
     //
     // get value caps
     //
-    return HidParser_GetSpecificValueCaps(&Parser, ReportType, UsagePage, LinkCollection, Usage, ValueCaps, ValueCapsLength);
+    return HidParser_GetSpecificValueCaps(&Parser, PreparsedData, ReportType, UsagePage, LinkCollection, Usage, ValueCaps, ValueCapsLength);
 }
 
 HIDAPI
@@ -236,12 +223,12 @@ HidP_GetUsages(
     //
     // init parser
     //
-    HidParser_InitParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, PreparsedData, &Parser);
+    HidParser_InitParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, &Parser);
 
     //
     // get usages
     //
-    return HidParser_GetUsages(&Parser, ReportType, UsagePage, LinkCollection, UsageList, UsageLength, Report, ReportLength);
+    return HidParser_GetUsages(&Parser, PreparsedData, ReportType, UsagePage, LinkCollection, UsageList, UsageLength, Report, ReportLength);
 }
 
 
@@ -311,12 +298,12 @@ HidP_GetScaledUsageValue(
     //
     // init parser
     //
-    HidParser_InitParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, PreparsedData, &Parser);
+    HidParser_InitParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, &Parser);
 
     //
     // get scaled usage value
     //
-    return HidParser_GetScaledUsageValue(&Parser, ReportType, UsagePage, LinkCollection, Usage, UsageValue, Report, ReportLength);
+    return HidParser_GetScaledUsageValue(&Parser, PreparsedData, ReportType, UsagePage, LinkCollection, Usage, UsageValue, Report, ReportLength);
 }
 
 HIDAPI
@@ -335,7 +322,7 @@ HidP_TranslateUsageAndPagesToI8042ScanCodes(
     //
     // init parser
     //
-    HidParser_InitParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, NULL, &Parser);
+    HidParser_InitParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, &Parser);
 
     //
     // translate usage pages
index 5732a34..a62ed93 100644 (file)
@@ -324,8 +324,8 @@ USBD_CreateConfigurationRequestEx(
          InterfaceList[InterfaceCount].InterfaceDescriptor != NULL;
          InterfaceCount++)
     {
-        UrbSize += sizeof(USBD_INTERFACE_INFORMATION);
-        UrbSize += (InterfaceList[InterfaceCount].InterfaceDescriptor->bNumEndpoints - 1) * sizeof(USBD_PIPE_INFORMATION);
+        UrbSize += FIELD_OFFSET(USBD_INTERFACE_INFORMATION, Pipes);
+        UrbSize += (InterfaceList[InterfaceCount].InterfaceDescriptor->bNumEndpoints) * sizeof(USBD_PIPE_INFORMATION);
     }
 
     UrbSize += sizeof(URB) + sizeof(USBD_INTERFACE_INFORMATION);
index 5d16301..6ab1276 100644 (file)
@@ -4,6 +4,7 @@ add_definitions(
     -DNDEBUG=1)
 
 list(APPEND SOURCE
+    context.c
     hidparser.c
     parser.c
     api.c)
index c2d781e..a3abc9f 100644 (file)
@@ -31,143 +31,9 @@ static ULONG KeyboardScanCodes[256] =
     150,158,159,128,136,177,178,176,142,152,173,140
 };
 
-
-
-ULONG
-HidParser_NumberOfTopCollections(
-    IN PHID_PARSER Parser)
-{
-    PHID_PARSER_CONTEXT ParserContext;
-
-    //
-    // get parser context
-    //
-    ParserContext = (PHID_PARSER_CONTEXT)Parser->ParserContext;
-
-    //
-    // sanity checks
-    //
-    ASSERT(ParserContext);
-    ASSERT(ParserContext->RootCollection);
-    ASSERT(ParserContext->RootCollection->NodeCount);
-
-    //
-    // number of top collections
-    //
-    return ParserContext->RootCollection->NodeCount;
-}
-
-PHID_COLLECTION
-HidParser_GetCollection(
-    IN PHID_PARSER Parser,
-    IN ULONG CollectionNumber)
-{
-    PHID_PARSER_CONTEXT ParserContext;
-
-    //
-    // get parser context
-    //
-    ParserContext = (PHID_PARSER_CONTEXT)Parser->ParserContext;
-
-    //
-    // sanity checks
-    //
-    ASSERT(ParserContext);
-    ASSERT(ParserContext->RootCollection);
-    ASSERT(ParserContext->RootCollection->NodeCount);
-
-    //
-    // is collection index out of bounds
-    //
-    if (CollectionNumber < ParserContext->RootCollection->NodeCount)
-    {
-        //
-        // valid collection
-        //
-        return ParserContext->RootCollection->Nodes[CollectionNumber];
-    }
-
-    //
-    // no such collection
-    //
-    Parser->Debug("HIDPARSE] No such collection %lu\n", CollectionNumber);
-    return NULL;
-}
-
-PHID_REPORT
-HidParser_GetReportInCollection(
-    PHID_COLLECTION Collection,
-    IN UCHAR ReportType)
-{
-    ULONG Index;
-    PHID_REPORT Report;
-
-    //
-    // search in local array
-    //
-    for(Index = 0; Index < Collection->ReportCount; Index++)
-    {
-        if (Collection->Reports[Index]->Type == ReportType)
-        {
-            //
-            // found report
-            //
-            return Collection->Reports[Index];
-        }
-    }
-
-    //
-    // search in local array
-    //
-    for(Index = 0; Index < Collection->NodeCount; Index++)
-    {
-        Report = HidParser_GetReportInCollection(Collection->Nodes[Index], ReportType);
-        if (Report)
-        {
-            //
-            // found report
-            //
-            return Report;
-        }
-    }
-
-    //
-    // not found
-    //
-    return NULL;
-}
-
-PHID_REPORT
-HidParser_GetReportByType(
-    IN PHID_PARSER Parser,
-    IN ULONG CollectionIndex,
-    IN UCHAR ReportType)
-{
-    PHID_COLLECTION Collection;
-
-    //
-    // find collection
-    //
-    Collection = HidParser_GetCollection(Parser, CollectionIndex);
-    if (!Collection)
-    {
-        //
-        // no such collection
-        //
-        ASSERT(FALSE);
-        return NULL;
-    }
-
-    //
-    // search report
-    //
-    return HidParser_GetReportInCollection(Collection, ReportType);
-}
-
 HIDPARSER_STATUS
 HidParser_GetCollectionUsagePage(
-    IN PHID_PARSER Parser,
-    IN ULONG CollectionIndex,
+    IN PVOID CollectionContext,
     OUT PUSHORT Usage,
     OUT PUSHORT UsagePage)
 {
@@ -176,7 +42,7 @@ HidParser_GetCollectionUsagePage(
     //
     // find collection
     //
-    Collection = HidParser_GetCollection(Parser, CollectionIndex);
+    Collection = HidParser_GetCollectionFromContext(CollectionContext);
     if (!Collection)
     {
         //
@@ -195,33 +61,16 @@ HidParser_GetCollectionUsagePage(
 
 ULONG
 HidParser_GetReportLength(
-    IN PHID_PARSER Parser,
-    IN ULONG CollectionIndex,
-    IN ULONG ReportType)
+    IN PVOID CollectionContext,
+    IN UCHAR ReportType)
 {
-    PHID_PARSER_CONTEXT ParserContext;
     PHID_REPORT Report;
     ULONG ReportLength;
 
-    //
-    // get parser context
-    //
-    ParserContext = (PHID_PARSER_CONTEXT)Parser->ParserContext;
-
-    //
-    // sanity checks
-    //
-    ASSERT(ParserContext);
-
-    //
-    // FIXME support multiple top collecions
-    //
-    ASSERT(ParserContext->RootCollection->NodeCount == 1);
-
     //
     // get first report
     //
-    Report = HidParser_GetReportByType(Parser, CollectionIndex, ReportType);
+    Report = HidParser_GetReportInCollection(CollectionContext, ReportType);
     if (!Report)
     {
         //
@@ -249,56 +98,17 @@ HidParser_GetReportLength(
     return ReportLength;
 }
 
-UCHAR
-HidParser_IsReportIDUsed(
-    IN PHID_PARSER Parser)
-{
-    PHID_PARSER_CONTEXT ParserContext;
-
-    //
-    // get parser context
-    //
-    ParserContext = (PHID_PARSER_CONTEXT)Parser->ParserContext;
-
-    //
-    // sanity checks
-    //
-    ASSERT(ParserContext);
-
-    //
-    // return flag
-    //
-    return ParserContext->UseReportIDs;
-}
-
 ULONG
 HidParser_GetReportItemCountFromReportType(
-    IN PHID_PARSER Parser,
-    IN ULONG CollectionIndex,
-    IN ULONG ReportType)
+    IN PVOID CollectionContext,
+    IN UCHAR ReportType)
 {
-    PHID_PARSER_CONTEXT ParserContext;
     PHID_REPORT Report;
 
-    //
-    // get parser context
-    //
-    ParserContext = (PHID_PARSER_CONTEXT)Parser->ParserContext;
-
-    //
-    // sanity checks
-    //
-    ASSERT(ParserContext);
-
-    //
-    // FIXME support multiple top collecions
-    //
-    ASSERT(ParserContext->RootCollection->NodeCount == 1);
-
     //
     // get report
     //
-    Report = HidParser_GetReportByType(Parser, CollectionIndex, ReportType);
+    Report = HidParser_GetReportInCollection(CollectionContext, ReportType);
     if (!Report)
     {
         //
@@ -316,35 +126,18 @@ HidParser_GetReportItemCountFromReportType(
 
 ULONG
 HidParser_GetReportItemTypeCountFromReportType(
-    IN PHID_PARSER Parser,
-    IN ULONG CollectionIndex,
-    IN ULONG ReportType,
+    IN PVOID CollectionContext,
+    IN UCHAR ReportType,
     IN ULONG bData)
 {
-    PHID_PARSER_CONTEXT ParserContext;
     ULONG Index;
     PHID_REPORT Report;
     ULONG ItemCount = 0;
 
-    //
-    // get parser context
-    //
-    ParserContext = (PHID_PARSER_CONTEXT)Parser->ParserContext;
-
-    //
-    // sanity checks
-    //
-    ASSERT(ParserContext);
-
-    //
-    // FIXME support multiple top collecions
-    //
-    ASSERT(ParserContext->RootCollection->NodeCount == 1);
-
     //
     // get report
     //
-    Report = HidParser_GetReportByType(Parser, CollectionIndex, ReportType);
+    Report = HidParser_GetReportInCollection(CollectionContext, ReportType);
     if (!Report)
     {
         //
@@ -361,14 +154,14 @@ HidParser_GetReportItemTypeCountFromReportType(
         //
         // check item type
         //
-        if (Report->Items[Index]->HasData && bData == TRUE)
+        if (Report->Items[Index].HasData && bData == TRUE)
         {
             //
             // found data item
             //
             ItemCount++;
         }
-        else if (Report->Items[Index]->HasData == FALSE && bData == FALSE)
+        else if (Report->Items[Index].HasData == FALSE && bData == FALSE)
         {
             //
             // found value item
@@ -383,85 +176,6 @@ HidParser_GetReportItemTypeCountFromReportType(
     return ItemCount;
 }
 
-ULONG
-HidParser_GetContextSize(
-    IN PHID_PARSER Parser,
-    IN ULONG CollectionIndex)
-{
-    //
-    // FIXME the context must contain all parsed info
-    //
-    return sizeof(HID_PARSER_CONTEXT);
-}
-
-VOID
-HidParser_FreeContext(
-    IN PHID_PARSER Parser,
-    IN PUCHAR Context,
-    IN ULONG ContextLength)
-{
-    //
-    // FIXME implement freeing of parsed info
-    //
-}
-
-HIDPARSER_STATUS
-HidParser_AllocateParser(
-    IN PHIDPARSER_ALLOC_FUNCTION AllocFunction,
-    IN PHIDPARSER_FREE_FUNCTION FreeFunction,
-    IN PHIDPARSER_ZERO_FUNCTION ZeroFunction,
-    IN PHIDPARSER_COPY_FUNCTION CopyFunction,
-    IN PHIDPARSER_DEBUG_FUNCTION DebugFunction,
-    OUT PHID_PARSER *OutParser)
-{
-    PHID_PARSER Parser;
-    PHID_PARSER_CONTEXT ParserContext;
-
-    //
-    // allocate 
-    //
-    Parser = (PHID_PARSER)AllocFunction(sizeof(HID_PARSER));
-    if (!Parser)
-    {
-        //
-        // no memory
-        //
-        return HIDPARSER_STATUS_INSUFFICIENT_RESOURCES;
-    }
-
-    //
-    // allocate parser context
-    //
-    ParserContext = (PHID_PARSER_CONTEXT)AllocFunction(sizeof(HID_PARSER_CONTEXT));
-    if (!ParserContext)
-    {
-        //
-        // no memory
-        //
-        FreeFunction(Parser);
-        return HIDPARSER_STATUS_INSUFFICIENT_RESOURCES;
-    }
-
-
-    //
-    // init parser
-    //
-    Parser->Alloc = AllocFunction;
-    Parser->Free = FreeFunction;
-    Parser->Zero = ZeroFunction;
-    Parser->Copy = CopyFunction;
-    Parser->Debug = DebugFunction;
-    Parser->ParserContext = ParserContext;
-
-    //
-    // store result
-    //
-    *OutParser = Parser;
-    //
-    // success
-    //
-    return HIDPARSER_STATUS_SUCCESS;
-}
 
 VOID
 HidParser_InitParser(
@@ -470,7 +184,6 @@ HidParser_InitParser(
     IN PHIDPARSER_ZERO_FUNCTION ZeroFunction,
     IN PHIDPARSER_COPY_FUNCTION CopyFunction,
     IN PHIDPARSER_DEBUG_FUNCTION DebugFunction,
-    IN PVOID ParserContext,
     OUT PHID_PARSER Parser)
 {
     Parser->Alloc = AllocFunction;
@@ -478,85 +191,23 @@ HidParser_InitParser(
     Parser->Zero = ZeroFunction;
     Parser->Copy = CopyFunction;
     Parser->Debug = DebugFunction;
-    Parser->ParserContext = ParserContext;
-}
-
-ULONG
-HidParser_GetCollectionCount(
-    IN PHID_COLLECTION Collection)
-{
-    ULONG Index;
-    ULONG Count = Collection->NodeCount;
-
-    for(Index = 0; Index < Collection->NodeCount; Index++)
-    {
-        //
-        // count collection for sub nodes
-        //
-        Count += HidParser_GetCollectionCount(Collection->Nodes[Index]);
-    }
-
-    //
-    // done
-    //
-    return Count;
-}
-
-ULONG
-HidParser_GetTotalCollectionCount(
-    IN PHID_PARSER Parser)
-{
-    PHID_PARSER_CONTEXT ParserContext;
-
-    //
-    // get parser context
-    //
-    ParserContext = (PHID_PARSER_CONTEXT)Parser->ParserContext;
-
-    //
-    // sanity check
-    //
-    ASSERT(ParserContext);
-    ASSERT(ParserContext->RootCollection);
-
-    //
-    // count collections
-    //
-    return HidParser_GetCollectionCount(ParserContext->RootCollection);
 }
 
 ULONG
 HidParser_GetMaxUsageListLengthWithReportAndPage(
-    IN PHID_PARSER Parser,
-    IN ULONG CollectionIndex,
-    IN ULONG ReportType,
+    IN PVOID CollectionContext,
+    IN UCHAR ReportType,
     IN USAGE  UsagePage  OPTIONAL)
 {
-    PHID_PARSER_CONTEXT ParserContext;
     ULONG Index;
     PHID_REPORT Report;
     ULONG ItemCount = 0;
     USHORT CurrentUsagePage;
 
-    //
-    // get parser context
-    //
-    ParserContext = (PHID_PARSER_CONTEXT)Parser->ParserContext;
-
-    //
-    // sanity checks
-    //
-    ASSERT(ParserContext);
-
-    //
-    // FIXME support multiple top collecions
-    //
-    ASSERT(ParserContext->RootCollection->NodeCount == 1);
-
     //
     // get report
     //
-    Report = HidParser_GetReportByType(Parser, CollectionIndex, ReportType);
+    Report = HidParser_GetReportInCollection(CollectionContext, ReportType);
     if (!Report)
     {
         //
@@ -570,8 +221,8 @@ HidParser_GetMaxUsageListLengthWithReportAndPage(
         //
         // check usage page
         //
-        CurrentUsagePage = (Report->Items[Index]->UsageMinimum >> 16);
-        if (CurrentUsagePage == UsagePage && Report->Items[Index]->HasData)
+        CurrentUsagePage = (Report->Items[Index].UsageMinimum >> 16);
+        if (CurrentUsagePage == UsagePage && Report->Items[Index].HasData)
         {
             //
             // found item
@@ -589,39 +240,23 @@ HidParser_GetMaxUsageListLengthWithReportAndPage(
 HIDPARSER_STATUS
 HidParser_GetSpecificValueCapsWithReport(
     IN PHID_PARSER Parser,
-    IN ULONG CollectionIndex,
-    IN ULONG ReportType,
+    IN PVOID CollectionContext,
+    IN UCHAR ReportType,
     IN USHORT UsagePage,
     IN USHORT Usage,
     OUT PHIDP_VALUE_CAPS  ValueCaps,
     IN OUT PULONG  ValueCapsLength)
 {
-    PHID_PARSER_CONTEXT ParserContext;
     ULONG Index;
     PHID_REPORT Report;
     ULONG ItemCount = 0;
     USHORT CurrentUsagePage;
     USHORT CurrentUsage;
 
-    //
-    // get parser context
-    //
-    ParserContext = (PHID_PARSER_CONTEXT)Parser->ParserContext;
-
-    //
-    // sanity checks
-    //
-    ASSERT(ParserContext);
-
-    //
-    // FIXME support multiple top collecions
-    //
-    ASSERT(ParserContext->RootCollection->NodeCount == 1);
-
     //
     // get report
     //
-    Report = HidParser_GetReportByType(Parser, CollectionIndex, ReportType);
+    Report = HidParser_GetReportInCollection(CollectionContext, ReportType);
     if (!Report)
     {
         //
@@ -635,8 +270,8 @@ HidParser_GetSpecificValueCapsWithReport(
         //
         // check usage page
         //
-        CurrentUsagePage = (Report->Items[Index]->UsageMinimum >> 16);
-        CurrentUsage = (Report->Items[Index]->UsageMinimum & 0xFFFF);
+        CurrentUsagePage = (Report->Items[Index].UsageMinimum >> 16);
+        CurrentUsage = (Report->Items[Index].UsageMinimum & 0xFFFF);
 
         if ((Usage == CurrentUsage && UsagePage == CurrentUsagePage) || (Usage == 0 && UsagePage == CurrentUsagePage) || (Usage == CurrentUsage && UsagePage == 0) || (Usage == 0 && UsagePage == 0))
         {
@@ -655,10 +290,10 @@ HidParser_GetSpecificValueCapsWithReport(
                 //
                 ValueCaps[ItemCount].UsagePage = CurrentUsagePage;
                 ValueCaps[ItemCount].ReportID = Report->ReportID;
-                ValueCaps[ItemCount].LogicalMin = Report->Items[Index]->Minimum;
-                ValueCaps[ItemCount].LogicalMax = Report->Items[Index]->Maximum;
-                ValueCaps[ItemCount].IsAbsolute = !Report->Items[Index]->Relative;
-                ValueCaps[ItemCount].BitSize = Report->Items[Index]->BitCount;
+                ValueCaps[ItemCount].LogicalMin = Report->Items[Index].Minimum;
+                ValueCaps[ItemCount].LogicalMax = Report->Items[Index].Maximum;
+                ValueCaps[ItemCount].IsAbsolute = !Report->Items[Index].Relative;
+                ValueCaps[ItemCount].BitSize = Report->Items[Index].BitCount;
 
                 //
                 // FIXME: FILLMEIN
@@ -695,15 +330,14 @@ HidParser_GetSpecificValueCapsWithReport(
 HIDPARSER_STATUS
 HidParser_GetUsagesWithReport(
     IN PHID_PARSER Parser,
-    IN ULONG CollectionIndex,
-    IN ULONG  ReportType,
+    IN PVOID CollectionContext,
+    IN UCHAR  ReportType,
     IN USAGE  UsagePage,
     OUT USAGE  *UsageList,
     IN OUT PULONG UsageLength,
     IN PCHAR  ReportDescriptor,
     IN ULONG  ReportDescriptorLength)
 {
-    PHID_PARSER_CONTEXT ParserContext;
     ULONG Index;
     PHID_REPORT Report;
     ULONG ItemCount = 0;
@@ -712,25 +346,10 @@ HidParser_GetUsagesWithReport(
     UCHAR Activated;
     ULONG Data;
 
-    //
-    // get parser context
-    //
-    ParserContext = (PHID_PARSER_CONTEXT)Parser->ParserContext;
-
-    //
-    // sanity checks
-    //
-    ASSERT(ParserContext);
-
-    //
-    // FIXME support multiple top collecions
-    //
-    ASSERT(ParserContext->RootCollection->NodeCount == 1);
-
     //
     // get report
     //
-    Report = HidParser_GetReportByType(Parser, CollectionIndex, ReportType);
+    Report = HidParser_GetReportInCollection(CollectionContext, ReportType);
     if (!Report)
     {
         //
@@ -752,7 +371,7 @@ HidParser_GetUsagesWithReport(
         //
         // get report item
         //
-        ReportItem = Report->Items[Index];
+        ReportItem = &Report->Items[Index];
 
         //
         // does it have data
@@ -843,40 +462,24 @@ HidParser_GetUsagesWithReport(
 HIDPARSER_STATUS
 HidParser_GetScaledUsageValueWithReport(
     IN PHID_PARSER Parser,
-    IN ULONG CollectionIndex,
-    IN ULONG ReportType,
+    IN PVOID CollectionContext,
+    IN UCHAR ReportType,
     IN USAGE UsagePage,
     IN USAGE  Usage,
     OUT PLONG UsageValue,
     IN PCHAR ReportDescriptor,
     IN ULONG ReportDescriptorLength)
 {
-    PHID_PARSER_CONTEXT ParserContext;
     ULONG Index;
     PHID_REPORT Report;
     USHORT CurrentUsagePage;
     PHID_REPORT_ITEM ReportItem;
     ULONG Data;
 
-    //
-    // get parser context
-    //
-    ParserContext = (PHID_PARSER_CONTEXT)Parser->ParserContext;
-
-    //
-    // sanity checks
-    //
-    ASSERT(ParserContext);
-
-    //
-    // FIXME support multiple top collecions
-    //
-    ASSERT(ParserContext->RootCollection->NodeCount == 1);
-
     //
     // get report
     //
-    Report = HidParser_GetReportByType(Parser, CollectionIndex, ReportType);
+    Report = HidParser_GetReportInCollection(CollectionContext, ReportType);
     if (!Report)
     {
         //
@@ -898,7 +501,7 @@ HidParser_GetScaledUsageValueWithReport(
         //
         // get report item
         //
-        ReportItem = Report->Items[Index];
+        ReportItem = &Report->Items[Index];
 
         //
         // check usage page
@@ -1034,7 +637,6 @@ HidParser_DispatchKey(
 HIDPARSER_STATUS
 HidParser_TranslateUsage(
     IN PHID_PARSER Parser,
-    IN ULONG CollectionIndex,
     IN USAGE Usage,
     IN HIDP_KEYBOARD_DIRECTION  KeyAction,
     IN OUT PHIDP_KEYBOARD_MODIFIER_STATE  ModifierState,
@@ -1066,15 +668,3 @@ HidParser_TranslateUsage(
     //
     return HIDPARSER_STATUS_SUCCESS;
 }
-
-ULONG
-HidParser_GetCollectionNumberFromParserContext(
-    IN PHID_PARSER Parser)
-{
-    PHID_PARSER_CONTEXT Context = (PHID_PARSER_CONTEXT)Parser->ParserContext;
-
-    //
-    // get parser context
-    //
-    return Context->CollectionIndex;
-}
diff --git a/lib/drivers/hidparser/context.c b/lib/drivers/hidparser/context.c
new file mode 100644 (file)
index 0000000..3bf3662
--- /dev/null
@@ -0,0 +1,344 @@
+/*
+ * PROJECT:     ReactOS HID Parser Library
+ * LICENSE:     GPL - See COPYING in the top level directory
+ * FILE:        lib/drivers/hidparser/context.c
+ * PURPOSE:     HID Parser
+ * PROGRAMMERS:
+ *              Michael Martin (michael.martin@reactos.org)
+ *              Johannes Anderwald (johannes.anderwald@reactos.org)
+ */
+
+
+#include "parser.h"
+
+typedef struct
+{
+    ULONG Size;
+    union
+    {
+        UCHAR RawData[1];
+    };
+}HID_COLLECTION_CONTEXT, *PHID_COLLECTION_CONTEXT;
+
+ULONG
+HidParser_CalculateCollectionSize(
+    IN PHID_COLLECTION Collection)
+{
+    ULONG Size = 0, Index;
+
+    Size = sizeof(HID_COLLECTION);
+
+    //
+    // add size required for the number of report items
+    //
+    for(Index = 0; Index < Collection->ReportCount; Index++)
+    {
+        //
+        // get report size
+        //
+        ASSERT(Collection->Reports[Index]->ItemCount);
+        Size += sizeof(HID_REPORT) + Collection->Reports[Index]->ItemCount * sizeof(HID_REPORT_ITEM);
+    }
+
+    //
+    // calculate size for sub collections
+    //
+    for(Index = 0; Index < Collection->NodeCount; Index++)
+    {
+        Size += HidParser_CalculateCollectionSize(Collection->Nodes[Index]);
+    }
+
+    //
+    // append size for the offset
+    //
+    Size += (Collection->ReportCount + Collection->NodeCount) * sizeof(ULONG);
+
+    //
+    // done
+    //
+    return Size;
+}
+
+ULONG
+HidParser_CalculateContextSize(
+    IN PHID_COLLECTION Collection)
+{
+    ULONG Size;
+
+    //
+    // minimum size is the size of the collection
+    //
+    Size = HidParser_CalculateCollectionSize(Collection);
+
+    //
+    // append collection context size
+    //
+    Size += sizeof(HID_COLLECTION_CONTEXT);
+    return Size;
+}
+
+ULONG
+HidParser_StoreCollection(
+    IN PHID_PARSER Parser,
+    IN PHID_COLLECTION Collection,
+    IN PHID_COLLECTION_CONTEXT CollectionContext,
+    IN ULONG CurrentOffset)
+{
+    ULONG Index;
+    ULONG ReportSize;
+    ULONG InitialOffset;
+    ULONG CollectionSize;
+    PHID_COLLECTION TargetCollection;
+
+    //
+    // backup initial offset
+    //
+    InitialOffset = CurrentOffset;
+
+    //
+    // get target collection
+    //
+    TargetCollection = (PHID_COLLECTION)(&CollectionContext->RawData[CurrentOffset]);
+
+    //
+    // first copy the collection details
+    //
+    Parser->Copy(TargetCollection, Collection, sizeof(HID_COLLECTION));
+
+    //
+    // calulcate collection size
+    //
+    CollectionSize = sizeof(HID_COLLECTION) + sizeof(ULONG) * (Collection->ReportCount + Collection->NodeCount);
+
+    //
+    // increase offset
+    //
+    CurrentOffset += CollectionSize;
+
+    //
+    // sanity check
+    //
+    ASSERT(CurrentOffset < CollectionContext->Size);
+
+    //
+    // first store the report items
+    //
+    for(Index = 0; Index < Collection->ReportCount; Index++)
+    {
+        //
+        // calculate report size
+        //
+        ReportSize = sizeof(HID_REPORT) + Collection->Reports[Index]->ItemCount * sizeof(HID_REPORT_ITEM);
+
+        //
+        // sanity check
+        //
+        ASSERT(CurrentOffset + ReportSize < CollectionContext->Size);
+
+        //
+        // copy report item
+        //
+        Parser->Copy(&CollectionContext->RawData[CurrentOffset], Collection->Reports[Index], ReportSize);
+
+        //
+        // store offset to report item
+        //
+        TargetCollection->Offsets[Index] = CurrentOffset;
+
+        //
+        // move to next offset
+        //
+        CurrentOffset += ReportSize;
+    }
+
+    ASSERT(CurrentOffset <= CollectionContext->Size);
+
+    //
+    // now store the sub collections
+    //
+    for(Index = 0; Index < Collection->NodeCount; Index++)
+    {
+        //
+        // store offset
+        //
+        TargetCollection->Offsets[Collection->NodeCount + Index] = CurrentOffset;
+
+        //
+        // store sub collections
+        //
+        CurrentOffset += HidParser_StoreCollection(Parser, Collection->Nodes[Index], CollectionContext, CurrentOffset);
+
+        //
+        // sanity check
+        //
+        ASSERT(CurrentOffset < CollectionContext->Size);
+    }
+
+    //
+    // return size of collection
+    //
+    return CurrentOffset - InitialOffset;
+}
+
+HIDPARSER_STATUS
+HidParser_BuildCollectionContext(
+    IN PHID_PARSER Parser,
+    IN PHID_COLLECTION RootCollection,
+    IN PVOID Context,
+    IN ULONG ContextSize)
+{
+    PHID_COLLECTION_CONTEXT CollectionContext;
+    ULONG CollectionSize;
+
+    //
+    // init context
+    //
+    CollectionContext = (PHID_COLLECTION_CONTEXT)Context;
+    CollectionContext->Size = ContextSize;
+
+    //
+    // store collections
+    //
+    CollectionSize = HidParser_StoreCollection(Parser, RootCollection, CollectionContext, 0);
+
+    //
+    // sanity check
+    //
+    ASSERT(CollectionSize + sizeof(HID_COLLECTION_CONTEXT) == ContextSize);
+
+    DPRINT1("CollectionContext %p\n", CollectionContext);
+    DPRINT1("CollectionContext RawData %p\n", CollectionContext->RawData);
+    DPRINT1("CollectionContext Size %lu\n", CollectionContext->Size);
+
+    //
+    // done
+    //
+    return HIDPARSER_STATUS_SUCCESS;
+}
+
+PHID_REPORT
+HidParser_SearchReportInCollection(
+    IN PHID_COLLECTION_CONTEXT CollectionContext,
+    IN PHID_COLLECTION Collection,
+    IN UCHAR ReportType)
+{
+    ULONG Index;
+    PHID_REPORT Report;
+    PHID_COLLECTION SubCollection;
+
+    //
+    // search first in local array
+    //
+    for(Index = 0; Index < Collection->ReportCount; Index++)
+    {
+        //
+        // get report
+        //
+        Report = (PHID_REPORT)(CollectionContext->RawData + Collection->Offsets[Index]);
+        if (Report->Type == ReportType)
+        {
+            //
+            // found report
+            //
+            return Report;
+        }
+    }
+
+    //
+    // now search in sub collections
+    //
+    for(Index = 0; Index < Collection->NodeCount; Index++)
+    {
+        //
+        // get collection
+        //
+        SubCollection = (PHID_COLLECTION)(CollectionContext->RawData + Collection->Offsets[Collection->NodeCount + Index]);
+
+        //
+        // recursively search collection
+        //
+        Report = HidParser_SearchReportInCollection(CollectionContext, SubCollection, ReportType);
+        if (Report)
+        {
+            //
+            // found report
+            //
+            return Report;
+        }
+    }
+
+    //
+    // not found
+    //
+    return NULL;
+}
+
+PHID_REPORT
+HidParser_GetReportInCollection(
+    IN PVOID Context,
+    IN UCHAR ReportType)
+{
+    PHID_COLLECTION_CONTEXT CollectionContext = (PHID_COLLECTION_CONTEXT)Context;
+
+    //
+    // done
+    //
+    return HidParser_SearchReportInCollection(CollectionContext, (PHID_COLLECTION)&CollectionContext->RawData, ReportType);
+}
+
+PHID_COLLECTION
+HidParser_GetCollectionFromContext(
+    IN PVOID Context)
+{
+    PHID_COLLECTION_CONTEXT CollectionContext = (PHID_COLLECTION_CONTEXT)Context;
+
+    //
+    // return root collection
+    //
+    return (PHID_COLLECTION)CollectionContext->RawData;
+}
+
+ULONG
+HidParser_GetCollectionCount(
+    IN PHID_COLLECTION_CONTEXT CollectionContext,
+    IN PHID_COLLECTION Collection)
+{
+    ULONG Index;
+    ULONG Count = Collection->NodeCount;
+    PHID_COLLECTION SubCollection;
+
+    for(Index = 0; Index < Collection->NodeCount; Index++)
+    {
+        //
+        // get offset to sub collection
+        //
+        SubCollection = (PHID_COLLECTION)(CollectionContext->RawData + Collection->Offsets[Collection->NodeCount + Index]);
+
+        //
+        // count collection for sub nodes
+        //
+        Count += HidParser_GetCollectionCount(CollectionContext, SubCollection);
+    }
+
+    //
+    // done
+    //
+    return Count;
+}
+
+ULONG
+HidParser_GetTotalCollectionCount(
+    IN PVOID Context)
+{
+    PHID_COLLECTION_CONTEXT CollectionContext;
+
+    //
+    // get parser context
+    //
+    CollectionContext = (PHID_COLLECTION_CONTEXT)Context;
+
+    //
+    // count collections
+    //
+    return HidParser_GetCollectionCount(CollectionContext, (PHID_COLLECTION)CollectionContext->RawData);
+}
index c84533e..402f7fd 100644 (file)
@@ -51,11 +51,12 @@ HidParser_GetCollectionDescription(
     HIDPARSER_STATUS ParserStatus;
     ULONG CollectionCount;
     ULONG Index;
+    PVOID ParserContext;
 
     //
     // first parse the report descriptor
     //
-    ParserStatus = HidParser_ParseReportDescriptor(Parser, ReportDesc, DescLength);
+    ParserStatus = HidParser_ParseReportDescriptor(Parser, ReportDesc, DescLength, &ParserContext);
     if (ParserStatus != HIDPARSER_STATUS_SUCCESS)
     {
         //
@@ -68,7 +69,7 @@ HidParser_GetCollectionDescription(
     //
     // get collection count
     //
-    CollectionCount = HidParser_NumberOfTopCollections(Parser);
+    CollectionCount = HidParser_NumberOfTopCollections(ParserContext);
     if (CollectionCount == 0)
     {
         //
@@ -110,14 +111,27 @@ HidParser_GetCollectionDescription(
 
     for(Index = 0; Index < CollectionCount; Index++)
     {
+        //
+        // set preparsed data length
+        //
+        DeviceDescription->CollectionDesc[Index].PreparsedDataLength = HidParser_GetContextSize(Parser, ParserContext, Index);
+        ParserStatus = HidParser_BuildContext(Parser, ParserContext, Index, DeviceDescription->CollectionDesc[Index].PreparsedDataLength, (PVOID*)&DeviceDescription->CollectionDesc[Index].PreparsedData);
+        if (ParserStatus != HIDPARSER_STATUS_SUCCESS)
+        {
+            //
+            // no memory
+            //
+            return TranslateHidParserStatus(ParserStatus);
+        }
+
         //
         // init report description
         //
         DeviceDescription->ReportIDs[Index].CollectionNumber = Index + 1;
         DeviceDescription->ReportIDs[Index].ReportID = Index; //FIXME
-        DeviceDescription->ReportIDs[Index].InputLength = HidParser_GetReportLength(Parser, Index, HID_REPORT_TYPE_INPUT);
-        DeviceDescription->ReportIDs[Index].OutputLength = HidParser_GetReportLength(Parser, Index, HID_REPORT_TYPE_OUTPUT);
-        DeviceDescription->ReportIDs[Index].FeatureLength = HidParser_GetReportLength(Parser, Index, HID_REPORT_TYPE_FEATURE);
+        DeviceDescription->ReportIDs[Index].InputLength = HidParser_GetReportLength((PVOID)DeviceDescription->CollectionDesc[Index].PreparsedData, HID_REPORT_TYPE_INPUT);
+        DeviceDescription->ReportIDs[Index].OutputLength = HidParser_GetReportLength((PVOID)DeviceDescription->CollectionDesc[Index].PreparsedData, HID_REPORT_TYPE_OUTPUT);
+        DeviceDescription->ReportIDs[Index].FeatureLength = HidParser_GetReportLength((PVOID)DeviceDescription->CollectionDesc[Index].PreparsedData, HID_REPORT_TYPE_FEATURE);
 
         //
         // init collection description
@@ -127,7 +141,7 @@ HidParser_GetCollectionDescription(
         //
         // get collection usage page
         //
-        ParserStatus = HidParser_GetCollectionUsagePage(Parser, Index, &DeviceDescription->CollectionDesc[Index].Usage, &DeviceDescription->CollectionDesc[Index].UsagePage);
+        ParserStatus = HidParser_GetCollectionUsagePage((PVOID)DeviceDescription->CollectionDesc[Index].PreparsedData, &DeviceDescription->CollectionDesc[Index].Usage, &DeviceDescription->CollectionDesc[Index].UsagePage);
 
         //
         // windows seems to prepend the report id, regardless if it is required
@@ -135,24 +149,6 @@ HidParser_GetCollectionDescription(
         DeviceDescription->CollectionDesc[Index].InputLength = (DeviceDescription->ReportIDs[Index].InputLength > 0 ? DeviceDescription->ReportIDs[Index].InputLength + 1 : 0);
         DeviceDescription->CollectionDesc[Index].OutputLength = (DeviceDescription->ReportIDs[Index].OutputLength > 0 ? DeviceDescription->ReportIDs[Index].OutputLength + 1 : 0);
         DeviceDescription->CollectionDesc[Index].FeatureLength = (DeviceDescription->ReportIDs[Index].FeatureLength > 0 ? DeviceDescription->ReportIDs[Index].FeatureLength + 1 : 0);
-
-        //
-        // set preparsed data length
-        //
-        DeviceDescription->CollectionDesc[Index].PreparsedDataLength = HidParser_GetContextSize(Parser, Index);
-        DeviceDescription->CollectionDesc[Index].PreparsedData = Parser->Alloc(DeviceDescription->CollectionDesc[Index].PreparsedDataLength);
-        if (!DeviceDescription->CollectionDesc[Index].PreparsedData)
-        {
-            //
-            // no memory
-            //
-            return STATUS_INSUFFICIENT_RESOURCES;
-        }
-
-        //
-        // copy context
-        //
-        Parser->Copy(DeviceDescription->CollectionDesc[Index].PreparsedData, Parser->ParserContext, DeviceDescription->CollectionDesc[Index].PreparsedDataLength);
     }
 
     //
@@ -181,9 +177,9 @@ HidParser_FreeCollectionDescription(
     for(Index = 0; Index < DeviceDescription->CollectionDescLength; Index++)
     {
         //
-        // free parser context
+        // free collection context
         //
-        HidParser_FreeContext(Parser, (PUCHAR)DeviceDescription->CollectionDesc[Index].PreparsedData, DeviceDescription->CollectionDesc[Index].PreparsedDataLength);
+        Parser->Free(DeviceDescription->CollectionDesc[Index].PreparsedData);
     }
 
     //
@@ -202,15 +198,9 @@ NTSTATUS
 NTAPI
 HidParser_GetCaps(
     IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
     OUT PHIDP_CAPS  Capabilities)
 {
-    ULONG CollectionNumber;
-
-    //
-    // get collection number from context
-    //
-    CollectionNumber = HidParser_GetCollectionNumberFromParserContext(Parser);
-
     //
     // zero capabilities
     //
@@ -219,10 +209,10 @@ HidParser_GetCaps(
     //
     // init capabilities
     //
-    HidParser_GetCollectionUsagePage(Parser, CollectionNumber, &Capabilities->Usage, &Capabilities->UsagePage);
-    Capabilities->InputReportByteLength = HidParser_GetReportLength(Parser, CollectionNumber, HID_REPORT_TYPE_INPUT);
-    Capabilities->OutputReportByteLength = HidParser_GetReportLength(Parser, CollectionNumber, HID_REPORT_TYPE_OUTPUT);
-    Capabilities->FeatureReportByteLength = HidParser_GetReportLength(Parser, CollectionNumber, HID_REPORT_TYPE_FEATURE);
+    HidParser_GetCollectionUsagePage(CollectionContext, &Capabilities->Usage, &Capabilities->UsagePage);
+    Capabilities->InputReportByteLength = HidParser_GetReportLength(CollectionContext, HID_REPORT_TYPE_INPUT);
+    Capabilities->OutputReportByteLength = HidParser_GetReportLength(CollectionContext, HID_REPORT_TYPE_OUTPUT);
+    Capabilities->FeatureReportByteLength = HidParser_GetReportLength(CollectionContext, HID_REPORT_TYPE_FEATURE);
 
     //
     // always pre-prend report id
@@ -234,29 +224,29 @@ HidParser_GetCaps(
     //
     // get number of link collection nodes
     //
-    Capabilities->NumberLinkCollectionNodes = HidParser_GetTotalCollectionCount(Parser, CollectionNumber);
+    Capabilities->NumberLinkCollectionNodes = HidParser_GetTotalCollectionCount(CollectionContext);
 
     //
     // get data indices
     //
-    Capabilities->NumberInputDataIndices = HidParser_GetReportItemTypeCountFromReportType(Parser, CollectionNumber, HID_REPORT_TYPE_INPUT, TRUE);
-    Capabilities->NumberOutputDataIndices = HidParser_GetReportItemTypeCountFromReportType(Parser, CollectionNumber, HID_REPORT_TYPE_OUTPUT, TRUE);
-    Capabilities->NumberFeatureDataIndices = HidParser_GetReportItemTypeCountFromReportType(Parser, CollectionNumber, HID_REPORT_TYPE_FEATURE, TRUE);
+    Capabilities->NumberInputDataIndices = HidParser_GetReportItemTypeCountFromReportType(CollectionContext, HID_REPORT_TYPE_INPUT, TRUE);
+    Capabilities->NumberOutputDataIndices = HidParser_GetReportItemTypeCountFromReportType(CollectionContext, HID_REPORT_TYPE_OUTPUT, TRUE);
+    Capabilities->NumberFeatureDataIndices = HidParser_GetReportItemTypeCountFromReportType(CollectionContext, HID_REPORT_TYPE_FEATURE, TRUE);
 
     //
     // get value caps
     //
-    Capabilities->NumberInputValueCaps = HidParser_GetReportItemTypeCountFromReportType(Parser, CollectionNumber, HID_REPORT_TYPE_INPUT, FALSE);
-    Capabilities->NumberOutputValueCaps = HidParser_GetReportItemTypeCountFromReportType(Parser, CollectionNumber, HID_REPORT_TYPE_OUTPUT, FALSE);
-    Capabilities->NumberFeatureValueCaps = HidParser_GetReportItemTypeCountFromReportType(Parser, CollectionNumber, HID_REPORT_TYPE_FEATURE, FALSE);
+    Capabilities->NumberInputValueCaps = HidParser_GetReportItemTypeCountFromReportType(CollectionContext, HID_REPORT_TYPE_INPUT, FALSE);
+    Capabilities->NumberOutputValueCaps = HidParser_GetReportItemTypeCountFromReportType(CollectionContext, HID_REPORT_TYPE_OUTPUT, FALSE);
+    Capabilities->NumberFeatureValueCaps = HidParser_GetReportItemTypeCountFromReportType(CollectionContext, HID_REPORT_TYPE_FEATURE, FALSE);
 
 
     //
     // get button caps
     //
-    Capabilities->NumberInputButtonCaps = HidParser_GetReportItemCountFromReportType(Parser, CollectionNumber, HID_REPORT_TYPE_INPUT);
-    Capabilities->NumberOutputButtonCaps = HidParser_GetReportItemCountFromReportType(Parser, CollectionNumber, HID_REPORT_TYPE_OUTPUT);
-    Capabilities->NumberFeatureButtonCaps = HidParser_GetReportItemCountFromReportType(Parser, CollectionNumber, HID_REPORT_TYPE_FEATURE);
+    Capabilities->NumberInputButtonCaps = HidParser_GetReportItemCountFromReportType(CollectionContext, HID_REPORT_TYPE_INPUT);
+    Capabilities->NumberOutputButtonCaps = HidParser_GetReportItemCountFromReportType(CollectionContext, HID_REPORT_TYPE_OUTPUT);
+    Capabilities->NumberFeatureButtonCaps = HidParser_GetReportItemCountFromReportType(CollectionContext, HID_REPORT_TYPE_FEATURE);
 
     //
     // done
@@ -269,17 +259,10 @@ ULONG
 NTAPI
 HidParser_MaxUsageListLength(
     IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
     IN HIDP_REPORT_TYPE  ReportType,
     IN USAGE  UsagePage  OPTIONAL)
 {
-    ULONG CollectionNumber;
-
-    //
-    // get collection number from context
-    //
-    CollectionNumber = HidParser_GetCollectionNumberFromParserContext(Parser);
-
-
     //
     // FIXME test what should be returned when usage page is not defined
     //
@@ -301,21 +284,21 @@ HidParser_MaxUsageListLength(
         //
         // input report
         //
-        return HidParser_GetMaxUsageListLengthWithReportAndPage(Parser, CollectionNumber, HID_REPORT_TYPE_INPUT, UsagePage);
+        return HidParser_GetMaxUsageListLengthWithReportAndPage(CollectionContext, HID_REPORT_TYPE_INPUT, UsagePage);
     }
     else if (ReportType == HidP_Output)
     {
         //
         // input report
         //
-        return HidParser_GetMaxUsageListLengthWithReportAndPage(Parser, CollectionNumber, HID_REPORT_TYPE_OUTPUT, UsagePage);
+        return HidParser_GetMaxUsageListLengthWithReportAndPage(CollectionContext, HID_REPORT_TYPE_OUTPUT, UsagePage);
     }
     else if (ReportType == HidP_Feature)
     {
         //
         // input report
         //
-        return HidParser_GetMaxUsageListLengthWithReportAndPage(Parser, CollectionNumber, HID_REPORT_TYPE_FEATURE, UsagePage);
+        return HidParser_GetMaxUsageListLengthWithReportAndPage(CollectionContext, HID_REPORT_TYPE_FEATURE, UsagePage);
     }
     else
     {
@@ -333,11 +316,12 @@ NTSTATUS
 NTAPI
 HidParser_GetButtonCaps(
     IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
     IN HIDP_REPORT_TYPE ReportType,
     IN PHIDP_BUTTON_CAPS ButtonCaps,
     IN PUSHORT ButtonCapsLength)
 {
-    return HidParser_GetSpecificButtonCaps(Parser, ReportType, HID_USAGE_PAGE_UNDEFINED, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_PAGE_UNDEFINED, ButtonCaps, (PULONG)ButtonCapsLength);
+    return HidParser_GetSpecificButtonCaps(Parser, CollectionContext, ReportType, HID_USAGE_PAGE_UNDEFINED, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_PAGE_UNDEFINED, ButtonCaps, (PULONG)ButtonCapsLength);
 }
 
 HIDAPI
@@ -345,6 +329,7 @@ NTSTATUS
 NTAPI
 HidParser_GetSpecificValueCaps(
     IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
     IN HIDP_REPORT_TYPE  ReportType,
     IN USAGE  UsagePage,
     IN USHORT  LinkCollection,
@@ -353,14 +338,6 @@ HidParser_GetSpecificValueCaps(
     IN OUT PULONG  ValueCapsLength)
 {
     HIDPARSER_STATUS ParserStatus;
-    ULONG CollectionNumber;
-
-    //
-    // get collection number from context
-    //
-    CollectionNumber = HidParser_GetCollectionNumberFromParserContext(Parser);
-
-
 
     //
     // FIXME: implement searching in specific collection
@@ -372,21 +349,21 @@ HidParser_GetSpecificValueCaps(
         //
         // input report
         //
-        ParserStatus = HidParser_GetSpecificValueCapsWithReport(Parser, CollectionNumber, HID_REPORT_TYPE_INPUT, UsagePage, Usage, ValueCaps, ValueCapsLength);
+        ParserStatus = HidParser_GetSpecificValueCapsWithReport(Parser, CollectionContext, HID_REPORT_TYPE_INPUT, UsagePage, Usage, ValueCaps, ValueCapsLength);
     }
     else if (ReportType == HidP_Output)
     {
         //
         // input report
         //
-        ParserStatus = HidParser_GetSpecificValueCapsWithReport(Parser, CollectionNumber, HID_REPORT_TYPE_OUTPUT, UsagePage, Usage, ValueCaps, ValueCapsLength);
+        ParserStatus = HidParser_GetSpecificValueCapsWithReport(Parser, CollectionContext, HID_REPORT_TYPE_OUTPUT, UsagePage, Usage, ValueCaps, ValueCapsLength);
     }
     else if (ReportType == HidP_Feature)
     {
         //
         // input report
         //
-        ParserStatus = HidParser_GetSpecificValueCapsWithReport(Parser, CollectionNumber, HID_REPORT_TYPE_FEATURE, UsagePage, Usage, ValueCaps, ValueCapsLength);
+        ParserStatus = HidParser_GetSpecificValueCapsWithReport(Parser, CollectionContext, HID_REPORT_TYPE_FEATURE, UsagePage, Usage, ValueCaps, ValueCapsLength);
     }
     else
     {
@@ -545,6 +522,7 @@ NTSTATUS
 NTAPI
 HidParser_GetUsages(
     IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
     IN HIDP_REPORT_TYPE  ReportType,
     IN USAGE  UsagePage,
     IN USHORT  LinkCollection  OPTIONAL,
@@ -554,12 +532,6 @@ HidParser_GetUsages(
     IN ULONG  ReportLength)
 {
     HIDPARSER_STATUS ParserStatus;
-    ULONG CollectionNumber;
-
-    //
-    // get collection number from context
-    //
-    CollectionNumber = HidParser_GetCollectionNumberFromParserContext(Parser);
 
     //
     // FIXME: implement searching in specific collection
@@ -571,21 +543,21 @@ HidParser_GetUsages(
         //
         // input report
         //
-        ParserStatus = HidParser_GetUsagesWithReport(Parser, CollectionNumber, HID_REPORT_TYPE_INPUT, UsagePage, UsageList, UsageLength, Report, ReportLength);
+        ParserStatus = HidParser_GetUsagesWithReport(Parser, CollectionContext, HID_REPORT_TYPE_INPUT, UsagePage, UsageList, UsageLength, Report, ReportLength);
     }
     else if (ReportType == HidP_Output)
     {
         //
         // input report
         //
-        ParserStatus = HidParser_GetUsagesWithReport(Parser, CollectionNumber, HID_REPORT_TYPE_OUTPUT, UsagePage, UsageList, UsageLength, Report, ReportLength);
+        ParserStatus = HidParser_GetUsagesWithReport(Parser, CollectionContext, HID_REPORT_TYPE_OUTPUT, UsagePage, UsageList, UsageLength, Report, ReportLength);
     }
     else if (ReportType == HidP_Feature)
     {
         //
         // input report
         //
-        ParserStatus = HidParser_GetUsagesWithReport(Parser, CollectionNumber, HID_REPORT_TYPE_FEATURE, UsagePage, UsageList, UsageLength, Report, ReportLength);
+        ParserStatus = HidParser_GetUsagesWithReport(Parser, CollectionContext, HID_REPORT_TYPE_FEATURE, UsagePage, UsageList, UsageLength, Report, ReportLength);
     }
     else
     {
@@ -614,6 +586,7 @@ NTSTATUS
 NTAPI
 HidParser_GetScaledUsageValue(
     IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
     IN HIDP_REPORT_TYPE  ReportType,
     IN USAGE  UsagePage,
     IN USHORT  LinkCollection  OPTIONAL,
@@ -623,12 +596,6 @@ HidParser_GetScaledUsageValue(
     IN ULONG  ReportLength)
 {
     HIDPARSER_STATUS ParserStatus;
-    ULONG CollectionNumber;
-
-    //
-    // get collection number from context
-    //
-    CollectionNumber = HidParser_GetCollectionNumberFromParserContext(Parser);
 
     //
     // FIXME: implement searching in specific collection
@@ -640,21 +607,21 @@ HidParser_GetScaledUsageValue(
         //
         // input report
         //
-        ParserStatus = HidParser_GetScaledUsageValueWithReport(Parser, CollectionNumber, HID_REPORT_TYPE_INPUT, UsagePage, Usage, UsageValue, Report, ReportLength);
+        ParserStatus = HidParser_GetScaledUsageValueWithReport(Parser, CollectionContext, HID_REPORT_TYPE_INPUT, UsagePage, Usage, UsageValue, Report, ReportLength);
     }
     else if (ReportType == HidP_Output)
     {
         //
         // input report
         //
-        ParserStatus = HidParser_GetScaledUsageValueWithReport(Parser, CollectionNumber, HID_REPORT_TYPE_OUTPUT, UsagePage, Usage, UsageValue, Report, ReportLength);
+        ParserStatus = HidParser_GetScaledUsageValueWithReport(Parser, CollectionContext, HID_REPORT_TYPE_OUTPUT, UsagePage, Usage, UsageValue, Report, ReportLength);
     }
     else if (ReportType == HidP_Feature)
     {
         //
         // input report
         //
-        ParserStatus = HidParser_GetScaledUsageValueWithReport(Parser, CollectionNumber, HID_REPORT_TYPE_FEATURE,  UsagePage, Usage, UsageValue, Report, ReportLength);
+        ParserStatus = HidParser_GetScaledUsageValueWithReport(Parser, CollectionContext, HID_REPORT_TYPE_FEATURE,  UsagePage, Usage, UsageValue, Report, ReportLength);
     }
     else
     {
@@ -692,12 +659,6 @@ HidParser_TranslateUsageAndPagesToI8042ScanCodes(
 {
     ULONG Index;
     HIDPARSER_STATUS Status = HIDPARSER_STATUS_SUCCESS;
-    ULONG CollectionNumber;
-
-    //
-    // get collection number from context
-    //
-    CollectionNumber = HidParser_GetCollectionNumberFromParserContext(Parser);
 
     for(Index = 0; Index < UsageListLength; Index++)
     {
@@ -709,7 +670,7 @@ HidParser_TranslateUsageAndPagesToI8042ScanCodes(
             //
             // process usage
             //
-            Status = HidParser_TranslateUsage(Parser, CollectionNumber, ChangedUsageList[Index].Usage, KeyAction, ModifierState, InsertCodesProcedure, InsertCodesContext);
+            Status = HidParser_TranslateUsage(Parser, ChangedUsageList[Index].Usage, KeyAction, ModifierState, InsertCodesProcedure, InsertCodesContext);
         }
         else if (ChangedUsageList[Index].UsagePage == HID_USAGE_PAGE_CONSUMER)
         {
@@ -760,6 +721,7 @@ NTSTATUS
 NTAPI
 HidParser_GetUsagesEx(
     IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
     IN HIDP_REPORT_TYPE  ReportType,
     IN USHORT  LinkCollection,
     OUT PUSAGE_AND_PAGE  ButtonList,
@@ -767,7 +729,7 @@ HidParser_GetUsagesEx(
     IN PCHAR  Report,
     IN ULONG  ReportLength)
 {
-    return HidParser_GetUsages(Parser, ReportType, HID_USAGE_PAGE_UNDEFINED, LinkCollection, (PUSAGE)ButtonList, UsageLength, Report, ReportLength);
+    return HidParser_GetUsages(Parser, CollectionContext, ReportType, HID_USAGE_PAGE_UNDEFINED, LinkCollection, (PUSAGE)ButtonList, UsageLength, Report, ReportLength);
 }
 
 HIDAPI
@@ -904,6 +866,7 @@ NTSTATUS
 NTAPI
 HidParser_GetSpecificButtonCaps(
     IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
     IN HIDP_REPORT_TYPE  ReportType,
     IN USAGE  UsagePage,
     IN USHORT  LinkCollection,
@@ -922,6 +885,7 @@ NTSTATUS
 NTAPI
 HidParser_GetData(
     IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
     IN HIDP_REPORT_TYPE  ReportType,
     OUT PHIDP_DATA  DataList,
     IN OUT PULONG  DataLength,
@@ -938,6 +902,7 @@ NTSTATUS
 NTAPI
 HidParser_GetExtendedAttributes(
     IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
     IN HIDP_REPORT_TYPE  ReportType,
     IN USHORT  DataIndex,
     OUT PHIDP_EXTENDED_ATTRIBUTES  Attributes,
@@ -953,6 +918,7 @@ NTSTATUS
 NTAPI
 HidParser_GetLinkCollectionNodes(
     IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
     OUT PHIDP_LINK_COLLECTION_NODE  LinkCollectionNodes,
     IN OUT PULONG  LinkCollectionNodesLength)
 {
@@ -966,6 +932,7 @@ NTSTATUS
 NTAPI
 HidParser_GetUsageValue(
     IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
     IN HIDP_REPORT_TYPE  ReportType,
     IN USAGE  UsagePage,
     IN USHORT  LinkCollection,
@@ -983,6 +950,7 @@ NTSTATUS
 NTAPI
 HidParser_SysPowerEvent(
     IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
     IN PCHAR HidPacket,
     IN USHORT HidPacketLength,
     OUT PULONG OutputBuffer)
@@ -996,6 +964,7 @@ NTSTATUS
 NTAPI
 HidParser_SysPowerCaps (
     IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
     OUT PULONG OutputBuffer)
 {
     UNIMPLEMENTED
@@ -1008,6 +977,7 @@ NTSTATUS
 NTAPI
 HidParser_GetUsageValueArray(
     IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
     IN HIDP_REPORT_TYPE  ReportType,
     IN USAGE  UsagePage,
     IN USHORT  LinkCollection  OPTIONAL,
@@ -1027,6 +997,7 @@ NTSTATUS
 NTAPI
 HidParser_UnsetUsages(
     IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
     IN HIDP_REPORT_TYPE  ReportType,
     IN USAGE  UsagePage,
     IN USHORT  LinkCollection,
@@ -1061,6 +1032,7 @@ NTSTATUS
 NTAPI
 HidParser_SetUsages(
     IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
     IN HIDP_REPORT_TYPE  ReportType,
     IN USAGE  UsagePage,
     IN USHORT  LinkCollection,
@@ -1079,6 +1051,7 @@ NTSTATUS
 NTAPI
 HidParser_SetUsageValueArray(
     IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
     IN HIDP_REPORT_TYPE  ReportType,
     IN USAGE  UsagePage,
     IN USHORT  LinkCollection  OPTIONAL,
@@ -1098,6 +1071,7 @@ NTSTATUS
 NTAPI
 HidParser_SetUsageValue(
     IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
     IN HIDP_REPORT_TYPE  ReportType,
     IN USAGE  UsagePage,
     IN USHORT  LinkCollection,
@@ -1116,6 +1090,7 @@ NTSTATUS
 NTAPI
 HidParser_SetScaledUsageValue(
     IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
     IN HIDP_REPORT_TYPE  ReportType,
     IN USAGE  UsagePage,
     IN USHORT  LinkCollection  OPTIONAL,
@@ -1134,6 +1109,7 @@ NTSTATUS
 NTAPI
 HidParser_SetData(
     IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
     IN HIDP_REPORT_TYPE  ReportType,
     IN PHIDP_DATA  DataList,
     IN OUT PULONG  DataLength,
@@ -1150,11 +1126,12 @@ ULONG
 NTAPI
 HidParser_MaxDataListLength(
     IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
     IN HIDP_REPORT_TYPE  ReportType)
 {
     UNIMPLEMENTED
     ASSERT(FALSE);
-    return STATUS_NOT_IMPLEMENTED;
+    return 0;
 }
 
 HIDAPI
@@ -1162,6 +1139,7 @@ NTSTATUS
 NTAPI
 HidParser_InitializeReportForID(
     IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
     IN HIDP_REPORT_TYPE  ReportType,
     IN UCHAR  ReportID,
     IN OUT PCHAR  Report,
@@ -1179,6 +1157,7 @@ NTSTATUS
 NTAPI
 HidParser_GetValueCaps(
     IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
     HIDP_REPORT_TYPE ReportType,
     PHIDP_VALUE_CAPS ValueCaps,
     PULONG ValueCapsLength)
index 24d282a..71eb157 100644 (file)
@@ -79,23 +79,8 @@ typedef struct
     // debug function
     //
     PHIDPARSER_DEBUG_FUNCTION Debug;
-
-    //
-    // parser context
-    //
-    void * ParserContext;
-
 }HID_PARSER, *PHID_PARSER;
 
-HIDPARSER_STATUS
-HidParser_AllocateParser(
-    IN PHIDPARSER_ALLOC_FUNCTION AllocFunction,
-    IN PHIDPARSER_FREE_FUNCTION FreeFunction,
-    IN PHIDPARSER_ZERO_FUNCTION ZeroFunction,
-    IN PHIDPARSER_COPY_FUNCTION CopyFunction,
-    IN PHIDPARSER_DEBUG_FUNCTION DebugFunction,
-    OUT PHID_PARSER *OutParser);
-
 VOID
 HidParser_InitParser(
     IN PHIDPARSER_ALLOC_FUNCTION AllocFunction,
@@ -103,7 +88,6 @@ HidParser_InitParser(
     IN PHIDPARSER_ZERO_FUNCTION ZeroFunction,
     IN PHIDPARSER_COPY_FUNCTION CopyFunction,
     IN PHIDPARSER_DEBUG_FUNCTION DebugFunction,
-    IN PVOID ParserContext,
     OUT PHID_PARSER Parser);
 
 NTSTATUS
@@ -126,6 +110,7 @@ NTSTATUS
 NTAPI
 HidParser_GetCaps(
     IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
     OUT PHIDP_CAPS  Capabilities);
 
 HIDAPI
@@ -133,6 +118,7 @@ NTSTATUS
 NTAPI
 HidParser_GetSpecificValueCaps(
     IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
     IN HIDP_REPORT_TYPE  ReportType,
     IN USAGE  UsagePage,
     IN USHORT  LinkCollection,
@@ -146,6 +132,7 @@ NTSTATUS
 NTAPI
 HidParser_GetButtonCaps(
     IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
     HIDP_REPORT_TYPE ReportType,
     PHIDP_BUTTON_CAPS ButtonCaps,
     PUSHORT ButtonCapsLength);
@@ -155,6 +142,7 @@ NTSTATUS
 NTAPI
 HidParser_GetSpecificButtonCaps(
     IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
     IN HIDP_REPORT_TYPE  ReportType,
     IN USAGE  UsagePage,
     IN USHORT  LinkCollection,
@@ -167,6 +155,7 @@ NTSTATUS
 NTAPI
 HidParser_GetScaledUsageValue(
     IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
     IN HIDP_REPORT_TYPE  ReportType,
     IN USAGE  UsagePage,
     IN USHORT  LinkCollection  OPTIONAL,
@@ -181,6 +170,7 @@ NTSTATUS
 NTAPI
 HidParser_GetData(
     IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
     IN HIDP_REPORT_TYPE  ReportType,
     OUT PHIDP_DATA  DataList,
     IN OUT PULONG  DataLength,
@@ -192,6 +182,7 @@ NTSTATUS
 NTAPI
 HidParser_GetExtendedAttributes(
     IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
     IN HIDP_REPORT_TYPE  ReportType,
     IN USHORT  DataIndex,
     OUT PHIDP_EXTENDED_ATTRIBUTES  Attributes,
@@ -202,6 +193,7 @@ NTSTATUS
 NTAPI
 HidParser_GetLinkCollectionNodes(
     IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
     OUT PHIDP_LINK_COLLECTION_NODE  LinkCollectionNodes,
     IN OUT PULONG  LinkCollectionNodesLength);
 
@@ -210,6 +202,7 @@ NTSTATUS
 NTAPI
 HidParser_GetUsageValue(
     IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
     IN HIDP_REPORT_TYPE  ReportType,
     IN USAGE  UsagePage,
     IN USHORT  LinkCollection,
@@ -234,6 +227,7 @@ ULONG
 NTAPI
 HidParser_MaxUsageListLength(
     IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
     IN HIDP_REPORT_TYPE  ReportType,
     IN USAGE  UsagePage  OPTIONAL);
 
@@ -242,6 +236,7 @@ NTSTATUS
 NTAPI
 HidParser_GetUsages(
     IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
     IN HIDP_REPORT_TYPE  ReportType,
     IN USAGE  UsagePage,
     IN USHORT  LinkCollection  OPTIONAL,
@@ -255,6 +250,7 @@ NTSTATUS
 NTAPI
 HidParser_GetUsagesEx(
     IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
     IN HIDP_REPORT_TYPE  ReportType,
     IN USHORT  LinkCollection,
     OUT PUSAGE_AND_PAGE  ButtonList,
@@ -267,6 +263,7 @@ NTSTATUS
 NTAPI
 HidParser_SysPowerEvent (
     IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
     IN PCHAR HidPacket,
     IN USHORT HidPacketLength,
     OUT PULONG OutputBuffer);
@@ -275,6 +272,7 @@ NTSTATUS
 NTAPI
 HidParser_SysPowerCaps (
     IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
     OUT PULONG OutputBuffer);
 
 HIDAPI
@@ -282,6 +280,7 @@ NTSTATUS
 NTAPI
 HidParser_GetUsageValueArray(
     IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
     IN HIDP_REPORT_TYPE  ReportType,
     IN USAGE  UsagePage,
     IN USHORT  LinkCollection  OPTIONAL,
@@ -307,6 +306,7 @@ NTSTATUS
 NTAPI
 HidParser_UnsetUsages(
     IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
     IN HIDP_REPORT_TYPE  ReportType,
     IN USAGE  UsagePage,
     IN USHORT  LinkCollection,
@@ -343,6 +343,7 @@ NTSTATUS
 NTAPI
 HidParser_SetUsages(
     IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
     IN HIDP_REPORT_TYPE  ReportType,
     IN USAGE  UsagePage,
     IN USHORT  LinkCollection,
@@ -356,6 +357,7 @@ NTSTATUS
 NTAPI
 HidParser_SetUsageValueArray(
     IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
     IN HIDP_REPORT_TYPE  ReportType,
     IN USAGE  UsagePage,
     IN USHORT  LinkCollection  OPTIONAL,
@@ -370,6 +372,7 @@ NTSTATUS
 NTAPI
 HidParser_SetUsageValue(
     IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
     IN HIDP_REPORT_TYPE  ReportType,
     IN USAGE  UsagePage,
     IN USHORT  LinkCollection,
@@ -383,6 +386,7 @@ NTSTATUS
 NTAPI
 HidParser_SetScaledUsageValue(
     IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
     IN HIDP_REPORT_TYPE  ReportType,
     IN USAGE  UsagePage,
     IN USHORT  LinkCollection  OPTIONAL,
@@ -396,6 +400,7 @@ NTSTATUS
 NTAPI
 HidParser_SetData(
     IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
     IN HIDP_REPORT_TYPE  ReportType,
     IN PHIDP_DATA  DataList,
     IN OUT PULONG  DataLength,
@@ -407,6 +412,7 @@ ULONG
 NTAPI
 HidParser_MaxDataListLength(
     IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
     IN HIDP_REPORT_TYPE  ReportType);
 
 HIDAPI
@@ -414,6 +420,7 @@ NTSTATUS
 NTAPI
 HidParser_InitializeReportForID(
     IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
     IN HIDP_REPORT_TYPE  ReportType,
     IN UCHAR  ReportID,
     IN OUT PCHAR  Report,
@@ -422,7 +429,6 @@ HidParser_InitializeReportForID(
 HIDPARSER_STATUS
 HidParser_TranslateUsage(
     IN PHID_PARSER Parser,
-    IN ULONG CollectionNumber,
     IN USAGE Usage,
     IN HIDP_KEYBOARD_DIRECTION  KeyAction,
     IN OUT PHIDP_KEYBOARD_MODIFIER_STATE  ModifierState,
@@ -434,6 +440,7 @@ NTSTATUS
 NTAPI
 HidParser_GetValueCaps(
     PHID_PARSER Parser,
+    IN PVOID CollectionContext,
     HIDP_REPORT_TYPE ReportType,
     PHIDP_VALUE_CAPS ValueCaps,
     PULONG ValueCapsLength);
index 4bb494b..998bce4 100644 (file)
@@ -123,40 +123,6 @@ HidParser_AllocateCollection(
     return HIDPARSER_STATUS_SUCCESS;
 }
 
-
-VOID
-HidParser_ResetParser(
-    OUT PHID_PARSER Parser)
-{
-    ULONG Index;
-    PHID_PARSER_CONTEXT ParserContext;
-
-    //
-    // get parser context
-    //
-    ParserContext = (PHID_PARSER_CONTEXT)Parser->ParserContext;
-
-    if (ParserContext->RootCollection)
-    {
-        //
-        // delete root collection
-        //
-        HidParser_FreeCollection(Parser, ParserContext->RootCollection);
-    }
-
-    //
-    // reinit parser
-    //
-    ParserContext->RootCollection = NULL;
-    ParserContext->UseReportIDs = FALSE;
-
-    //
-    // zero item states
-    //
-    Parser->Zero(&ParserContext->GlobalItemState, sizeof(GLOBAL_ITEM_STATE));
-    Parser->Zero(&ParserContext->LocalItemState, sizeof(LOCAL_ITEM_STATE));
-}
-
 HIDPARSER_STATUS
 HidParser_AddCollection(
     IN PHID_PARSER Parser,
@@ -260,18 +226,11 @@ HidParser_FindReportInCollection(
 HIDPARSER_STATUS
 HidParser_FindReport(
     IN PHID_PARSER Parser,
+    IN PHID_PARSER_CONTEXT ParserContext,
     IN UCHAR ReportType,
     IN UCHAR ReportID,
     OUT PHID_REPORT *OutReport)
 {
-    PHID_PARSER_CONTEXT ParserContext;
-
-    //
-    // get parser context
-    //
-    ParserContext = (PHID_PARSER_CONTEXT)Parser->ParserContext;
-    ASSERT(ParserContext);
-
     //
     // search in current top level collection
     //
@@ -315,17 +274,11 @@ HidParser_AllocateReport(
 HIDPARSER_STATUS
 HidParser_AddReportToCollection(
     IN PHID_PARSER Parser,
+    IN PHID_PARSER_CONTEXT ParserContext,
     IN PHID_COLLECTION CurrentCollection,
     IN PHID_REPORT NewReport)
 {
     PHID_REPORT * NewReportArray;
-    PHID_PARSER_CONTEXT ParserContext;
-
-    //
-    // get parser context
-    //
-    ParserContext = (PHID_PARSER_CONTEXT)Parser->ParserContext;
-    ASSERT(ParserContext);
 
     //
     // allocate new report array
@@ -368,6 +321,7 @@ HidParser_AddReportToCollection(
 HIDPARSER_STATUS
 HidParser_GetReport(
     IN PHID_PARSER Parser,
+    IN PHID_PARSER_CONTEXT ParserContext,
     IN PHID_COLLECTION Collection,
     IN UCHAR ReportType,
     IN UCHAR ReportID,
@@ -379,7 +333,7 @@ HidParser_GetReport(
     //
     // try finding existing report
     //
-    Status = HidParser_FindReport(Parser, ReportType, ReportID, OutReport);
+    Status = HidParser_FindReport(Parser, ParserContext, ReportType, ReportID, OutReport);
     if (Status == HIDPARSER_STATUS_SUCCESS || CreateIfNotExists == FALSE)
     {
         //
@@ -403,7 +357,7 @@ HidParser_GetReport(
     //
     // add report
     //
-    Status = HidParser_AddReportToCollection(Parser, Collection, *OutReport);
+    Status = HidParser_AddReportToCollection(Parser, ParserContext, Collection, *OutReport);
     if (Status != HIDPARSER_STATUS_SUCCESS)
     {
         //
@@ -418,132 +372,36 @@ HidParser_GetReport(
     return Status;
 }
 
-
-HIDPARSER_STATUS
-HidParser_ReserveCollectionItems(
-    IN PHID_PARSER Parser,
-    IN PHID_COLLECTION Collection,
-    IN ULONG ReportCount)
-{
-    PHID_REPORT_ITEM * NewReportArray;
-
-    if (Collection->ItemCount + ReportCount <= Collection->ItemCountAllocated)
-    {
-        //
-        // enough space for the next items
-        //
-        return HIDPARSER_STATUS_SUCCESS;
-    }
-
-    //
-    // allocate report array
-    //
-    NewReportArray = (PHID_REPORT_ITEM*)Parser->Alloc(sizeof(PHID_REPORT) * (Collection->ItemCountAllocated + ReportCount));
-    if (!NewReportArray)
-    {
-        //
-        // no memory
-        //
-        return HIDPARSER_STATUS_INSUFFICIENT_RESOURCES;
-    }
-
-    //
-    // are there any items
-    //
-    if (Collection->ItemCount)
-    {
-        //
-        // copy old items
-        //
-        Parser->Copy(NewReportArray, Collection->Items, sizeof(PHID_REPORT_ITEM) * Collection->ItemCount);
-
-        //
-        // free old item
-        //
-        Parser->Free(Collection->Items);
-    }
-
-    //
-    // replace array
-    //
-    Collection->Items = NewReportArray;
-    Collection->ItemCountAllocated += ReportCount;
-
-    //
-    // completed sucessfully
-    //
-    return HIDPARSER_STATUS_SUCCESS;
-}
-
-
 HIDPARSER_STATUS
 HidParser_ReserveReportItems(
     IN PHID_PARSER Parser,
     IN PHID_REPORT Report,
-    IN ULONG ReportCount)
+    IN ULONG ReportCount,
+    OUT PHID_REPORT *OutReport)
 {
-    PHID_REPORT_ITEM * NewReportArray;
+    PHID_REPORT NewReport;
+    ULONG OldSize, Size;
 
     if (Report->ItemCount + ReportCount <= Report->ItemAllocated)
     {
         //
-        // enough space for the next items
+        // space is already allocated
         //
+        *OutReport = Report;
         return HIDPARSER_STATUS_SUCCESS;
     }
 
     //
-    // allocate report array
-    //
-    NewReportArray = (PHID_REPORT_ITEM*)Parser->Alloc(sizeof(PHID_REPORT_ITEM) * (Report->ItemAllocated + ReportCount));
-    if (!NewReportArray)
-    {
-        //
-        // no memory
-        //
-        return HIDPARSER_STATUS_INSUFFICIENT_RESOURCES;
-    }
-
-    //
-    // are there any items
-    //
-    if (Report->ItemCount)
-    {
-        //
-        // copy old items
-        //
-        Parser->Copy(NewReportArray, Report->Items, sizeof(PHID_REPORT_ITEM) * Report->ItemCount);
-
-        //
-        // free old item
-        //
-        Parser->Free(Report->Items);
-    }
-
-    //
-    // replace array
-    //
-    Report->Items = NewReportArray;
-    Report->ItemAllocated += ReportCount;
-
-    //
-    // completed sucessfully
+    //calculate new size
     //
-    return HIDPARSER_STATUS_SUCCESS;
-}
-
-HIDPARSER_STATUS
-HidParser_AllocateReportItem(
-    IN PHID_PARSER Parser,
-    OUT PHID_REPORT_ITEM * OutReportItem)
-{
-    PHID_REPORT_ITEM ReportItem;
+    OldSize = sizeof(HID_REPORT) + (Report->ItemCount) * sizeof(HID_REPORT_ITEM);
+    Size =  ReportCount * sizeof(HID_REPORT_ITEM);
 
     //
-    // allocate report item
+    // allocate memory
     //
-    ReportItem = (PHID_REPORT_ITEM)Parser->Alloc(sizeof(HID_REPORT_ITEM));
-    if (!ReportItem)
+    NewReport = (PHID_REPORT)Parser->Alloc(Size + OldSize);
+    if (!NewReport)
     {
         //
         // no memory
@@ -551,45 +409,26 @@ HidParser_AllocateReportItem(
         return HIDPARSER_STATUS_INSUFFICIENT_RESOURCES;
     }
 
-    //
-    // store result
-    //
-    *OutReportItem = ReportItem;
-    return HIDPARSER_STATUS_SUCCESS;
-}
 
-VOID
-HidParser_AddReportItemToReport(
-    IN OUT PHID_REPORT Report,
-    IN PHID_REPORT_ITEM ReportItem)
-{
     //
-    // there should be space in item array
+    // copy old report
     //
-    ASSERT(Report->ItemCount + 1 <= Report->ItemAllocated);
+    Parser->Copy(NewReport, Report, OldSize);
 
     //
-    // store item
+    // increase array size
     //
-    Report->Items[Report->ItemCount] = ReportItem;
-    Report->ItemCount++;
-}
+    NewReport->ItemAllocated += ReportCount;
 
-VOID
-HidParser_AddReportItemToCollection(
-    IN OUT PHID_COLLECTION Collection,
-    IN PHID_REPORT_ITEM ReportItem)
-{
     //
-    // there should be space in item array
+    // store result
     //
-    ASSERT(Collection->ItemCount + 1 <= Collection->ItemCountAllocated);
+    *OutReport = NewReport;
 
     //
-    // store item
+    // completed sucessfully
     //
-    Collection->Items[Collection->ItemCount] = ReportItem;
-    Collection->ItemCount++;
+    return HIDPARSER_STATUS_SUCCESS;
 }
 
 VOID
@@ -745,23 +584,87 @@ HidParser_InitReportItem(
     return HIDPARSER_STATUS_SUCCESS;
 }
 
+BOOLEAN
+HidParser_UpdateCurrentCollectionReport(
+    IN PHID_COLLECTION Collection,
+    IN PHID_REPORT Report,
+    IN PHID_REPORT NewReport)
+{
+    ULONG Index;
+    BOOLEAN Found = FALSE, TempFound;
+
+    //
+    // search in local list
+    //
+    for(Index = 0; Index < Collection->ReportCount; Index++)
+    {
+        if (Collection->Reports[Index] == Report)
+        {
+            //
+            // update report
+            //
+            Collection->Reports[Index] = NewReport;
+            Found = TRUE;
+        }
+    }
+
+    //
+    // search in sub collections
+    //
+    for(Index = 0; Index < Collection->NodeCount; Index++)
+    {
+        //
+        // was it found
+        //
+        TempFound = HidParser_UpdateCurrentCollectionReport(Collection->Nodes[Index], Report, NewReport);
+        if (TempFound)
+        {
+            //
+            // the same report should not be found in different collections
+            //
+            ASSERT(Found == FALSE);
+            Found = TRUE;
+        }
+    }
+
+    //
+    // done
+    //
+    return Found;
+}
+
+BOOLEAN
+HidParser_UpdateCollectionReport(
+    IN PHID_PARSER_CONTEXT ParserContext,
+    IN PHID_REPORT Report,
+    IN PHID_REPORT NewReport)
+{
+    //
+    // update in current collection
+    //
+    return HidParser_UpdateCurrentCollectionReport(ParserContext->RootCollection->Nodes[ParserContext->RootCollection->NodeCount-1], Report, NewReport);
+}
+
+
 HIDPARSER_STATUS
 HidParser_AddMainItem(
     IN PHID_PARSER Parser,
+    IN PHID_PARSER_CONTEXT ParserContext,
     IN PHID_REPORT Report,
     IN PGLOBAL_ITEM_STATE GlobalItemState,
     IN PLOCAL_ITEM_STATE LocalItemState,
     IN PMAIN_ITEM_DATA ItemData,
     IN PHID_COLLECTION Collection)
 {
-    PHID_REPORT_ITEM ReportItem;
     HIDPARSER_STATUS Status;
     ULONG Index;
+    PHID_REPORT NewReport;
+    BOOLEAN Found;
 
     //
     // first grow report item array
     //
-    Status = HidParser_ReserveReportItems(Parser, Report, GlobalItemState->ReportCount);
+    Status = HidParser_ReserveReportItems(Parser, Report, GlobalItemState->ReportCount, &NewReport);
     if (Status != HIDPARSER_STATUS_SUCCESS)
     {
         //
@@ -770,35 +673,23 @@ HidParser_AddMainItem(
         return Status;
     }
 
-    //
-    // grow collection item array
-    //
-    Status = HidParser_ReserveCollectionItems(Parser, Collection, GlobalItemState->ReportCount);
-    if (Status != HIDPARSER_STATUS_SUCCESS)
+    if (NewReport != Report)
     {
         //
-        // failed to allocate memory
+        // update current top level collection
         //
-        return Status;
+        Found = HidParser_UpdateCollectionReport(ParserContext, Report, NewReport);
+        ASSERT(Found);
     }
 
-
+    //
+    // sanity check
+    //
+    ASSERT(NewReport->ItemCount + GlobalItemState->ReportCount <= NewReport->ItemAllocated);
 
     for(Index = 0; Index < GlobalItemState->ReportCount; Index++)
     {
-        //
-        // create report item
-        //
-        Status = HidParser_AllocateReportItem(Parser, &ReportItem);
-        if (Status != HIDPARSER_STATUS_SUCCESS)
-        {
-            //
-            // failed to allocate memory
-            //
-            return Status;
-        }
-
-        Status = HidParser_InitReportItem(Report, ReportItem, GlobalItemState, LocalItemState, ItemData, Index);
+        Status = HidParser_InitReportItem(NewReport, &NewReport->Items[NewReport->ItemCount], GlobalItemState, LocalItemState, ItemData, Index);
         if (Status != HIDPARSER_STATUS_SUCCESS)
         {
             //
@@ -808,10 +699,9 @@ HidParser_AddMainItem(
         }
 
         //
-        // add report item
+        // increment report item count
         //
-        HidParser_AddReportItemToReport(Report, ReportItem);
-        HidParser_AddReportItemToCollection(Collection, ReportItem);
+        NewReport->ItemCount++;
     }
 
     //
@@ -820,11 +710,36 @@ HidParser_AddMainItem(
     return HIDPARSER_STATUS_SUCCESS;
 }
 
+HIDPARSER_STATUS
+AllocateParserContext(
+    IN PHID_PARSER Parser,
+    OUT PHID_PARSER_CONTEXT *OutParserContext)
+{
+    PHID_PARSER_CONTEXT ParserContext;
+
+    ParserContext = Parser->Alloc(sizeof(HID_PARSER_CONTEXT));
+    if (!ParserContext)
+    {
+        //
+        // failed
+        //
+        return HIDPARSER_STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    //
+    // store result
+    //
+    *OutParserContext = ParserContext;
+    return HIDPARSER_STATUS_SUCCESS;
+}
+
+
 HIDPARSER_STATUS
 HidParser_ParseReportDescriptor(
     IN PHID_PARSER Parser,
     IN PUCHAR ReportDescriptor,
-    IN ULONG ReportLength)
+    IN ULONG ReportLength,
+    OUT PVOID *OutParser)
 {
     PGLOBAL_ITEM_STATE LinkedGlobalItemState, NextLinkedGlobalItemState;
     ULONG Index;
@@ -843,15 +758,12 @@ HidParser_ParseReportDescriptor(
     PHID_PARSER_CONTEXT ParserContext;
 
     //
-    // reset parser
+    // allocate parser
     //
-    HidParser_ResetParser(Parser);
+    Status = AllocateParserContext(Parser, &ParserContext);
+    if (Status != HIDPARSER_STATUS_SUCCESS)
+        return Status;
 
-    //
-    // get parser context
-    //
-    ParserContext =(PHID_PARSER_CONTEXT)Parser->ParserContext;
-    ASSERT(ParserContext);
 
     //
     // allocate usage stack
@@ -1039,7 +951,7 @@ HidParser_ParseReportDescriptor(
                     //
                     // get report
                     //
-                    Status = HidParser_GetReport(Parser, CurrentCollection, ReportType, ParserContext->GlobalItemState.ReportId, TRUE, &Report);
+                    Status = HidParser_GetReport(Parser, ParserContext, CurrentCollection, ReportType, ParserContext->GlobalItemState.ReportId, TRUE, &Report);
                     ASSERT(Status == HIDPARSER_STATUS_SUCCESS);
 
                     // fill in a sensible default if the index isn't set
@@ -1059,7 +971,7 @@ HidParser_ParseReportDescriptor(
                     //
                     // add states & data to the report
                     //
-                    Status = HidParser_AddMainItem(Parser, Report, &ParserContext->GlobalItemState, &ParserContext->LocalItemState, MainItemData, CurrentCollection);
+                    Status = HidParser_AddMainItem(Parser, ParserContext, Report, &ParserContext->GlobalItemState, &ParserContext->LocalItemState, MainItemData, CurrentCollection);
                     ASSERT(Status == HIDPARSER_STATUS_SUCCESS);
                 }
 
@@ -1348,8 +1260,140 @@ HidParser_ParseReportDescriptor(
     Parser->Free(ParserContext->LocalItemState.UsageStack);
     ParserContext->LocalItemState.UsageStack = NULL;
 
+    //
+    // store result
+    //
+    *OutParser = ParserContext;
+
     //
     // done
     //
     return HIDPARSER_STATUS_SUCCESS;
 }
+
+PHID_COLLECTION
+HidParser_GetCollection(
+    IN PHID_PARSER Parser,
+    PHID_PARSER_CONTEXT ParserContext,
+    IN ULONG CollectionNumber)
+{
+    //
+    // sanity checks
+    //
+    ASSERT(ParserContext);
+    ASSERT(ParserContext->RootCollection);
+    ASSERT(ParserContext->RootCollection->NodeCount);
+
+    //
+    // is collection index out of bounds
+    //
+    if (CollectionNumber < ParserContext->RootCollection->NodeCount)
+    {
+        //
+        // valid collection
+        //
+        return ParserContext->RootCollection->Nodes[CollectionNumber];
+    }
+
+    //
+    // no such collection
+    //
+    Parser->Debug("HIDPARSE] No such collection %lu\n", CollectionNumber);
+    return NULL;
+}
+
+
+ULONG
+HidParser_NumberOfTopCollections(
+    IN PVOID ParserCtx)
+{
+    PHID_PARSER_CONTEXT ParserContext;
+
+    //
+    // get parser context
+    //
+    ParserContext = (PHID_PARSER_CONTEXT)ParserCtx;
+
+    //
+    // sanity checks
+    //
+    ASSERT(ParserContext);
+    ASSERT(ParserContext->RootCollection);
+    ASSERT(ParserContext->RootCollection->NodeCount);
+
+    //
+    // number of top collections
+    //
+    return ParserContext->RootCollection->NodeCount;
+}
+
+HIDPARSER_STATUS
+HidParser_BuildContext(
+    IN PHID_PARSER Parser,
+    IN PVOID ParserContext,
+    IN ULONG CollectionIndex,
+    IN ULONG ContextSize,
+    OUT PVOID *CollectionContext)
+{
+    PHID_COLLECTION Collection;
+    PVOID Context;
+    HIDPARSER_STATUS Status;
+
+    //
+    // lets get the collection
+    //
+    Collection = HidParser_GetCollection(Parser, (PHID_PARSER_CONTEXT)ParserContext, CollectionIndex);
+    ASSERT(Collection);
+
+    //
+    // lets allocate the context
+    //
+    Context = Parser->Alloc(ContextSize);
+    if (Context == NULL)
+    {
+        //
+        // no memory
+        //
+        return HIDPARSER_STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    //
+    // lets build the context
+    //
+    Status = HidParser_BuildCollectionContext(Parser, Collection, Context, ContextSize);
+    if (Status == HIDPARSER_STATUS_SUCCESS)
+    {
+        //
+        // store context
+        //
+        *CollectionContext = Context;
+    }
+
+    //
+    // done
+    //
+    return Status;
+}
+
+
+ULONG
+HidParser_GetContextSize(
+    IN PHID_PARSER Parser,
+    IN PVOID ParserContext,
+    IN ULONG CollectionIndex)
+{
+    PHID_COLLECTION Collection;
+    ULONG Size;
+
+    //
+    // lets get the collection
+    //
+    Collection = HidParser_GetCollection(Parser, (PHID_PARSER_CONTEXT)ParserContext, CollectionIndex);
+
+    //
+    // calculate size
+    //
+    Size = HidParser_CalculateContextSize(Collection);
+    return Size;
+}
+
index 1a633a9..24a6aab 100644 (file)
@@ -199,23 +199,19 @@ struct _HID_REPORT;
 
 typedef struct __HID_COLLECTION__
 {
-    struct __HID_COLLECTION__ * Root;
-
     UCHAR Type;
     ULONG Usage;
     UCHAR StringID;
     UCHAR PhysicalID;
+    ULONG ReportCount;
     ULONG NodeCount;
-    struct __HID_COLLECTION__ ** Nodes;
 
-    ULONG ItemCount;
-    ULONG ItemCountAllocated;
-
-    PHID_REPORT_ITEM * Items;
-
-    ULONG ReportCount;
+    struct __HID_COLLECTION__ ** Nodes;
+    struct __HID_COLLECTION__ * Root;
     struct _HID_REPORT ** Reports; 
 
+    ULONG Offsets[1];
+
 }HID_COLLECTION, *PHID_COLLECTION;
 
 typedef struct _HID_REPORT
@@ -223,11 +219,9 @@ typedef struct _HID_REPORT
     UCHAR Type;
     UCHAR ReportID;
     ULONG ReportSize;
-
     ULONG ItemCount;
     ULONG ItemAllocated;
-    PHID_REPORT_ITEM* Items;
-
+    HID_REPORT_ITEM Items[1];
 }HID_REPORT, *PHID_REPORT;
 
 typedef struct
@@ -259,32 +253,20 @@ typedef struct
 
 }HID_PARSER_CONTEXT, *PHID_PARSER_CONTEXT;
 
-HIDPARSER_STATUS
-HidParser_ParseReportDescriptor(
-    PHID_PARSER Parser,
-    PUCHAR Report,
-    ULONG ReportSize);
-
-ULONG
-HidParser_NumberOfTopCollections(
-    IN PHID_PARSER Parser);
-
 #define HID_REPORT_TYPE_INPUT          0x01
 #define HID_REPORT_TYPE_OUTPUT         0x02
 #define HID_REPORT_TYPE_FEATURE                0x04
 
 HIDPARSER_STATUS
 HidParser_GetCollectionUsagePage(
-    IN PHID_PARSER Parser,
-    IN ULONG CollectionNumber,
+    IN PVOID CollectionContext,
     OUT PUSHORT Usage,
     OUT PUSHORT UsagePage);
 
 ULONG
 HidParser_GetReportLength(
-    IN PHID_PARSER Parser,
-    IN ULONG CollectionIndex,
-    IN ULONG ReportType);
+    IN PVOID CollectionContext,
+    IN UCHAR ReportType);
 
 UCHAR
 HidParser_IsReportIDUsed(
@@ -292,44 +274,26 @@ HidParser_IsReportIDUsed(
 
 ULONG
 HidParser_GetReportItemCountFromReportType(
-    IN PHID_PARSER Parser,
-    IN ULONG CollectionNumber,
-    IN ULONG ReportType);
+    IN PVOID CollectionContext,
+    IN UCHAR ReportType);
 
 ULONG
 HidParser_GetReportItemTypeCountFromReportType(
-    IN PHID_PARSER Parser,
-    IN ULONG CollectionNumber,
-    IN ULONG ReportType,
+    IN PVOID CollectionContext,
+    IN UCHAR ReportType,
     IN ULONG bData);
 
-ULONG
-HidParser_GetContextSize(
-    IN PHID_PARSER Parser,
-    IN ULONG CollectionNumber);
-
-VOID
-HidParser_FreeContext(
-    IN PHID_PARSER Parser,
-    IN PUCHAR Context,
-    IN ULONG ContextLength);
-
-ULONG
-HidParser_GetTotalCollectionCount(
-    IN PHID_PARSER Parser);
-
 ULONG
 HidParser_GetMaxUsageListLengthWithReportAndPage(
-    IN PHID_PARSER Parser,
-    IN ULONG CollectionNumber,
-    IN ULONG  ReportType,
+    IN PVOID CollectionContext,
+    IN UCHAR  ReportType,
     IN USAGE  UsagePage  OPTIONAL);
 
 HIDPARSER_STATUS
 HidParser_GetSpecificValueCapsWithReport(
     IN PHID_PARSER Parser,
-    IN ULONG CollectionNumber,
-    IN ULONG ReportType,
+    IN PVOID CollectionContext,
+    IN UCHAR ReportType,
     IN USHORT UsagePage,
     IN USHORT Usage,
     OUT PHIDP_VALUE_CAPS  ValueCaps,
@@ -339,8 +303,8 @@ HidParser_GetSpecificValueCapsWithReport(
 HIDPARSER_STATUS
 HidParser_GetUsagesWithReport(
     IN PHID_PARSER Parser,
-    IN ULONG CollectionNumber,
-    IN ULONG  ReportType,
+    IN PVOID CollectionContext,
+    IN UCHAR  ReportType,
     IN USAGE  UsagePage,
     OUT USAGE  *UsageList,
     IN OUT PULONG UsageLength,
@@ -350,15 +314,64 @@ HidParser_GetUsagesWithReport(
 HIDPARSER_STATUS
 HidParser_GetScaledUsageValueWithReport(
     IN PHID_PARSER Parser,
-    IN ULONG CollectionNumber,
-    IN ULONG ReportType,
+    IN PVOID CollectionContext,
+    IN UCHAR ReportType,
     IN USAGE UsagePage,
     IN USAGE  Usage,
     OUT PLONG UsageValue,
     IN PCHAR ReportDescriptor,
     IN ULONG ReportDescriptorLength);
 
+/* parser.c */
+
+HIDPARSER_STATUS
+HidParser_BuildContext(
+    IN PHID_PARSER Parser,
+    IN PVOID ParserContext,
+    IN ULONG CollectionIndex,
+    IN ULONG ContextSize,
+    OUT PVOID *CollectionContext);
+
 ULONG
-HidParser_GetCollectionNumberFromParserContext(
-    IN PHID_PARSER Parser);
+HidParser_CalculateContextSize(
+    IN PHID_COLLECTION Collection);
+
+HIDPARSER_STATUS
+HidParser_ParseReportDescriptor(
+    PHID_PARSER Parser,
+    PUCHAR Report,
+    ULONG ReportSize,
+    OUT PVOID *ParserContext);
 
+ULONG
+HidParser_NumberOfTopCollections(
+    IN PVOID ParserContext);
+
+ULONG
+HidParser_GetContextSize(
+    IN PHID_PARSER Parser,
+    IN PVOID ParserContext,
+    IN ULONG CollectionNumber);
+
+
+/* context.c */
+
+PHID_COLLECTION
+HidParser_GetCollectionFromContext(
+    IN PVOID Context);
+
+ULONG
+HidParser_GetTotalCollectionCount(
+    IN PVOID CollectionContext);
+
+HIDPARSER_STATUS
+HidParser_BuildCollectionContext(
+    IN PHID_PARSER Parser,
+    IN PHID_COLLECTION RootCollection,
+    IN PVOID Context,
+    IN ULONG ContextSize);
+
+PHID_REPORT
+HidParser_GetReportInCollection(
+    IN PVOID Context,
+    IN UCHAR ReportType);