[HIDPARSER]
[reactos.git] / lib / drivers / hidparser / parser.c
index d86b6df..998bce4 100644 (file)
@@ -123,62 +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;
-
-
-    //
-    // delete all reports
-    //
-    for(Index = 0; Index < ParserContext->ReportCount; Index++)
-    {
-        //
-        // delete report
-        //
-        HidParser_DeleteReport(Parser, ParserContext->Reports[Index]);
-    }
-
-    if (ParserContext->ReportCount && ParserContext->Reports)
-    {
-        //
-        // free report array
-        //
-       Parser->Free(ParserContext->Reports);
-    }
-
-    if (ParserContext->RootCollection)
-    {
-        //
-        // delete root collection
-        //
-        HidParser_FreeCollection(Parser, ParserContext->RootCollection);
-    }
-
-    //
-    // reinit parser
-    //
-    ParserContext->ReportCount = 0;
-    ParserContext->Reports = NULL;
-    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,
@@ -237,33 +181,40 @@ HidParser_AddCollection(
 }
 
 HIDPARSER_STATUS
-HidParser_FindReport(
-    IN PHID_PARSER Parser,
+HidParser_FindReportInCollection(
+    IN PHID_COLLECTION Collection,
     IN UCHAR ReportType,
     IN UCHAR ReportID,
     OUT PHID_REPORT *OutReport)
 {
-    PHID_PARSER_CONTEXT ParserContext;
     ULONG Index;
+    HIDPARSER_STATUS Status;
 
     //
-    // get parser context
+    // search in local list
     //
-    ParserContext = (PHID_PARSER_CONTEXT)Parser->ParserContext;
-    ASSERT(ParserContext);
-
-    for(Index = 0; Index < ParserContext->ReportCount; Index++)
+    for(Index = 0; Index < Collection->ReportCount; Index++)
     {
-        if (ParserContext->Reports[Index]->Type == ReportType && ParserContext->Reports[Index]->ReportID == ReportID)
+        if (Collection->Reports[Index]->Type == ReportType && Collection->Reports[Index]->ReportID == ReportID)
         {
             //
             // found report
             //
-            *OutReport = ParserContext->Reports[Index];
+            *OutReport = Collection->Reports[Index];
             return HIDPARSER_STATUS_SUCCESS;
         }
     }
 
+    //
+    // search in sub collections
+    //
+    for(Index = 0; Index < Collection->NodeCount; Index++)
+    {
+        Status = HidParser_FindReportInCollection(Collection->Nodes[Index], ReportType, ReportID, OutReport);
+        if (Status == HIDPARSER_STATUS_SUCCESS)
+            return Status;
+    }
+
     //
     // no such report found
     //
@@ -271,6 +222,21 @@ HidParser_FindReport(
     return HIDPARSER_STATUS_REPORT_NOT_FOUND;
 }
 
+
+HIDPARSER_STATUS
+HidParser_FindReport(
+    IN PHID_PARSER Parser,
+    IN PHID_PARSER_CONTEXT ParserContext,
+    IN UCHAR ReportType,
+    IN UCHAR ReportID,
+    OUT PHID_REPORT *OutReport)
+{
+    //
+    // search in current top level collection
+    //
+    return HidParser_FindReportInCollection(ParserContext->RootCollection->Nodes[ParserContext->RootCollection->NodeCount-1], ReportType, ReportID, OutReport);
+}
+
 HIDPARSER_STATUS
 HidParser_AllocateReport(
     IN PHID_PARSER Parser,
@@ -306,23 +272,18 @@ HidParser_AllocateReport(
 }
 
 HIDPARSER_STATUS
-HidParser_AddReport(
+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
     //
-    NewReportArray = (PHID_REPORT*)Parser->Alloc(sizeof(PHID_REPORT) * (ParserContext->ReportCount + 1));
+    NewReportArray = (PHID_REPORT*)Parser->Alloc(sizeof(PHID_REPORT) * (CurrentCollection->ReportCount + 1));
     if (!NewReportArray)
     {
         //
@@ -331,25 +292,25 @@ HidParser_AddReport(
         return HIDPARSER_STATUS_INSUFFICIENT_RESOURCES;
     }
 
-    if (ParserContext->ReportCount)
+    if (CurrentCollection->ReportCount)
     {
         //
         // copy old array contents
         //
-        Parser->Copy(NewReportArray, ParserContext->Reports, sizeof(PHID_REPORT) * ParserContext->ReportCount);
+        Parser->Copy(NewReportArray, CurrentCollection->Reports, sizeof(PHID_REPORT) * CurrentCollection->ReportCount);
 
         //
         // free old array
         //
-        Parser->Free(ParserContext->Reports);
+        Parser->Free(CurrentCollection->Reports);
     }
 
     //
     // store result
     //
-    NewReportArray[ParserContext->ReportCount] = NewReport;
-    ParserContext->Reports = NewReportArray;
-    ParserContext->ReportCount++;
+    NewReportArray[CurrentCollection->ReportCount] = NewReport;
+    CurrentCollection->Reports = NewReportArray;
+    CurrentCollection->ReportCount++;
 
     //
     // completed successfully
@@ -360,6 +321,8 @@ HidParser_AddReport(
 HIDPARSER_STATUS
 HidParser_GetReport(
     IN PHID_PARSER Parser,
+    IN PHID_PARSER_CONTEXT ParserContext,
+    IN PHID_COLLECTION Collection,
     IN UCHAR ReportType,
     IN UCHAR ReportID,
     IN UCHAR CreateIfNotExists,
@@ -370,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)
     {
         //
@@ -394,7 +357,7 @@ HidParser_GetReport(
     //
     // add report
     //
-    Status = HidParser_AddReport(Parser, *OutReport);
+    Status = HidParser_AddReportToCollection(Parser, ParserContext, Collection, *OutReport);
     if (Status != HIDPARSER_STATUS_SUCCESS)
     {
         //
@@ -409,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
+    //calculate new size
     //
-    NewReportArray = (PHID_REPORT_ITEM*)Parser->Alloc(sizeof(PHID_REPORT_ITEM) * (Report->ItemAllocated + ReportCount));
-    if (!NewReportArray)
-    {
-        //
-        // no memory
-        //
-        return HIDPARSER_STATUS_INSUFFICIENT_RESOURCES;
-    }
+    OldSize = sizeof(HID_REPORT) + (Report->ItemCount) * sizeof(HID_REPORT_ITEM);
+    Size =  ReportCount * sizeof(HID_REPORT_ITEM);
 
     //
-    // are there any items
+    // allocate memory
     //
-    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
-    //
-    return HIDPARSER_STATUS_SUCCESS;
-}
-
-HIDPARSER_STATUS
-HidParser_AllocateReportItem(
-    IN PHID_PARSER Parser,
-    OUT PHID_REPORT_ITEM * OutReportItem)
-{
-    PHID_REPORT_ITEM ReportItem;
-
-    //
-    // allocate report item
-    //
-    ReportItem = (PHID_REPORT_ITEM)Parser->Alloc(sizeof(HID_REPORT_ITEM));
-    if (!ReportItem)
+    NewReport = (PHID_REPORT)Parser->Alloc(Size + OldSize);
+    if (!NewReport)
     {
         //
         // no memory
@@ -542,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
@@ -736,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)
     {
         //
@@ -761,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)
         {
             //
@@ -799,10 +699,9 @@ HidParser_AddMainItem(
         }
 
         //
-        // add report item
+        // increment report item count
         //
-        HidParser_AddReportItemToReport(Report, ReportItem);
-        HidParser_AddReportItemToCollection(Collection, ReportItem);
+        NewReport->ItemCount++;
     }
 
     //
@@ -811,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;
@@ -834,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
@@ -925,7 +846,7 @@ HidParser_ParseReportDescriptor(
             }
 
         }
-
+        Parser->Debug("Tag %x Type %x Size %x Offset %lu Length %lu\n", CurrentItem->Tag, CurrentItem->Type, CurrentItem->Size,  ((ULONG_PTR)CurrentItem - (ULONG_PTR)ReportDescriptor), ReportLength);
         //
         // handle items
         //
@@ -1019,7 +940,7 @@ HidParser_ParseReportDescriptor(
                             break;
 
                         default:
-                            Parser->Debug("[HIDPARSE] Unknown ReportType %x\n", CurrentItem->Tag);
+                            Parser->Debug("[HIDPARSE] Unknown ReportType Tag %x Type %x Size %x CurrentItemSize %x\n", CurrentItem->Tag, CurrentItem->Type, CurrentItem->Size, CurrentItemSize);
                             ASSERT(FALSE);
                             break;
                     }
@@ -1030,7 +951,7 @@ HidParser_ParseReportDescriptor(
                     //
                     // get report
                     //
-                    Status = HidParser_GetReport(Parser, 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
@@ -1050,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);
                 }
 
@@ -1246,7 +1167,7 @@ HidParser_ParseReportDescriptor(
                         break;
 
                     case ITEM_TAG_LOCAL_USAGE_MAXIMUM:
-                        Parser->Debug("[HIDPARSE] ITEM_TAG_LOCAL_USAGE_MAXIMUM Data %x\n", Data);
+                        Parser->Debug("[HIDPARSE] ITEM_TAG_LOCAL_USAGE_MAXIMUM Data %x ItemSize %x %x\n", Data, CurrentItemSize, CurrentItem->Size);
                         ParserContext->LocalItemState.UsageMaximum.u.Extended = Data;
                         ParserContext->LocalItemState.UsageMaximum.IsExtended
                             = CurrentItemSize == sizeof(ULONG);
@@ -1339,9 +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;
+}
+