mirror of
https://github.com/reactos/reactos.git
synced 2025-08-06 08:32:58 +00:00

- 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
344 lines
7.7 KiB
C
344 lines
7.7 KiB
C
/*
|
|
* 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);
|
|
}
|