reactos/sdk/lib/drivers/hidparser/context.c

345 lines
7.7 KiB
C
Raw Normal View History

/*
* 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"
#define NDEBUG
#include <debug.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_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
//
CopyFunction(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
//
CopyFunction(&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->ReportCount + Index] = CurrentOffset;
//
// store sub collections
//
CurrentOffset += HidParser_StoreCollection(Collection->Nodes[Index], CollectionContext, CurrentOffset);
//
// sanity check
//
ASSERT(CurrentOffset < CollectionContext->Size);
}
//
// return size of collection
//
return CurrentOffset - InitialOffset;
}
NTSTATUS
HidParser_BuildCollectionContext(
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(RootCollection, CollectionContext, 0);
//
// sanity check
//
ASSERT(CollectionSize + sizeof(HID_COLLECTION_CONTEXT) == ContextSize);
DPRINT("CollectionContext %p\n", CollectionContext);
DPRINT("CollectionContext RawData %p\n", CollectionContext->RawData);
DPRINT("CollectionContext Size %lu\n", CollectionContext->Size);
//
// done
//
return HIDP_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->ReportCount + 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->ReportCount + 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);
}