Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140/* * PROJECT: ReactOS HID Parser Library * 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) */
#include "parser.h"
#define NDEBUG#include <debug.h>
NTSTATUSNTAPIHidParser_GetCollectionDescription( IN PHIDP_REPORT_DESCRIPTOR ReportDesc, IN ULONG DescLength, IN POOL_TYPE PoolType, OUT PHIDP_DEVICE_DESC DeviceDescription){ NTSTATUS ParserStatus; ULONG CollectionCount; ULONG Index; PVOID ParserContext;
// // first parse the report descriptor // ParserStatus = HidParser_ParseReportDescriptor(ReportDesc, DescLength, &ParserContext); if (ParserStatus != HIDP_STATUS_SUCCESS) { // // failed to parse report descriptor // DebugFunction("[HIDPARSER] Failed to parse report descriptor with %x\n", ParserStatus); return ParserStatus; }
// // get collection count // CollectionCount = HidParser_NumberOfTopCollections(ParserContext); if (CollectionCount == 0) { // // no top level collections found // ASSERT(FALSE); return STATUS_NO_DATA_DETECTED; }
// // zero description // ZeroFunction(DeviceDescription, sizeof(HIDP_DEVICE_DESC));
// // allocate collection // DeviceDescription->CollectionDesc = (PHIDP_COLLECTION_DESC)AllocFunction(sizeof(HIDP_COLLECTION_DESC) * CollectionCount); if (!DeviceDescription->CollectionDesc) { // // no memory // return STATUS_INSUFFICIENT_RESOURCES; }
// // allocate report description // DeviceDescription->ReportIDs = (PHIDP_REPORT_IDS)AllocFunction(sizeof(HIDP_REPORT_IDS) * CollectionCount); if (!DeviceDescription->ReportIDs) { // // no memory // FreeFunction(DeviceDescription->CollectionDesc); return STATUS_INSUFFICIENT_RESOURCES; }
for(Index = 0; Index < CollectionCount; Index++) { // // set preparsed data length // DeviceDescription->CollectionDesc[Index].PreparsedDataLength = HidParser_GetContextSize(ParserContext, Index); ParserStatus = HidParser_BuildContext(ParserContext, Index, DeviceDescription->CollectionDesc[Index].PreparsedDataLength, (PVOID*)&DeviceDescription->CollectionDesc[Index].PreparsedData); if (ParserStatus != HIDP_STATUS_SUCCESS) { // // no memory // FreeFunction(DeviceDescription->CollectionDesc); FreeFunction(DeviceDescription->ReportIDs); return ParserStatus; }
// // init report description // DeviceDescription->ReportIDs[Index].CollectionNumber = Index + 1; DeviceDescription->ReportIDs[Index].ReportID = Index; //FIXME DeviceDescription->ReportIDs[Index].InputLength = HidParser_GetReportLength((PVOID)DeviceDescription->CollectionDesc[Index].PreparsedData, HID_REPORT_TYPE_INPUT); DeviceDescription->ReportIDs[Index].OutputLength = HidParser_GetReportLength((PVOID)DeviceDescription->CollectionDesc[Index].PreparsedData, HID_REPORT_TYPE_OUTPUT); DeviceDescription->ReportIDs[Index].FeatureLength = HidParser_GetReportLength((PVOID)DeviceDescription->CollectionDesc[Index].PreparsedData, HID_REPORT_TYPE_FEATURE);
DeviceDescription->ReportIDs[Index].InputLength += (HidParser_UsesReportId((PVOID)DeviceDescription->CollectionDesc[Index].PreparsedData, HID_REPORT_TYPE_INPUT) ? 1 : 0); DeviceDescription->ReportIDs[Index].OutputLength += (HidParser_UsesReportId((PVOID)DeviceDescription->CollectionDesc[Index].PreparsedData, HID_REPORT_TYPE_OUTPUT) ? 1 : 0); DeviceDescription->ReportIDs[Index].FeatureLength += (HidParser_UsesReportId((PVOID)DeviceDescription->CollectionDesc[Index].PreparsedData, HID_REPORT_TYPE_FEATURE) ? 1 : 0);
// // init collection description // DeviceDescription->CollectionDesc[Index].CollectionNumber = Index + 1;
// // get collection usage page // ParserStatus = HidParser_GetCollectionUsagePage((PVOID)DeviceDescription->CollectionDesc[Index].PreparsedData, &DeviceDescription->CollectionDesc[Index].Usage, &DeviceDescription->CollectionDesc[Index].UsagePage); if (ParserStatus != HIDP_STATUS_SUCCESS) { // collection not found FreeFunction(DeviceDescription->CollectionDesc); FreeFunction(DeviceDescription->ReportIDs); return ParserStatus; }
// // windows seems to prepend the report id, regardless if it is required // DeviceDescription->CollectionDesc[Index].CollectionNumber = Index + 1; DeviceDescription->CollectionDesc[Index].InputLength = DeviceDescription->ReportIDs[Index].InputLength; DeviceDescription->CollectionDesc[Index].OutputLength = DeviceDescription->ReportIDs[Index].OutputLength; DeviceDescription->CollectionDesc[Index].FeatureLength = DeviceDescription->ReportIDs[Index].FeatureLength;
DeviceDescription->CollectionDesc[Index].InputLength += (HidParser_UsesReportId((PVOID)DeviceDescription->CollectionDesc[Index].PreparsedData, HID_REPORT_TYPE_INPUT) == FALSE ? 1 : 0); DeviceDescription->CollectionDesc[Index].OutputLength += (HidParser_UsesReportId((PVOID)DeviceDescription->CollectionDesc[Index].PreparsedData, HID_REPORT_TYPE_OUTPUT) == FALSE ? 1 : 0); DeviceDescription->CollectionDesc[Index].FeatureLength += (HidParser_UsesReportId((PVOID)DeviceDescription->CollectionDesc[Index].PreparsedData, HID_REPORT_TYPE_FEATURE) == FALSE ? 1 : 0);
}
// // store collection & report count // DeviceDescription->CollectionDescLength = CollectionCount; DeviceDescription->ReportIDsLength = CollectionCount;
// // done // return STATUS_SUCCESS;}
VOIDNTAPIHidParser_FreeCollectionDescription( IN PHIDP_DEVICE_DESC DeviceDescription){ ULONG Index;
// // first free all context // for(Index = 0; Index < DeviceDescription->CollectionDescLength; Index++) { // // free collection context // FreeFunction(DeviceDescription->CollectionDesc[Index].PreparsedData); }
// // now free collection description // FreeFunction(DeviceDescription->CollectionDesc);
// // free report description // FreeFunction(DeviceDescription->ReportIDs);}
HIDAPINTSTATUSNTAPIHidParser_GetCaps( IN PVOID CollectionContext, OUT PHIDP_CAPS Capabilities){ // // zero capabilities // ZeroFunction(Capabilities, sizeof(HIDP_CAPS));
// // init capabilities // HidParser_GetCollectionUsagePage(CollectionContext, &Capabilities->Usage, &Capabilities->UsagePage); Capabilities->InputReportByteLength = HidParser_GetReportLength(CollectionContext, HID_REPORT_TYPE_INPUT); Capabilities->OutputReportByteLength = HidParser_GetReportLength(CollectionContext, HID_REPORT_TYPE_OUTPUT); Capabilities->FeatureReportByteLength = HidParser_GetReportLength(CollectionContext, HID_REPORT_TYPE_FEATURE);
// // always pre-prend report id // Capabilities->InputReportByteLength = (Capabilities->InputReportByteLength > 0 ? Capabilities->InputReportByteLength + 1 : 0); Capabilities->OutputReportByteLength = (Capabilities->OutputReportByteLength > 0 ? Capabilities->OutputReportByteLength + 1 : 0); Capabilities->FeatureReportByteLength = (Capabilities->FeatureReportByteLength > 0 ? Capabilities->FeatureReportByteLength + 1 : 0);
// // get number of link collection nodes // Capabilities->NumberLinkCollectionNodes = HidParser_GetTotalCollectionCount(CollectionContext);
// // get data indices // Capabilities->NumberInputDataIndices = HidParser_GetReportItemTypeCountFromReportType(CollectionContext, HID_REPORT_TYPE_INPUT, TRUE); Capabilities->NumberOutputDataIndices = HidParser_GetReportItemTypeCountFromReportType(CollectionContext, HID_REPORT_TYPE_OUTPUT, TRUE); Capabilities->NumberFeatureDataIndices = HidParser_GetReportItemTypeCountFromReportType(CollectionContext, HID_REPORT_TYPE_FEATURE, TRUE);
// // get value caps // Capabilities->NumberInputValueCaps = HidParser_GetReportItemTypeCountFromReportType(CollectionContext, HID_REPORT_TYPE_INPUT, FALSE); Capabilities->NumberOutputValueCaps = HidParser_GetReportItemTypeCountFromReportType(CollectionContext, HID_REPORT_TYPE_OUTPUT, FALSE); Capabilities->NumberFeatureValueCaps = HidParser_GetReportItemTypeCountFromReportType(CollectionContext, HID_REPORT_TYPE_FEATURE, FALSE);
// // get button caps // Capabilities->NumberInputButtonCaps = HidParser_GetReportItemCountFromReportType(CollectionContext, HID_REPORT_TYPE_INPUT); Capabilities->NumberOutputButtonCaps = HidParser_GetReportItemCountFromReportType(CollectionContext, HID_REPORT_TYPE_OUTPUT); Capabilities->NumberFeatureButtonCaps = HidParser_GetReportItemCountFromReportType(CollectionContext, HID_REPORT_TYPE_FEATURE);
// // done // return HIDP_STATUS_SUCCESS;}
HIDAPIULONGNTAPIHidParser_MaxUsageListLength( IN PVOID CollectionContext, IN HIDP_REPORT_TYPE ReportType, IN USAGE UsagePage OPTIONAL){ // // FIXME test what should be returned when usage page is not defined // if (UsagePage == HID_USAGE_PAGE_UNDEFINED) { // // implement me // UNIMPLEMENTED;
// // invalid report // return 0; }
if (ReportType == HidP_Input) { // // input report // return HidParser_GetMaxUsageListLengthWithReportAndPage(CollectionContext, HID_REPORT_TYPE_INPUT, UsagePage); } else if (ReportType == HidP_Output) { // // input report // return HidParser_GetMaxUsageListLengthWithReportAndPage(CollectionContext, HID_REPORT_TYPE_OUTPUT, UsagePage); } else if (ReportType == HidP_Feature) { // // input report // return HidParser_GetMaxUsageListLengthWithReportAndPage(CollectionContext, HID_REPORT_TYPE_FEATURE, UsagePage); } else { // // invalid report type // return 0; }}
#undef HidParser_GetButtonCaps
HIDAPINTSTATUSNTAPIHidParser_GetButtonCaps( IN PVOID CollectionContext, IN HIDP_REPORT_TYPE ReportType, IN PHIDP_BUTTON_CAPS ButtonCaps, IN PUSHORT ButtonCapsLength){ return HidParser_GetSpecificButtonCaps(CollectionContext, ReportType, HID_USAGE_PAGE_UNDEFINED, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_PAGE_UNDEFINED, ButtonCaps, (PULONG)ButtonCapsLength);}
HIDAPINTSTATUSNTAPIHidParser_GetSpecificValueCaps( IN PVOID CollectionContext, IN HIDP_REPORT_TYPE ReportType, IN USAGE UsagePage, IN USHORT LinkCollection, IN USAGE Usage, OUT PHIDP_VALUE_CAPS ValueCaps, IN OUT PUSHORT ValueCapsLength){ NTSTATUS ParserStatus;
// // FIXME: implement searching in specific collection // ASSERT(LinkCollection == HIDP_LINK_COLLECTION_UNSPECIFIED);
if (ReportType == HidP_Input) { // // input report // ParserStatus = HidParser_GetSpecificValueCapsWithReport(CollectionContext, HID_REPORT_TYPE_INPUT, UsagePage, Usage, ValueCaps, ValueCapsLength); } else if (ReportType == HidP_Output) { // // input report // ParserStatus = HidParser_GetSpecificValueCapsWithReport(CollectionContext, HID_REPORT_TYPE_OUTPUT, UsagePage, Usage, ValueCaps, ValueCapsLength); } else if (ReportType == HidP_Feature) { // // input report // ParserStatus = HidParser_GetSpecificValueCapsWithReport(CollectionContext, HID_REPORT_TYPE_FEATURE, UsagePage, Usage, ValueCaps, ValueCapsLength); } else { // // invalid report type // return HIDP_STATUS_INVALID_REPORT_TYPE; }
// // return status // return ParserStatus;}
HIDAPINTSTATUSNTAPIHidParser_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;}
HIDAPINTSTATUSNTAPIHidParser_GetUsages( IN PVOID CollectionContext, IN HIDP_REPORT_TYPE ReportType, IN USAGE UsagePage, IN USHORT LinkCollection OPTIONAL, OUT USAGE *UsageList, IN OUT PULONG UsageLength, IN PCHAR Report, IN ULONG ReportLength){ NTSTATUS ParserStatus;
// // FIXME: implement searching in specific collection // ASSERT(LinkCollection == HIDP_LINK_COLLECTION_UNSPECIFIED);
if (ReportType == HidP_Input) { // // input report // ParserStatus = HidParser_GetUsagesWithReport(CollectionContext, HID_REPORT_TYPE_INPUT, UsagePage, UsageList, UsageLength, Report, ReportLength); } else if (ReportType == HidP_Output) { // // input report // ParserStatus = HidParser_GetUsagesWithReport(CollectionContext, HID_REPORT_TYPE_OUTPUT, UsagePage, UsageList, UsageLength, Report, ReportLength); } else if (ReportType == HidP_Feature) { // // input report // ParserStatus = HidParser_GetUsagesWithReport(CollectionContext, HID_REPORT_TYPE_FEATURE, UsagePage, UsageList, UsageLength, Report, ReportLength); } else { // // invalid report type // return HIDP_STATUS_INVALID_REPORT_TYPE; }
// // return status // return ParserStatus;}
HIDAPINTSTATUSNTAPIHidParser_GetScaledUsageValue( IN PVOID CollectionContext, IN HIDP_REPORT_TYPE ReportType, IN USAGE UsagePage, IN USHORT LinkCollection OPTIONAL, IN USAGE Usage, OUT PLONG UsageValue, IN PCHAR Report, IN ULONG ReportLength){ NTSTATUS ParserStatus;
// // FIXME: implement searching in specific collection // ASSERT(LinkCollection == HIDP_LINK_COLLECTION_UNSPECIFIED);
if (ReportType == HidP_Input) { // // input report // ParserStatus = HidParser_GetScaledUsageValueWithReport(CollectionContext, HID_REPORT_TYPE_INPUT, UsagePage, Usage, UsageValue, Report, ReportLength); } else if (ReportType == HidP_Output) { // // input report // ParserStatus = HidParser_GetScaledUsageValueWithReport(CollectionContext, HID_REPORT_TYPE_OUTPUT, UsagePage, Usage, UsageValue, Report, ReportLength); } else if (ReportType == HidP_Feature) { // // input report // ParserStatus = HidParser_GetScaledUsageValueWithReport(CollectionContext, HID_REPORT_TYPE_FEATURE, UsagePage, Usage, UsageValue, Report, ReportLength); } else { // // invalid report type // return HIDP_STATUS_INVALID_REPORT_TYPE; }
// // return status // return ParserStatus;}
HIDAPINTSTATUSNTAPIHidParser_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){ ULONG Index; NTSTATUS Status = HIDP_STATUS_SUCCESS;
for(Index = 0; Index < UsageListLength; Index++) { // // check current usage // if (ChangedUsageList[Index].UsagePage == HID_USAGE_PAGE_KEYBOARD) { // // process keyboard usage // Status = HidParser_TranslateKbdUsage(ChangedUsageList[Index].Usage, KeyAction, ModifierState, InsertCodesProcedure, InsertCodesContext); } else if (ChangedUsageList[Index].UsagePage == HID_USAGE_PAGE_CONSUMER) { // // process consumer usage // Status = HidParser_TranslateCustUsage(ChangedUsageList[Index].Usage, KeyAction, ModifierState, InsertCodesProcedure, InsertCodesContext); } else { // // invalid page / end of usage list page // return HIDP_STATUS_I8042_TRANS_UNKNOWN; }
// // check status // if (Status != HIDP_STATUS_SUCCESS) { // // failed // return Status; } }
// // return status // return Status;}
HIDAPINTSTATUSNTAPIHidParser_GetUsagesEx( IN PVOID CollectionContext, IN HIDP_REPORT_TYPE ReportType, IN USHORT LinkCollection, OUT PUSAGE_AND_PAGE ButtonList, IN OUT ULONG *UsageLength, IN PCHAR Report, IN ULONG ReportLength){ return HidParser_GetUsages(CollectionContext, ReportType, HID_USAGE_PAGE_UNDEFINED, LinkCollection, (PUSAGE)ButtonList, UsageLength, Report, ReportLength);}
HIDAPINTSTATUSNTAPIHidParser_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;}
HIDAPINTSTATUSNTAPIHidParser_GetSpecificButtonCaps( IN PVOID CollectionContext, IN HIDP_REPORT_TYPE ReportType, IN USAGE UsagePage, IN USHORT LinkCollection, IN USAGE Usage, OUT PHIDP_BUTTON_CAPS ButtonCaps, IN OUT PULONG ButtonCapsLength){ UNIMPLEMENTED; ASSERT(FALSE); return STATUS_NOT_IMPLEMENTED;}
HIDAPINTSTATUSNTAPIHidParser_GetData( IN PVOID CollectionContext, IN HIDP_REPORT_TYPE ReportType, OUT PHIDP_DATA DataList, IN OUT PULONG DataLength, IN PCHAR Report, IN ULONG ReportLength){ UNIMPLEMENTED; ASSERT(FALSE); return STATUS_NOT_IMPLEMENTED;}
HIDAPINTSTATUSNTAPIHidParser_GetExtendedAttributes( IN PVOID CollectionContext, IN HIDP_REPORT_TYPE ReportType, IN USHORT DataIndex, OUT PHIDP_EXTENDED_ATTRIBUTES Attributes, IN OUT PULONG LengthAttributes){ UNIMPLEMENTED; ASSERT(FALSE); return STATUS_NOT_IMPLEMENTED;}
HIDAPINTSTATUSNTAPIHidParser_GetLinkCollectionNodes( IN PVOID CollectionContext, OUT PHIDP_LINK_COLLECTION_NODE LinkCollectionNodes, IN OUT PULONG LinkCollectionNodesLength){ UNIMPLEMENTED; ASSERT(FALSE); return STATUS_NOT_IMPLEMENTED;}
HIDAPINTSTATUSNTAPIHidParser_GetUsageValue( IN PVOID CollectionContext, IN HIDP_REPORT_TYPE ReportType, IN USAGE UsagePage, IN USHORT LinkCollection, IN USAGE Usage, OUT PULONG UsageValue, IN PCHAR Report, IN ULONG ReportLength){ NTSTATUS ParserStatus;
// // FIXME: implement searching in specific collection // ASSERT(LinkCollection == HIDP_LINK_COLLECTION_UNSPECIFIED);
if (ReportType == HidP_Input) { // // input report // ParserStatus = HidParser_GetUsageValueWithReport(CollectionContext, HID_REPORT_TYPE_INPUT, UsagePage, Usage, UsageValue, Report, ReportLength); } else if (ReportType == HidP_Output) { // // input report // ParserStatus = HidParser_GetUsageValueWithReport(CollectionContext, HID_REPORT_TYPE_OUTPUT, UsagePage, Usage, UsageValue, Report, ReportLength); } else if (ReportType == HidP_Feature) { // // input report // ParserStatus = HidParser_GetUsageValueWithReport(CollectionContext, HID_REPORT_TYPE_FEATURE, UsagePage, Usage, UsageValue, Report, ReportLength); } else { // // invalid report type // return HIDP_STATUS_INVALID_REPORT_TYPE; }
// // return status // return ParserStatus;}
NTSTATUSNTAPIHidParser_SysPowerEvent( IN PVOID CollectionContext, IN PCHAR HidPacket, IN USHORT HidPacketLength, OUT PULONG OutputBuffer){ UNIMPLEMENTED; ASSERT(FALSE); return STATUS_NOT_IMPLEMENTED;}
NTSTATUSNTAPIHidParser_SysPowerCaps ( IN PVOID CollectionContext, OUT PULONG OutputBuffer){ UNIMPLEMENTED; ASSERT(FALSE); return STATUS_NOT_IMPLEMENTED;}
HIDAPINTSTATUSNTAPIHidParser_GetUsageValueArray( IN PVOID CollectionContext, IN HIDP_REPORT_TYPE ReportType, IN USAGE UsagePage, IN USHORT LinkCollection OPTIONAL, IN USAGE Usage, OUT PCHAR UsageValue, IN USHORT UsageValueByteLength, IN PCHAR Report, IN ULONG ReportLength){ UNIMPLEMENTED; ASSERT(FALSE); return STATUS_NOT_IMPLEMENTED;}
HIDAPINTSTATUSNTAPIHidParser_UnsetUsages( IN PVOID CollectionContext, IN HIDP_REPORT_TYPE ReportType, IN USAGE UsagePage, IN USHORT LinkCollection, IN PUSAGE UsageList, IN OUT PULONG UsageLength, IN OUT PCHAR Report, IN ULONG ReportLength){ UNIMPLEMENTED; ASSERT(FALSE); return STATUS_NOT_IMPLEMENTED;}
HIDAPINTSTATUSNTAPIHidParser_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){ UNIMPLEMENTED; ASSERT(FALSE); return STATUS_NOT_IMPLEMENTED;}
HIDAPINTSTATUSNTAPIHidParser_SetUsages( IN PVOID CollectionContext, IN HIDP_REPORT_TYPE ReportType, IN USAGE UsagePage, IN USHORT LinkCollection, IN PUSAGE UsageList, IN OUT PULONG UsageLength, IN OUT PCHAR Report, IN ULONG ReportLength){ UNIMPLEMENTED; ASSERT(FALSE); return STATUS_NOT_IMPLEMENTED;}
HIDAPINTSTATUSNTAPIHidParser_SetUsageValueArray( IN PVOID CollectionContext, IN HIDP_REPORT_TYPE ReportType, IN USAGE UsagePage, IN USHORT LinkCollection OPTIONAL, IN USAGE Usage, IN PCHAR UsageValue, IN USHORT UsageValueByteLength, OUT PCHAR Report, IN ULONG ReportLength){ UNIMPLEMENTED; ASSERT(FALSE); return STATUS_NOT_IMPLEMENTED;}
HIDAPINTSTATUSNTAPIHidParser_SetUsageValue( IN PVOID CollectionContext, IN HIDP_REPORT_TYPE ReportType, IN USAGE UsagePage, IN USHORT LinkCollection, IN USAGE Usage, IN ULONG UsageValue, IN OUT PCHAR Report, IN ULONG ReportLength){ UNIMPLEMENTED; ASSERT(FALSE); return STATUS_NOT_IMPLEMENTED;}
HIDAPINTSTATUSNTAPIHidParser_SetScaledUsageValue( IN PVOID CollectionContext, IN HIDP_REPORT_TYPE ReportType, IN USAGE UsagePage, IN USHORT LinkCollection OPTIONAL, IN USAGE Usage, IN LONG UsageValue, IN OUT PCHAR Report, IN ULONG ReportLength){ UNIMPLEMENTED; ASSERT(FALSE); return STATUS_NOT_IMPLEMENTED;}
HIDAPINTSTATUSNTAPIHidParser_SetData( IN PVOID CollectionContext, IN HIDP_REPORT_TYPE ReportType, IN PHIDP_DATA DataList, IN OUT PULONG DataLength, IN OUT PCHAR Report, IN ULONG ReportLength){ UNIMPLEMENTED; ASSERT(FALSE); return STATUS_NOT_IMPLEMENTED;}
HIDAPIULONGNTAPIHidParser_MaxDataListLength( IN PVOID CollectionContext, IN HIDP_REPORT_TYPE ReportType){ UNIMPLEMENTED; ASSERT(FALSE); return 0;}
HIDAPINTSTATUSNTAPIHidParser_InitializeReportForID( IN PVOID CollectionContext, IN HIDP_REPORT_TYPE ReportType, IN UCHAR ReportID, IN OUT PCHAR Report, IN ULONG ReportLength){ UNIMPLEMENTED; ASSERT(FALSE); return STATUS_NOT_IMPLEMENTED;}
#undef HidParser_GetValueCaps
HIDAPINTSTATUSNTAPIHidParser_GetValueCaps( IN PVOID CollectionContext, HIDP_REPORT_TYPE ReportType, PHIDP_VALUE_CAPS ValueCaps, PULONG ValueCapsLength){ UNIMPLEMENTED; ASSERT(FALSE); return STATUS_NOT_IMPLEMENTED;}