[USB-BRINGUP]

- Implement a HID parsing library, which is based on Haiku`s exellent HID Stack
- Implement HidP_FreeCollection, HidP_GetCaps, HidP_GetCollectionDescription, HidP_MaxUsageListLength, HidP_GetSpecificValueCaps, HidP_GetUsages, HidP_GetScaledUsageValue
- hidparse driver is now implemented enough to support a hid mouse
- Tested in VBox 4.1.4 + WinXP + ReactOS usbohci+ mouhid+ hidclass+ hidparse+hidusb

svn path=/branches/usb-bringup/; revision=54834
This commit is contained in:
Johannes Anderwald 2012-01-04 21:58:18 +00:00
parent 07ae01f96c
commit d1e00dac5c
10 changed files with 4490 additions and 376 deletions

View file

@ -2,7 +2,10 @@
spec2def(hidparse.sys hidparse.spec)
add_definitions(-DDEBUG_MODE)
include_directories(${REACTOS_SOURCE_DIR}/ntoskrnl/include)
include_directories(
${REACTOS_SOURCE_DIR}/ntoskrnl/include
${REACTOS_SOURCE_DIR}/lib/drivers/hidparser)
add_library(hidparse SHARED hidparse.c hidparse.rc ${CMAKE_CURRENT_BINARY_DIR}/hidparse.def)
@ -12,3 +15,5 @@ add_cab_target(hidparse 2)
add_cab_target(hidparse 2)
add_importlib_target(hidparse.spec)
target_link_libraries(hidparse hidparser)

View file

@ -10,27 +10,315 @@
#include "hidparse.h"
PVOID
NTAPI
AllocFunction(
IN ULONG ItemSize)
{
PVOID Item = ExAllocatePool(NonPagedPool, ItemSize);
if (Item)
{
//
// zero item
//
RtlZeroMemory(Item, ItemSize);
}
//
// done
//
return Item;
}
VOID
NTAPI
FreeFunction(
IN PVOID Item)
{
//
// free item
//
ExFreePool(Item);
}
VOID
NTAPI
ZeroFunction(
IN PVOID Item,
IN ULONG ItemSize)
{
//
// zero item
//
RtlZeroMemory(Item, ItemSize);
}
VOID
NTAPI
CopyFunction(
IN PVOID Target,
IN PVOID Source,
IN ULONG Length)
{
//
// copy item
//
RtlCopyMemory(Target, Source, Length);
}
VOID
NTAPI
DebugFunction(
IN LPCSTR FormatStr, ...)
{
va_list args;
unsigned int i;
char printbuffer[1024];
va_start(args, FormatStr);
i = vsprintf(printbuffer, FormatStr, args);
va_end(args);
DbgPrint(printbuffer);
}
VOID
NTAPI
HidP_FreeCollectionDescription (
IN PHIDP_DEVICE_DESC DeviceDescription)
{
DPRINT1("HidP_FreeCollectionDescription DeviceDescription %p\n", DeviceDescription);
HID_PARSER Parser;
//
// init parser
//
HidParser_InitParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, NULL, &Parser);
//
// free collection
//
ExFreePool(DeviceDescription->CollectionDesc);
//
// free report ids
//
ExFreePool(DeviceDescription->ReportIDs);
HidParser_FreeCollectionDescription(&Parser, DeviceDescription);
}
HIDAPI
NTSTATUS
NTAPI
HidP_GetCaps(
IN PHIDP_PREPARSED_DATA PreparsedData,
OUT PHIDP_CAPS Capabilities)
{
HID_PARSER Parser;
//
// init parser
//
HidParser_InitParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, PreparsedData, &Parser);
//
// get caps
//
return HidParser_GetCaps(&Parser, Capabilities);
}
NTSTATUS
NTAPI
HidP_GetCollectionDescription(
IN PHIDP_REPORT_DESCRIPTOR ReportDesc,
IN ULONG DescLength,
IN POOL_TYPE PoolType,
OUT PHIDP_DEVICE_DESC DeviceDescription)
{
PHID_PARSER Parser;
HIDPARSER_STATUS Status;
//
// first allocate the parser
//
Status = HidParser_AllocateParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, &Parser);
if (Status != HIDPARSER_STATUS_SUCCESS)
{
//
// not enough memory
//
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// get description;
//
Status = HidParser_GetCollectionDescription(Parser, ReportDesc, DescLength, PoolType, DeviceDescription);
//
// FIXME parser memory leak
//
return Status;
}
HIDAPI
ULONG
NTAPI
HidP_MaxUsageListLength(
IN HIDP_REPORT_TYPE ReportType,
IN USAGE UsagePage OPTIONAL,
IN PHIDP_PREPARSED_DATA PreparsedData)
{
HID_PARSER Parser;
//
// sanity check
//
ASSERT(ReportType == HidP_Input || ReportType == HidP_Output || ReportType == HidP_Feature);
//
// init parser
//
HidParser_InitParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, PreparsedData, &Parser);
//
// get usage length
//
return HidParser_MaxUsageListLength(&Parser, ReportType, UsagePage);
}
HIDAPI
NTSTATUS
NTAPI
HidP_GetSpecificValueCaps(
IN HIDP_REPORT_TYPE ReportType,
IN USAGE UsagePage,
IN USHORT LinkCollection,
IN USAGE Usage,
OUT PHIDP_VALUE_CAPS ValueCaps,
IN OUT PULONG ValueCapsLength,
IN PHIDP_PREPARSED_DATA PreparsedData)
{
HID_PARSER Parser;
//
// sanity check
//
ASSERT(ReportType == HidP_Input || ReportType == HidP_Output || ReportType == HidP_Feature);
//
// init parser
//
HidParser_InitParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, PreparsedData, &Parser);
//
// get value caps
//
return HidParser_GetSpecificValueCaps(&Parser, ReportType, UsagePage, LinkCollection, Usage, ValueCaps, ValueCapsLength);
}
HIDAPI
NTSTATUS
NTAPI
HidP_GetUsages(
IN HIDP_REPORT_TYPE ReportType,
IN USAGE UsagePage,
IN USHORT LinkCollection OPTIONAL,
OUT USAGE *UsageList,
IN OUT ULONG *UsageLength,
IN PHIDP_PREPARSED_DATA PreparsedData,
IN PCHAR Report,
IN ULONG ReportLength)
{
HID_PARSER Parser;
//
// sanity check
//
ASSERT(ReportType == HidP_Input || ReportType == HidP_Output || ReportType == HidP_Feature);
//
// init parser
//
HidParser_InitParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, PreparsedData, &Parser);
//
// get usages
//
return HidParser_GetUsages(&Parser, ReportType, UsagePage, LinkCollection, UsageList, UsageLength, Report, ReportLength);
}
#undef HidP_GetButtonCaps
HIDAPI
NTSTATUS
NTAPI
HidP_UsageListDifference(
IN PUSAGE PreviousUsageList,
IN PUSAGE CurrentUsageList,
OUT PUSAGE BreakUsageList,
OUT PUSAGE MakeUsageList,
IN ULONG UsageListLength)
{
return HidParser_UsageListDifference(PreviousUsageList, CurrentUsageList, BreakUsageList, MakeUsageList, UsageListLength);
}
HIDAPI
NTSTATUS
NTAPI
HidP_GetUsagesEx(
IN HIDP_REPORT_TYPE ReportType,
IN USHORT LinkCollection,
OUT PUSAGE_AND_PAGE ButtonList,
IN OUT ULONG *UsageLength,
IN PHIDP_PREPARSED_DATA PreparsedData,
IN PCHAR Report,
IN ULONG ReportLength)
{
return HidP_GetUsages(ReportType, HID_USAGE_PAGE_UNDEFINED, LinkCollection, (PUSAGE)ButtonList, UsageLength, PreparsedData, Report, ReportLength);
}
HIDAPI
NTSTATUS
NTAPI
HidP_UsageAndPageListDifference(
IN PUSAGE_AND_PAGE PreviousUsageList,
IN PUSAGE_AND_PAGE CurrentUsageList,
OUT PUSAGE_AND_PAGE BreakUsageList,
OUT PUSAGE_AND_PAGE MakeUsageList,
IN ULONG UsageListLength)
{
return HidParser_UsageAndPageListDifference(PreviousUsageList, CurrentUsageList, BreakUsageList, MakeUsageList, UsageListLength);
}
HIDAPI
NTSTATUS
NTAPI
HidP_GetScaledUsageValue(
IN HIDP_REPORT_TYPE ReportType,
IN USAGE UsagePage,
IN USHORT LinkCollection OPTIONAL,
IN USAGE Usage,
OUT PLONG UsageValue,
IN PHIDP_PREPARSED_DATA PreparsedData,
IN PCHAR Report,
IN ULONG ReportLength)
{
HID_PARSER Parser;
//
// sanity check
//
ASSERT(ReportType == HidP_Input || ReportType == HidP_Output || ReportType == HidP_Feature);
//
// init parser
//
HidParser_InitParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, PreparsedData, &Parser);
//
// get scaled usage value
//
return HidParser_GetScaledUsageValue(&Parser, ReportType, UsagePage, LinkCollection, Usage, UsageValue, Report, ReportLength);
}
HIDAPI
NTSTATUS
NTAPI
@ -60,32 +348,6 @@ HidP_GetSpecificButtonCaps(
return STATUS_NOT_IMPLEMENTED;
}
HIDAPI
NTSTATUS
NTAPI
HidP_GetCaps(
IN PHIDP_PREPARSED_DATA PreparsedData,
OUT PHIDP_CAPS Capabilities)
{
UNIMPLEMENTED
ASSERT(FALSE);
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
NTAPI
HidP_GetCollectionDescription(
IN PHIDP_REPORT_DESCRIPTOR ReportDesc,
IN ULONG DescLength,
IN POOL_TYPE PoolType,
OUT PHIDP_DEVICE_DESC DeviceDescription)
{
UNIMPLEMENTED
ASSERT(FALSE);
return STATUS_NOT_IMPLEMENTED;
}
HIDAPI
NTSTATUS
NTAPI
@ -107,7 +369,7 @@ NTSTATUS
NTAPI
HidP_GetExtendedAttributes(
IN HIDP_REPORT_TYPE ReportType,
IN USHORT DataIndex,
IN USAGE UsagePage,
IN PHIDP_PREPARSED_DATA PreparsedData,
OUT PHIDP_EXTENDED_ATTRIBUTES Attributes,
IN OUT PULONG LengthAttributes)
@ -130,24 +392,6 @@ HidP_GetLinkCollectionNodes(
return STATUS_NOT_IMPLEMENTED;
}
HIDAPI
NTSTATUS
NTAPI
HidP_GetScaledUsageValue(
IN HIDP_REPORT_TYPE ReportType,
IN USAGE UsagePage,
IN USHORT LinkCollection OPTIONAL,
IN USAGE Usage,
OUT PLONG UsageValue,
IN PHIDP_PREPARSED_DATA PreparsedData,
IN PCHAR Report,
IN ULONG ReportLength)
{
UNIMPLEMENTED
ASSERT(FALSE);
return STATUS_NOT_IMPLEMENTED;
}
HIDAPI
NTSTATUS
NTAPI
@ -166,185 +410,6 @@ HidP_GetUsageValue(
return STATUS_NOT_IMPLEMENTED;
}
HIDAPI
NTSTATUS
NTAPI
HidP_UsageListDifference(
IN PUSAGE PreviousUsageList,
IN PUSAGE CurrentUsageList,
OUT PUSAGE BreakUsageList,
OUT PUSAGE MakeUsageList,
IN ULONG UsageListLength)
{
ULONG Index, SubIndex, bFound, BreakUsageIndex = 0, MakeUsageIndex = 0;
USAGE CurrentUsage, Usage;
if (UsageListLength)
{
Index = 0;
do
{
/* get current usage */
CurrentUsage = PreviousUsageList[Index];
/* is the end of list reached? */
if (!CurrentUsage)
break;
/* start searching in current usage list */
SubIndex = 0;
bFound = FALSE;
do
{
/* get usage of current list */
Usage = CurrentUsageList[SubIndex];
/* end of list reached? */
if (!Usage)
break;
/* check if it matches the current one */
if (CurrentUsage == Usage)
{
/* it does */
bFound = TRUE;
break;
}
/* move to next usage */
SubIndex++;
}while(SubIndex < UsageListLength);
/* was the usage found ?*/
if (!bFound)
{
/* store it in the break usage list */
BreakUsageList[BreakUsageIndex] = CurrentUsage;
BreakUsageIndex++;
}
/* move to next usage */
Index++;
}while(Index < UsageListLength);
/* now process the new items */
Index = 0;
do
{
/* get current usage */
CurrentUsage = CurrentUsageList[Index];
/* is the end of list reached? */
if (!CurrentUsage)
break;
/* start searching in current usage list */
SubIndex = 0;
bFound = FALSE;
do
{
/* get usage of previous list */
Usage = PreviousUsageList[SubIndex];
/* end of list reached? */
if (!Usage)
break;
/* check if it matches the current one */
if (CurrentUsage == Usage)
{
/* it does */
bFound = TRUE;
break;
}
/* move to next usage */
SubIndex++;
}while(SubIndex < UsageListLength);
/* was the usage found ?*/
if (!bFound)
{
/* store it in the make usage list */
MakeUsageList[MakeUsageIndex] = CurrentUsage;
MakeUsageIndex++;
}
/* move to next usage */
Index++;
}while(Index < UsageListLength);
}
/* does the break list contain empty entries */
if (BreakUsageIndex < UsageListLength)
{
/* zeroize entries */
RtlZeroMemory(&BreakUsageList[BreakUsageIndex], sizeof(USAGE) * (UsageListLength - BreakUsageIndex));
}
/* does the make usage list contain empty entries */
if (MakeUsageIndex < UsageListLength)
{
/* zeroize entries */
RtlZeroMemory(&MakeUsageList[MakeUsageIndex], sizeof(USAGE) * (UsageListLength - MakeUsageIndex));
}
/* done */
return HIDP_STATUS_SUCCESS;
}
HIDAPI
NTSTATUS
NTAPI
HidP_GetSpecificValueCaps(
IN HIDP_REPORT_TYPE ReportType,
IN USAGE UsagePage,
IN USHORT LinkCollection,
IN USAGE Usage,
OUT PHIDP_VALUE_CAPS ValueCaps,
IN OUT PULONG ValueCapsLength,
IN PHIDP_PREPARSED_DATA PreparsedData)
{
UNIMPLEMENTED
ASSERT(FALSE);
return STATUS_NOT_IMPLEMENTED;
}
HIDAPI
ULONG
NTAPI
HidP_MaxUsageListLength(
IN HIDP_REPORT_TYPE ReportType,
IN USAGE UsagePage OPTIONAL,
IN PHIDP_PREPARSED_DATA PreparsedData)
{
UNIMPLEMENTED
ASSERT(FALSE);
return STATUS_NOT_IMPLEMENTED;
}
HIDAPI
NTSTATUS
NTAPI
HidP_GetUsages(
IN HIDP_REPORT_TYPE ReportType,
IN USAGE UsagePage,
IN USHORT LinkCollection OPTIONAL,
OUT USAGE *UsageList,
IN OUT ULONG *UsageLength,
IN PHIDP_PREPARSED_DATA PreparsedData,
IN PCHAR Report,
IN ULONG ReportLength)
{
UNIMPLEMENTED
ASSERT(FALSE);
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
NTAPI
HidP_SysPowerEvent (
@ -388,150 +453,6 @@ HidP_GetUsageValueArray(
return STATUS_NOT_IMPLEMENTED;
}
HIDAPI
NTSTATUS
NTAPI
HidP_GetUsagesEx(
IN HIDP_REPORT_TYPE ReportType,
IN USHORT LinkCollection,
OUT PUSAGE_AND_PAGE ButtonList,
IN OUT ULONG *UsageLength,
IN PHIDP_PREPARSED_DATA PreparsedData,
IN PCHAR Report,
IN ULONG ReportLength)
{
return HidP_GetUsages(ReportType, HID_USAGE_PAGE_UNDEFINED, LinkCollection, (PUSAGE)ButtonList, UsageLength, PreparsedData, Report, ReportLength);
}
HIDAPI
NTSTATUS
NTAPI
HidP_UsageAndPageListDifference(
IN PUSAGE_AND_PAGE PreviousUsageList,
IN PUSAGE_AND_PAGE CurrentUsageList,
OUT PUSAGE_AND_PAGE BreakUsageList,
OUT PUSAGE_AND_PAGE MakeUsageList,
IN ULONG UsageListLength)
{
ULONG Index, SubIndex, BreakUsageListIndex = 0, MakeUsageListIndex = 0, bFound;
PUSAGE_AND_PAGE CurrentUsage, Usage;
if (UsageListLength)
{
/* process removed usages */
Index = 0;
do
{
/* get usage from current index */
CurrentUsage = &PreviousUsageList[Index];
/* end of list reached? */
if (CurrentUsage->Usage == 0 && CurrentUsage->UsagePage == 0)
break;
/* search in current list */
SubIndex = 0;
bFound = FALSE;
do
{
/* get usage */
Usage = &CurrentUsageList[SubIndex];
/* end of list reached? */
if (Usage->Usage == 0 && Usage->UsagePage == 0)
break;
/* does it match */
if (Usage->Usage == CurrentUsage->Usage && Usage->UsagePage == CurrentUsage->UsagePage)
{
/* found match */
bFound = TRUE;
}
/* move to next index */
SubIndex++;
}while(SubIndex < UsageListLength);
if (!bFound)
{
/* store it in break usage list */
BreakUsageList[BreakUsageListIndex].Usage = CurrentUsage->Usage;
BreakUsageList[BreakUsageListIndex].UsagePage = CurrentUsage->UsagePage;
BreakUsageListIndex++;
}
/* move to next index */
Index++;
}while(Index < UsageListLength);
/* process new usages */
Index = 0;
do
{
/* get usage from current index */
CurrentUsage = &CurrentUsageList[Index];
/* end of list reached? */
if (CurrentUsage->Usage == 0 && CurrentUsage->UsagePage == 0)
break;
/* search in current list */
SubIndex = 0;
bFound = FALSE;
do
{
/* get usage */
Usage = &PreviousUsageList[SubIndex];
/* end of list reached? */
if (Usage->Usage == 0 && Usage->UsagePage == 0)
break;
/* does it match */
if (Usage->Usage == CurrentUsage->Usage && Usage->UsagePage == CurrentUsage->UsagePage)
{
/* found match */
bFound = TRUE;
}
/* move to next index */
SubIndex++;
}while(SubIndex < UsageListLength);
if (!bFound)
{
/* store it in break usage list */
MakeUsageList[MakeUsageListIndex].Usage = CurrentUsage->Usage;
MakeUsageList[MakeUsageListIndex].UsagePage = CurrentUsage->UsagePage;
MakeUsageListIndex++;
}
/* move to next index */
Index++;
}while(Index < UsageListLength);
}
/* are there remaining free list entries */
if (BreakUsageListIndex < UsageListLength)
{
/* zero them */
RtlZeroMemory(&BreakUsageList[BreakUsageListIndex], (UsageListLength - BreakUsageListIndex) * sizeof(USAGE_AND_PAGE));
}
/* are there remaining free list entries */
if (MakeUsageListIndex < UsageListLength)
{
/* zero them */
RtlZeroMemory(&MakeUsageList[MakeUsageListIndex], (UsageListLength - MakeUsageListIndex) * sizeof(USAGE_AND_PAGE));
}
/* done */
return HIDP_STATUS_SUCCESS;
}
HIDAPI
NTSTATUS

View file

@ -5,4 +5,6 @@
#include <ntddk.h>
#include <hidpddi.h>
#include <hidpi.h>
#define NDEBUG
#include <debug.h>
#include "hidparser.h"

View file

@ -1,6 +1,7 @@
add_subdirectory(chew)
add_subdirectory(csq)
add_subdirectory(hidparser)
add_subdirectory(ip)
add_subdirectory(oskittcp)
add_subdirectory(sound)

View file

@ -0,0 +1,13 @@
add_definitions(
-DUNICODE -D_UNICODE
-DNDEBUG=1)
list(APPEND SOURCE
hidparser.c
parser.c
api.c)
add_library(hidparser ${SOURCE})
add_dependencies(hidparser bugcodes)

953
lib/drivers/hidparser/api.c Normal file
View file

@ -0,0 +1,953 @@
/*
* PROJECT: ReactOS HID Parser Library
* LICENSE: GPL - See COPYING in the top level directory
* FILE: lib/drivers/hidparser/api.c
* PURPOSE: HID Parser
* PROGRAMMERS:
* Michael Martin (michael.martin@reactos.org)
* Johannes Anderwald (johannes.anderwald@reactos.org)
*/
#include "parser.h"
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_GetReportByType(
IN PHID_PARSER Parser,
IN ULONG ReportType)
{
PHID_PARSER_CONTEXT ParserContext;
ULONG Index;
ULONG ReportCount = 0;
//
// get parser context
//
ParserContext = (PHID_PARSER_CONTEXT)Parser->ParserContext;
//
// sanity checks
//
ASSERT(ParserContext);
//
// FIXME support multiple top collecions
//
ASSERT(ParserContext->RootCollection->NodeCount == 1);
for(Index = 0; Index < ParserContext->ReportCount; Index++)
{
//
// check if the report type match
//
if (ParserContext->Reports[Index]->Type == ReportType)
{
//
// found report
//
return ParserContext->Reports[Index];
}
}
//
// report not found
//
return NULL;
}
ULONG
HidParser_NumberOfReports(
IN PHID_PARSER Parser,
IN ULONG ReportType)
{
PHID_PARSER_CONTEXT ParserContext;
ULONG Index;
ULONG ReportCount = 0;
//
// get parser context
//
ParserContext = (PHID_PARSER_CONTEXT)Parser->ParserContext;
//
// sanity checks
//
ASSERT(ParserContext);
//
// FIXME support multiple top collecions
//
ASSERT(ParserContext->RootCollection->NodeCount == 1);
for(Index = 0; Index < ParserContext->ReportCount; Index++)
{
//
// check if the report type match
//
if (ParserContext->Reports[Index]->Type == ReportType)
{
//
// found report
//
ReportCount++;
}
}
//
// done
//
return ReportCount;
}
HIDPARSER_STATUS
HidParser_GetCollectionUsagePage(
IN PHID_PARSER Parser,
IN ULONG CollectionIndex,
OUT PUSHORT Usage,
OUT PUSHORT UsagePage)
{
PHID_COLLECTION Collection;
//
// find collection
//
Collection = HidParser_GetCollection(Parser, CollectionIndex);
if (!Collection)
{
//
// collection not found
//
return HIDPARSER_STATUS_COLLECTION_NOT_FOUND;
}
//
// store result
//
*UsagePage = (Collection->Usage >> 16);
*Usage = (Collection->Usage & 0xFFFF);
return HIDPARSER_STATUS_SUCCESS;
}
ULONG
HidParser_GetReportLength(
IN PHID_PARSER Parser,
IN ULONG 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, ReportType);
if (!Report)
{
//
// no report found
//
return 0;
}
//
// get report length
//
ReportLength = Report->ReportSize;
//
// done
//
if (ReportLength)
{
//
// byte aligned length
//
ASSERT(ReportLength % 8 == 0);
return ReportLength / 8;
}
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 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, ReportType);
if (!Report)
{
//
// no such report
//
return 0;
}
//
// return report item count
//
return Report->ItemCount;
}
ULONG
HidParser_GetReportItemTypeCountFromReportType(
IN PHID_PARSER Parser,
IN ULONG 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, ReportType);
if (!Report)
{
//
// no such report
//
return 0;
}
//
// enumerate all items
//
for(Index = 0; Index < Report->ItemCount; Index++)
{
//
// check item type
//
if (Report->Items[Index]->HasData && bData == TRUE)
{
//
// found data item
//
ItemCount++;
}
else if (Report->Items[Index]->HasData == FALSE && bData == FALSE)
{
//
// found value item
//
ItemCount++;
}
}
//
// no report items
//
return ItemCount;
}
ULONG
HidParser_GetContextSize(
IN PHID_PARSER Parser)
{
//
// 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(
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,
IN PVOID ParserContext,
OUT PHID_PARSER Parser)
{
Parser->Alloc = AllocFunction;
Parser->Free = FreeFunction;
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 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, ReportType);
if (!Report)
{
//
// no such report
//
return 0;
}
for(Index = 0; Index < Report->ItemCount; Index++)
{
//
// check usage page
//
CurrentUsagePage = (Report->Items[Index]->UsageMinimum >> 16);
if (CurrentUsagePage == UsagePage && Report->Items[Index]->HasData)
{
//
// found item
//
ItemCount++;
}
}
//
// done
//
return ItemCount;
}
HIDPARSER_STATUS
HidParser_GetSpecificValueCapsWithReport(
IN PHID_PARSER Parser,
IN ULONG 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, ReportType);
if (!Report)
{
//
// no such report
//
return HIDPARSER_STATUS_REPORT_NOT_FOUND;
}
for(Index = 0; Index < Report->ItemCount; Index++)
{
//
// check usage page
//
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))
{
//
// check if there is enough place for the caps
//
if (ItemCount < *ValueCapsLength)
{
//
// zero caps
//
Parser->Zero(&ValueCaps[ItemCount], sizeof(HIDP_VALUE_CAPS));
//
// init caps
//
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;
//
// FIXME: FILLMEIN
//
}
//
// found item
//
ItemCount++;
}
}
//
// store result
//
*ValueCapsLength = ItemCount;
if (ItemCount)
{
//
// success
//
return HIDPARSER_STATUS_SUCCESS;
}
//
// item not found
//
return HIDPARSER_STATUS_USAGE_NOT_FOUND;
}
HIDPARSER_STATUS
HidParser_GetUsagesWithReport(
IN PHID_PARSER Parser,
IN ULONG 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;
USHORT CurrentUsagePage;
PHID_REPORT_ITEM ReportItem;
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, ReportType);
if (!Report)
{
//
// no such report
//
return HIDPARSER_STATUS_REPORT_NOT_FOUND;
}
if (Report->ReportSize / 8 != (ReportDescriptorLength - 1))
{
//
// invalid report descriptor length
//
return HIDPARSER_STATUS_INVALID_REPORT_LENGTH;
}
for(Index = 0; Index < Report->ItemCount; Index++)
{
//
// get report item
//
ReportItem = Report->Items[Index];
//
// does it have data
//
if (!ReportItem->HasData)
continue;
//
// check usage page
//
CurrentUsagePage = (ReportItem->UsageMinimum >> 16);
//
// does usage match
//
if (UsagePage != CurrentUsagePage)
continue;
//
// check if the specified usage is activated
//
ASSERT(ReportItem->ByteOffset < ReportDescriptorLength);
ASSERT(ReportItem->BitCount < 8);
//
// one extra shift for skipping the prepended report id
//
Data = ReportDescriptor[ReportItem->ByteOffset + 1];
//
// shift data
//
Data >>= ReportItem->Shift;
//
// clear unwanted bits
//
Data &= ReportItem->Mask;
//
// is it activated
//
Activated = (Data != 0);
if (!Activated)
continue;
//
// is there enough space for the usage
//
if (ItemCount >= *UsageLength)
{
ItemCount++;
continue;
}
//
// store item
//
UsageList[ItemCount] = (ReportItem->UsageMinimum & 0xFFFF);
ItemCount++;
}
if (ItemCount > *UsageLength)
{
//
// list too small
//
return HIDPARSER_STATUS_BUFFER_TOO_SMALL;
}
//
// success, clear rest of array
//
Parser->Zero(&UsageList[ItemCount], (*UsageLength - ItemCount) * sizeof(USAGE));
//
// store result size
//
*UsageLength = ItemCount;
//
// done
//
return HIDPARSER_STATUS_SUCCESS;
}
HIDPARSER_STATUS
HidParser_GetScaledUsageValueWithReport(
IN PHID_PARSER Parser,
IN ULONG 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;
ULONG ItemCount = 0;
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, ReportType);
if (!Report)
{
//
// no such report
//
return HIDPARSER_STATUS_REPORT_NOT_FOUND;
}
if (Report->ReportSize / 8 != (ReportDescriptorLength - 1))
{
//
// invalid report descriptor length
//
return HIDPARSER_STATUS_INVALID_REPORT_LENGTH;
}
for(Index = 0; Index < Report->ItemCount; Index++)
{
//
// get report item
//
ReportItem = Report->Items[Index];
//
// check usage page
//
CurrentUsagePage = (ReportItem->UsageMinimum >> 16);
//
// does usage page match
//
if (UsagePage != CurrentUsagePage)
continue;
//
// does the usage match
//
if (Usage != (ReportItem->UsageMinimum & 0xFFFF))
continue;
//
// check if the specified usage is activated
//
ASSERT(ReportItem->ByteOffset < ReportDescriptorLength);
//
// one extra shift for skipping the prepended report id
//
Data = 0;
Parser->Copy(&Data, &ReportDescriptor[ReportItem->ByteOffset +1], min(sizeof(ULONG), ReportDescriptorLength - (ReportItem->ByteOffset + 1)));
Data = ReportDescriptor[ReportItem->ByteOffset + 1];
//
// shift data
//
Data >>= ReportItem->Shift;
//
// clear unwanted bits
//
Data &= ReportItem->Mask;
if (ReportItem->Minimum > ReportItem->Maximum)
{
//
// logical boundaries are signed values
//
if ((Data & ~(ReportItem->Mask >> 1)) != 0)
{
Data |= ~ReportItem->Mask;
}
}
//
// store result
//
*UsageValue = Data;
return HIDPARSER_STATUS_SUCCESS;
}
//
// usage not found
//
return HIDPARSER_STATUS_USAGE_NOT_FOUND;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,427 @@
/*
* PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
* LICENSE: GPL - See COPYING in the top level directory
* FILE: lib/drivers/hidparser/hidparser.c
* PURPOSE: HID Parser
* PROGRAMMERS:
* Michael Martin (michael.martin@reactos.org)
* Johannes Anderwald (johannes.anderwald@reactos.org)
*/
#pragma once
#define _HIDPI_
#define _HIDPI_NO_FUNCTION_MACROS_
#include <ntddk.h>
#include <hidpddi.h>
#include <hidpi.h>
#include <debug.h>
//
// function prototypes
//
typedef PVOID (NTAPI *PHIDPARSER_ALLOC_FUNCTION)(ULONG Size);
typedef VOID (NTAPI *PHIDPARSER_FREE_FUNCTION)(PVOID Item);
typedef VOID (NTAPI *PHIDPARSER_ZERO_FUNCTION)(PVOID Item, ULONG Size);
typedef VOID (NTAPI *PHIDPARSER_COPY_FUNCTION)(PVOID Target, PVOID Source, ULONG Size);
typedef VOID (NTAPI *PHIDPARSER_DEBUG_FUNCTION)(LPCSTR Src, ...);
//
// status code
//
typedef long HIDPARSER_STATUS;
//
// result codes
//
typedef enum
{
HIDPARSER_STATUS_SUCCESS = 0,
HIDPARSER_STATUS_INSUFFICIENT_RESOURCES = -1,
HIDPARSER_STATUS_NOT_IMPLEMENTED = -2,
HIDPARSER_STATUS_REPORT_NOT_FOUND = -3,
HIDPARSER_STATUS_COLLECTION_NOT_FOUND = -4,
HIDPARSER_STATUS_INVALID_REPORT_LENGTH = -5,
HIDPARSER_STATUS_INVALID_REPORT_TYPE = -6,
HIDPARSER_STATUS_BUFFER_TOO_SMALL = -7,
HIDPARSER_STATUS_USAGE_NOT_FOUND = 8
}HIDPARSER_STATUS_CODES;
typedef struct
{
//
// size of struct
//
unsigned long Size;
//
// allocation function
//
PHIDPARSER_ALLOC_FUNCTION Alloc;
//
// free function
//
PFREE_FUNCTION Free;
//
// zero function
//
PHIDPARSER_ZERO_FUNCTION Zero;
//
// copy function
//
PHIDPARSER_COPY_FUNCTION Copy;
//
// 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,
IN PHIDPARSER_FREE_FUNCTION FreeFunction,
IN PHIDPARSER_ZERO_FUNCTION ZeroFunction,
IN PHIDPARSER_COPY_FUNCTION CopyFunction,
IN PHIDPARSER_DEBUG_FUNCTION DebugFunction,
IN PVOID ParserContext,
OUT PHID_PARSER Parser);
NTSTATUS
NTAPI
HidParser_GetCollectionDescription(
IN PHID_PARSER Parser,
IN PHIDP_REPORT_DESCRIPTOR ReportDesc,
IN ULONG DescLength,
IN POOL_TYPE PoolType,
OUT PHIDP_DEVICE_DESC DeviceDescription);
VOID
NTAPI
HidParser_FreeCollectionDescription(
IN PHID_PARSER Parser,
IN PHIDP_DEVICE_DESC DeviceDescription);
HIDAPI
NTSTATUS
NTAPI
HidParser_GetCaps(
IN PHID_PARSER Parser,
OUT PHIDP_CAPS Capabilities);
HIDAPI
NTSTATUS
NTAPI
HidParser_GetSpecificValueCaps(
IN PHID_PARSER Parser,
IN HIDP_REPORT_TYPE ReportType,
IN USAGE UsagePage,
IN USHORT LinkCollection,
IN USAGE Usage,
OUT PHIDP_VALUE_CAPS ValueCaps,
IN OUT PULONG ValueCapsLength);
HIDAPI
NTSTATUS
NTAPI
HidParser_GetButtonCaps(
IN PHID_PARSER Parser,
HIDP_REPORT_TYPE ReportType,
PHIDP_BUTTON_CAPS ButtonCaps,
PUSHORT ButtonCapsLength);
HIDAPI
NTSTATUS
NTAPI
HidParser_GetSpecificButtonCaps(
IN PHID_PARSER Parser,
IN HIDP_REPORT_TYPE ReportType,
IN USAGE UsagePage,
IN USHORT LinkCollection,
IN USAGE Usage,
OUT PHIDP_BUTTON_CAPS ButtonCaps,
IN OUT PULONG ButtonCapsLength);
HIDAPI
NTSTATUS
NTAPI
HidParser_GetScaledUsageValue(
IN PHID_PARSER Parser,
IN HIDP_REPORT_TYPE ReportType,
IN USAGE UsagePage,
IN USHORT LinkCollection OPTIONAL,
IN USAGE Usage,
OUT PLONG UsageValue,
IN PCHAR Report,
IN ULONG ReportLength);
HIDAPI
NTSTATUS
NTAPI
HidParser_GetData(
IN HIDP_REPORT_TYPE ReportType,
OUT PHIDP_DATA DataList,
IN OUT PULONG DataLength,
IN PHIDP_PREPARSED_DATA PreparsedData,
IN PCHAR Report,
IN ULONG ReportLength);
HIDAPI
NTSTATUS
NTAPI
HidParser_GetExtendedAttributes(
IN HIDP_REPORT_TYPE ReportType,
IN USHORT DataIndex,
IN PHIDP_PREPARSED_DATA PreparsedData,
OUT PHIDP_EXTENDED_ATTRIBUTES Attributes,
IN OUT PULONG LengthAttributes);
HIDAPI
NTSTATUS
NTAPI
HidParser_GetLinkCollectionNodes(
OUT PHIDP_LINK_COLLECTION_NODE LinkCollectionNodes,
IN OUT PULONG LinkCollectionNodesLength,
IN PHIDP_PREPARSED_DATA PreparsedData);
HIDAPI
NTSTATUS
NTAPI
HidParser_GetUsageValue(
IN HIDP_REPORT_TYPE ReportType,
IN USAGE UsagePage,
IN USHORT LinkCollection,
IN USAGE Usage,
OUT PULONG UsageValue,
IN PHIDP_PREPARSED_DATA PreparsedData,
IN PCHAR Report,
IN ULONG ReportLength);
HIDAPI
NTSTATUS
NTAPI
HidParser_UsageListDifference(
IN PUSAGE PreviousUsageList,
IN PUSAGE CurrentUsageList,
OUT PUSAGE BreakUsageList,
OUT PUSAGE MakeUsageList,
IN ULONG UsageListLength);
HIDAPI
ULONG
NTAPI
HidParser_MaxUsageListLength(
IN PHID_PARSER Parser,
IN HIDP_REPORT_TYPE ReportType,
IN USAGE UsagePage OPTIONAL);
HIDAPI
NTSTATUS
NTAPI
HidParser_GetUsages(
IN PHID_PARSER Parser,
IN HIDP_REPORT_TYPE ReportType,
IN USAGE UsagePage,
IN USHORT LinkCollection OPTIONAL,
OUT USAGE *UsageList,
IN OUT ULONG *UsageLength,
IN PCHAR Report,
IN ULONG ReportLength);
HIDAPI
NTSTATUS
NTAPI
HidParser_GetUsagesEx(
IN PHID_PARSER Parser,
IN HIDP_REPORT_TYPE ReportType,
IN USHORT LinkCollection,
OUT PUSAGE_AND_PAGE ButtonList,
IN OUT ULONG *UsageLength,
IN PCHAR Report,
IN ULONG ReportLength);
NTSTATUS
NTAPI
HidParser_SysPowerEvent (
IN PCHAR HidPacket,
IN USHORT HidPacketLength,
IN PHIDP_PREPARSED_DATA Ppd,
OUT PULONG OutputBuffer);
NTSTATUS
NTAPI
HidParser_SysPowerCaps (
IN PHIDP_PREPARSED_DATA Ppd,
OUT PULONG OutputBuffer);
HIDAPI
NTSTATUS
NTAPI
HidParser_GetUsageValueArray(
IN HIDP_REPORT_TYPE ReportType,
IN USAGE UsagePage,
IN USHORT LinkCollection OPTIONAL,
IN USAGE Usage,
OUT PCHAR UsageValue,
IN USHORT UsageValueByteLength,
IN PHIDP_PREPARSED_DATA PreparsedData,
IN PCHAR Report,
IN ULONG ReportLength);
HIDAPI
NTSTATUS
NTAPI
HidParser_UsageAndPageListDifference(
IN PUSAGE_AND_PAGE PreviousUsageList,
IN PUSAGE_AND_PAGE CurrentUsageList,
OUT PUSAGE_AND_PAGE BreakUsageList,
OUT PUSAGE_AND_PAGE MakeUsageList,
IN ULONG UsageListLength);
HIDAPI
NTSTATUS
NTAPI
HidParser_UnsetUsages(
IN HIDP_REPORT_TYPE ReportType,
IN USAGE UsagePage,
IN USHORT LinkCollection,
IN PUSAGE UsageList,
IN OUT PULONG UsageLength,
IN PHIDP_PREPARSED_DATA PreparsedData,
IN OUT PCHAR Report,
IN ULONG ReportLength);
HIDAPI
NTSTATUS
NTAPI
HidParser_TranslateUsagesToI8042ScanCodes(
IN PUSAGE ChangedUsageList,
IN ULONG UsageListLength,
IN HIDP_KEYBOARD_DIRECTION KeyAction,
IN OUT PHIDP_KEYBOARD_MODIFIER_STATE ModifierState,
IN PHIDP_INSERT_SCANCODES InsertCodesProcedure,
IN PVOID InsertCodesContext);
HIDAPI
NTSTATUS
NTAPI
HidParser_TranslateUsageAndPagesToI8042ScanCodes(
IN PUSAGE_AND_PAGE ChangedUsageList,
IN ULONG UsageListLength,
IN HIDP_KEYBOARD_DIRECTION KeyAction,
IN OUT PHIDP_KEYBOARD_MODIFIER_STATE ModifierState,
IN PHIDP_INSERT_SCANCODES InsertCodesProcedure,
IN PVOID InsertCodesContext);
HIDAPI
NTSTATUS
NTAPI
HidParser_SetUsages(
IN HIDP_REPORT_TYPE ReportType,
IN USAGE UsagePage,
IN USHORT LinkCollection,
IN PUSAGE UsageList,
IN OUT PULONG UsageLength,
IN PHIDP_PREPARSED_DATA PreparsedData,
IN OUT PCHAR Report,
IN ULONG ReportLength);
HIDAPI
NTSTATUS
NTAPI
HidParser_SetUsageValueArray(
IN HIDP_REPORT_TYPE ReportType,
IN USAGE UsagePage,
IN USHORT LinkCollection OPTIONAL,
IN USAGE Usage,
IN PCHAR UsageValue,
IN USHORT UsageValueByteLength,
IN PHIDP_PREPARSED_DATA PreparsedData,
OUT PCHAR Report,
IN ULONG ReportLength);
HIDAPI
NTSTATUS
NTAPI
HidParser_SetUsageValue(
IN HIDP_REPORT_TYPE ReportType,
IN USAGE UsagePage,
IN USHORT LinkCollection,
IN USAGE Usage,
IN ULONG UsageValue,
IN PHIDP_PREPARSED_DATA PreparsedData,
IN OUT PCHAR Report,
IN ULONG ReportLength);
HIDAPI
NTSTATUS
NTAPI
HidParser_SetScaledUsageValue(
IN HIDP_REPORT_TYPE ReportType,
IN USAGE UsagePage,
IN USHORT LinkCollection OPTIONAL,
IN USAGE Usage,
IN LONG UsageValue,
IN PHIDP_PREPARSED_DATA PreparsedData,
IN OUT PCHAR Report,
IN ULONG ReportLength);
HIDAPI
NTSTATUS
NTAPI
HidParser_SetData(
IN HIDP_REPORT_TYPE ReportType,
IN PHIDP_DATA DataList,
IN OUT PULONG DataLength,
IN PHIDP_PREPARSED_DATA PreparsedData,
IN OUT PCHAR Report,
IN ULONG ReportLength);
HIDAPI
ULONG
NTAPI
HidParser_MaxDataListLength(
IN HIDP_REPORT_TYPE ReportType,
IN PHIDP_PREPARSED_DATA PreparsedData);
HIDAPI
NTSTATUS
NTAPI
HidParser_InitializeReportForID(
IN HIDP_REPORT_TYPE ReportType,
IN UCHAR ReportID,
IN PHIDP_PREPARSED_DATA PreparsedData,
IN OUT PCHAR Report,
IN ULONG ReportLength);
HIDAPI
NTSTATUS
NTAPI
HidParser_GetValueCaps(
HIDP_REPORT_TYPE ReportType,
PHIDP_VALUE_CAPS ValueCaps,
PULONG ValueCapsLength,
PHIDP_PREPARSED_DATA PreparsedData);

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,362 @@
#pragma once
#include <ntddk.h>
#include <assert.h>
#include <pshpack1.h>
#include "hidparser.h"
/*
* Copyright 2007, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*/
#define HID_REPORT_TYPE_ANY 0x07
#define ITEM_TYPE_MAIN 0x0
#define ITEM_TYPE_GLOBAL 0x1
#define ITEM_TYPE_LOCAL 0x2
#define ITEM_TYPE_LONG 0x3
#define ITEM_TAG_MAIN_INPUT 0x8
#define ITEM_TAG_MAIN_OUTPUT 0x9
#define ITEM_TAG_MAIN_FEATURE 0xb
#define ITEM_TAG_MAIN_COLLECTION 0xa
#define ITEM_TAG_MAIN_END_COLLECTION 0xc
#define ITEM_TAG_GLOBAL_USAGE_PAGE 0x0
#define ITEM_TAG_GLOBAL_LOGICAL_MINIMUM 0x1
#define ITEM_TAG_GLOBAL_LOGICAL_MAXIMUM 0x2
#define ITEM_TAG_GLOBAL_PHYSICAL_MINIMUM 0x3
#define ITEM_TAG_GLOBAL_PHYSICAL_MAXIMUM 0x4
#define ITEM_TAG_GLOBAL_UNIT_EXPONENT 0x5
#define ITEM_TAG_GLOBAL_UNIT 0x6
#define ITEM_TAG_GLOBAL_REPORT_SIZE 0x7
#define ITEM_TAG_GLOBAL_REPORT_ID 0x8
#define ITEM_TAG_GLOBAL_REPORT_COUNT 0x9
#define ITEM_TAG_GLOBAL_PUSH 0xa
#define ITEM_TAG_GLOBAL_POP 0xb
#define ITEM_TAG_LOCAL_USAGE 0x0
#define ITEM_TAG_LOCAL_USAGE_MINIMUM 0x1
#define ITEM_TAG_LOCAL_USAGE_MAXIMUM 0x2
#define ITEM_TAG_LOCAL_DESIGNATOR_INDEX 0x3
#define ITEM_TAG_LOCAL_DESIGNATOR_MINIMUM 0x4
#define ITEM_TAG_LOCAL_DESIGNATOR_MAXIMUM 0x5
#define ITEM_TAG_LOCAL_STRING_INDEX 0x7
#define ITEM_TAG_LOCAL_STRING_MINIMUM 0x8
#define ITEM_TAG_LOCAL_STRING_MAXIMUM 0x9
#define ITEM_TAG_LOCAL_DELIMITER 0xa
#define ITEM_TAG_LONG 0xf
#define COLLECTION_PHYSICAL 0x00
#define COLLECTION_APPLICATION 0x01
#define COLLECTION_LOGICAL 0x02
#define COLLECTION_REPORT 0x03
#define COLLECTION_NAMED_ARRAY 0x04
#define COLLECTION_USAGE_SWITCH 0x05
#define COLLECTION_USAGE_MODIFIER 0x06
#define COLLECTION_ALL 0xff
#define UNIT_SYSTEM 0x0
#define UNIT_LENGTH 0x1
#define UNIT_MASS 0x2
#define UNIT_TIME 0x3
#define UNIT_TEMPERATURE 0x4
#define UNIT_CURRENT 0x5
#define UNIT_LUMINOUS_INTENSITY 0x6
#define USAGE_PAGE_SHIFT 16
#define USAGE_PAGE_MASK 0xffff
#define USAGE_ID_SHIFT 0
#define USAGE_ID_MASK 0xffff
typedef struct
{
UCHAR Size:2;
UCHAR Type:2;
UCHAR Tag:4;
}ITEM_PREFIX, *PITEM_PREFIX;
typedef struct
{
ITEM_PREFIX Prefix;
union
{
UCHAR UData8[4];
CHAR SData8[4];
USHORT UData16[2];
SHORT SData16[2];
ULONG UData32;
LONG SData32;
}Data;
}SHORT_ITEM, *PSHORT_ITEM;
typedef struct
{
ITEM_PREFIX Prefix;
UCHAR DataSize;
UCHAR LongItemTag;
UCHAR Data[0];
}LONG_ITEM,*PLONG_ITEM;
#define LBITFIELD9(b1,b2,b3,b4,b5,b6,b7,b8,b9) USHORT b9,b8,b7,b6,b5,b4,b3,b2,b1
typedef struct
{
USHORT DataConstant:1;
USHORT ArrayVariable:1;
USHORT Relative:1;
USHORT Wrap:1;
USHORT NonLinear:1;
USHORT NoPreferred:1;
USHORT NullState:1;
USHORT IsVolatile:1;
USHORT BitsBytes:1;
UCHAR reserved[2];
}MAIN_ITEM_DATA, *PMAIN_ITEM_DATA;
typedef struct __GLOBAL_ITEM_STATE_
{
USHORT UsagePage;
ULONG LogicalMinimum;
ULONG LogicialMaximum;
ULONG PhysicalMinimum;
ULONG PhysicalMaximum;
UCHAR UnitExponent;
UCHAR Unit;
ULONG ReportSize;
ULONG ReportCount;
UCHAR ReportId;
struct __GLOBAL_ITEM_STATE__ * Next;
}GLOBAL_ITEM_STATE, *PGLOBAL_ITEM_STATE;
typedef struct usage_value
{
union
{
struct {
USHORT UsageId;
USHORT UsagePage;
}s;
ULONG Extended;
}u;
UCHAR IsExtended;
}USAGE_VALUE, *PUSAGE_VALUE;
typedef struct
{
PUSAGE_VALUE UsageStack;
ULONG UsageStackUsed;
ULONG UsageStackAllocated;
USAGE_VALUE UsageMinimum;
USAGE_VALUE UsageMaximum;
UCHAR UsageMinimumSet;
UCHAR UsageMaximumSet;
ULONG DesignatorIndex;
UCHAR DesignatorIndexSet;
ULONG DesignatorMinimum;
ULONG DesignatorMaximum;
UCHAR StringIndex;
UCHAR StringIndexSet;
UCHAR StringMinimum;
UCHAR StringMaximum;
}LOCAL_ITEM_STATE, *PLOCAL_ITEM_STATE;
typedef struct
{
ULONG ByteOffset;
UCHAR Shift;
ULONG Mask;
UCHAR BitCount;
UCHAR HasData;
UCHAR Array;
UCHAR Relative;
ULONG Minimum;
ULONG Maximum;
ULONG UsageMinimum;
ULONG UsageMaximum;
ULONG Data;
UCHAR Valid;
}HID_REPORT_ITEM, *PHID_REPORT_ITEM;
struct HID_REPORT;
typedef struct __HID_COLLECTION__
{
struct __HID_COLLECTION__ * Root;
UCHAR Type;
ULONG Usage;
UCHAR StringID;
UCHAR PhysicalID;
ULONG NodeCount;
struct __HID_COLLECTION__ ** Nodes;
ULONG ItemCount;
ULONG ItemCountAllocated;
PHID_REPORT_ITEM * Items;
//ULONG ReportCount;
//struct HID_REPORT ** Reports;
}HID_COLLECTION, *PHID_COLLECTION;
typedef struct
{
UCHAR Type;
UCHAR ReportID;
ULONG ReportSize;
ULONG ItemCount;
ULONG ItemAllocated;
PHID_REPORT_ITEM *Items;
ULONG ReportStatus;
UCHAR * CurrentReport;
ULONG BusyCount;
}HID_REPORT, *PHID_REPORT;
typedef struct
{
//
// global item state
//
GLOBAL_ITEM_STATE GlobalItemState;
//
// local item state
//
LOCAL_ITEM_STATE LocalItemState;
//
// root collection
//
PHID_COLLECTION RootCollection;
//
// report count
//
ULONG ReportCount;
//
// reports
//
PHID_REPORT * Reports;
//
// uses report ids
//
UCHAR UseReportIDs;
}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
ULONG
HidParser_NumberOfReports(
IN PHID_PARSER Parser,
IN ULONG ReportType);
HIDPARSER_STATUS
HidParser_GetCollectionUsagePage(
IN PHID_PARSER Parser,
IN ULONG CollectionNumber,
OUT PUSHORT Usage,
OUT PUSHORT UsagePage);
ULONG
HidParser_GetReportLength(
IN PHID_PARSER Parser,
IN ULONG ReportType);
UCHAR
HidParser_IsReportIDUsed(
IN PHID_PARSER Parser);
ULONG
HidParser_GetReportItemCountFromReportType(
IN PHID_PARSER Parser,
IN ULONG ReportType);
ULONG
HidParser_GetReportItemTypeCountFromReportType(
IN PHID_PARSER Parser,
IN ULONG ReportType,
IN ULONG bData);
ULONG
HidParser_GetContextSize(
IN PHID_PARSER Parser);
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 ReportType,
IN USAGE UsagePage OPTIONAL);
HIDPARSER_STATUS
HidParser_GetSpecificValueCapsWithReport(
IN PHID_PARSER Parser,
IN ULONG ReportType,
IN USHORT UsagePage,
IN USHORT Usage,
OUT PHIDP_VALUE_CAPS ValueCaps,
IN OUT PULONG ValueCapsLength);
HIDPARSER_STATUS
HidParser_GetUsagesWithReport(
IN PHID_PARSER Parser,
IN HIDP_REPORT_TYPE ReportType,
IN USAGE UsagePage,
OUT USAGE *UsageList,
IN OUT PULONG UsageLength,
IN PCHAR ReportDescriptor,
IN ULONG ReportDescriptorLength);
HIDPARSER_STATUS
HidParser_GetScaledUsageValueWithReport(
IN PHID_PARSER Parser,
IN HIDP_REPORT_TYPE ReportType,
IN USAGE UsagePage,
IN USAGE Usage,
OUT PLONG UsageValue,
IN PCHAR ReportDescriptor,
IN ULONG ReportDescriptorLength);