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,
}
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
//
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,
}
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)
{
//
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
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,
//
// 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)
{
//
//
// add report
//
- Status = HidParser_AddReport(Parser, *OutReport);
+ Status = HidParser_AddReportToCollection(Parser, ParserContext, Collection, *OutReport);
if (Status != HIDPARSER_STATUS_SUCCESS)
{
//
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
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
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)
{
//
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)
{
//
}
//
- // add report item
+ // increment report item count
//
- HidParser_AddReportItemToReport(Report, ReportItem);
- HidParser_AddReportItemToCollection(Collection, ReportItem);
+ NewReport->ItemCount++;
}
//
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;
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
}
}
-
+ 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
//
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;
}
//
// 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
//
// 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);
}
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);
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;
+}
+