mirror of
https://github.com/reactos/reactos.git
synced 2024-11-20 06:15:26 +00:00
[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:
parent
07ae01f96c
commit
d1e00dac5c
10 changed files with 4490 additions and 376 deletions
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -5,4 +5,6 @@
|
|||
#include <ntddk.h>
|
||||
#include <hidpddi.h>
|
||||
#include <hidpi.h>
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
#include "hidparser.h"
|
|
@ -1,6 +1,7 @@
|
|||
|
||||
add_subdirectory(chew)
|
||||
add_subdirectory(csq)
|
||||
add_subdirectory(hidparser)
|
||||
add_subdirectory(ip)
|
||||
add_subdirectory(oskittcp)
|
||||
add_subdirectory(sound)
|
||||
|
|
13
lib/drivers/hidparser/CMakeLists.txt
Normal file
13
lib/drivers/hidparser/CMakeLists.txt
Normal 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
953
lib/drivers/hidparser/api.c
Normal 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;
|
||||
}
|
1083
lib/drivers/hidparser/hidparser.c
Normal file
1083
lib/drivers/hidparser/hidparser.c
Normal file
File diff suppressed because it is too large
Load diff
427
lib/drivers/hidparser/hidparser.h
Normal file
427
lib/drivers/hidparser/hidparser.h
Normal 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);
|
1347
lib/drivers/hidparser/parser.c
Normal file
1347
lib/drivers/hidparser/parser.c
Normal file
File diff suppressed because it is too large
Load diff
362
lib/drivers/hidparser/parser.h
Normal file
362
lib/drivers/hidparser/parser.h
Normal 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);
|
Loading…
Reference in a new issue