Something went wrong. Try again.
Reactos
Something went wrong. Try again.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370/* * PROJECT: ReactOS HID Parser Library * LICENSE: GPL - See COPYING in the top level directory * FILE: lib/drivers/hidparser/parser.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>
static UCHAR ItemSize[4] = { 0, 1, 2, 4 };
VOIDHidParser_DeleteReport( IN PHID_REPORT Report){ // // not implemented //}
VOIDHidParser_FreeCollection( IN PHID_COLLECTION Collection){ // // not implemented //}
NTSTATUSHidParser_AllocateCollection( IN PHID_COLLECTION ParentCollection, IN UCHAR Type, IN PLOCAL_ITEM_STATE LocalItemState, OUT PHID_COLLECTION * OutCollection){ PHID_COLLECTION Collection; USAGE_VALUE UsageValue;
// // first allocate the collection // Collection = (PHID_COLLECTION)AllocFunction(sizeof(HID_COLLECTION)); if (!Collection) { // // no memory // return HIDP_STATUS_INTERNAL_ERROR; }
// // init collection // Collection->Root = ParentCollection; Collection->Type = Type; Collection->StringID = LocalItemState->StringIndex; Collection->PhysicalID = LocalItemState->DesignatorIndex;
// // set Usage // ASSERT(LocalItemState); ASSERT(LocalItemState->UsageStack);
if (LocalItemState->UsageStackUsed > 0) { // // usage value from first local stack item // UsageValue.u.Extended = LocalItemState->UsageStack[0].u.Extended; } else if (LocalItemState->UsageMinimumSet) { // // use value from minimum // UsageValue.u.Extended = LocalItemState->UsageMinimum.u.Extended; } else if (LocalItemState->UsageMaximumSet) { // // use value from maximum // UsageValue.u.Extended = LocalItemState->UsageMaximum.u.Extended; } else if (Type == COLLECTION_LOGICAL) { // // root collection // UsageValue.u.Extended = 0; } else { // // no usage set // DebugFunction("HIDPARSE] No usage set\n"); UsageValue.u.Extended = 0; }
// // store usage // Collection->Usage = UsageValue.u.Extended;
// // store result // *OutCollection = Collection;
// // done // return HIDP_STATUS_SUCCESS;}
NTSTATUSHidParser_AddCollection( IN PHID_COLLECTION CurrentCollection, IN PHID_COLLECTION NewCollection){ PHID_COLLECTION * NewAllocCollection; ULONG CollectionCount;
// // increment collection array // CollectionCount = CurrentCollection->NodeCount + 1;
// // allocate new collection // NewAllocCollection = (PHID_COLLECTION*)AllocFunction(sizeof(PHID_COLLECTION) * CollectionCount); if (!NewAllocCollection) { // // no memory // return HIDP_STATUS_INTERNAL_ERROR; }
if (CurrentCollection->NodeCount) { // // copy old array // CopyFunction(NewAllocCollection, CurrentCollection->Nodes, CurrentCollection->NodeCount * sizeof(PHID_COLLECTION));
// // delete old array // FreeFunction(CurrentCollection->Nodes); }
// // insert new item // NewAllocCollection[CurrentCollection->NodeCount] = (struct __HID_COLLECTION__*)NewCollection;
// // store new array // CurrentCollection->Nodes = NewAllocCollection; CurrentCollection->NodeCount++;
// // done // return HIDP_STATUS_SUCCESS;}
NTSTATUSHidParser_FindReportInCollection( IN PHID_COLLECTION Collection, IN UCHAR ReportType, IN UCHAR ReportID, OUT PHID_REPORT *OutReport){ ULONG Index; NTSTATUS Status;
// // search in local list // for(Index = 0; Index < Collection->ReportCount; Index++) { if (Collection->Reports[Index]->Type == ReportType && Collection->Reports[Index]->ReportID == ReportID) { // // found report // *OutReport = Collection->Reports[Index]; return HIDP_STATUS_SUCCESS; } }
// // search in sub collections // for(Index = 0; Index < Collection->NodeCount; Index++) { Status = HidParser_FindReportInCollection(Collection->Nodes[Index], ReportType, ReportID, OutReport); if (Status == HIDP_STATUS_SUCCESS) return Status; }
// // no such report found // *OutReport = NULL; return HIDP_STATUS_REPORT_DOES_NOT_EXIST;}
NTSTATUSHidParser_FindReport( IN PHID_PARSER_CONTEXT ParserContext, IN UCHAR ReportType, IN UCHAR ReportID, OUT PHID_REPORT *OutReport){ // // search in current top level collection // return HidParser_FindReportInCollection(ParserContext->RootCollection->Nodes[ParserContext->RootCollection->NodeCount-1], ReportType, ReportID, OutReport);}
NTSTATUSHidParser_AllocateReport( IN UCHAR ReportType, IN UCHAR ReportID, OUT PHID_REPORT *OutReport){ PHID_REPORT Report;
// // allocate report // Report = (PHID_REPORT)AllocFunction(sizeof(HID_REPORT)); if (!Report) { // // no memory // return HIDP_STATUS_INTERNAL_ERROR; }
// // init report // Report->ReportID = ReportID; Report->Type = ReportType;
// // done // *OutReport = Report; return HIDP_STATUS_SUCCESS;}
NTSTATUSHidParser_AddReportToCollection( IN PHID_PARSER_CONTEXT ParserContext, IN PHID_COLLECTION CurrentCollection, IN PHID_REPORT NewReport){ PHID_REPORT * NewReportArray;
// // allocate new report array // NewReportArray = (PHID_REPORT*)AllocFunction(sizeof(PHID_REPORT) * (CurrentCollection->ReportCount + 1)); if (!NewReportArray) { // // no memory // return HIDP_STATUS_INTERNAL_ERROR; }
if (CurrentCollection->ReportCount) { // // copy old array contents // CopyFunction(NewReportArray, CurrentCollection->Reports, sizeof(PHID_REPORT) * CurrentCollection->ReportCount);
// // free old array // FreeFunction(CurrentCollection->Reports); }
// // store result // NewReportArray[CurrentCollection->ReportCount] = NewReport; CurrentCollection->Reports = NewReportArray; CurrentCollection->ReportCount++;
// // completed successfully // return HIDP_STATUS_SUCCESS;}
NTSTATUSHidParser_GetReport( IN PHID_PARSER_CONTEXT ParserContext, IN PHID_COLLECTION Collection, IN UCHAR ReportType, IN UCHAR ReportID, IN UCHAR CreateIfNotExists, OUT PHID_REPORT *OutReport){ NTSTATUS Status;
// // try finding existing report // Status = HidParser_FindReport(ParserContext, ReportType, ReportID, OutReport); if (Status == HIDP_STATUS_SUCCESS || CreateIfNotExists == FALSE) { // // founed report // return Status; }
// // allocate new report // Status = HidParser_AllocateReport(ReportType, ReportID, OutReport); if (Status != HIDP_STATUS_SUCCESS) { // // failed to allocate report // return Status; }
// // add report // Status = HidParser_AddReportToCollection(ParserContext, Collection, *OutReport); if (Status != HIDP_STATUS_SUCCESS) { // // failed to allocate report // FreeFunction(*OutReport); }
// // done // return Status;}
NTSTATUSHidParser_ReserveReportItems( IN PHID_REPORT Report, IN ULONG ReportCount, OUT PHID_REPORT *OutReport){ PHID_REPORT NewReport; ULONG OldSize, Size;
if (Report->ItemCount + ReportCount <= Report->ItemAllocated) { // // space is already allocated // *OutReport = Report; return HIDP_STATUS_SUCCESS; }
// //calculate new size // OldSize = sizeof(HID_REPORT) + (Report->ItemCount) * sizeof(HID_REPORT_ITEM); Size = ReportCount * sizeof(HID_REPORT_ITEM);
// // allocate memory // NewReport = (PHID_REPORT)AllocFunction(Size + OldSize); if (!NewReport) { // // no memory // return HIDP_STATUS_INTERNAL_ERROR; }
// // copy old report // CopyFunction(NewReport, Report, OldSize);
// // increase array size // NewReport->ItemAllocated += ReportCount;
// // store result // *OutReport = NewReport;
// // completed sucessfully // return HIDP_STATUS_SUCCESS;}
VOIDHidParser_SignRange( IN ULONG Minimum, IN ULONG Maximum, OUT PULONG NewMinimum, OUT PULONG NewMaximum){ ULONG Mask = 0x80000000; ULONG Index;
for (Index = 0; Index < 4; Index++) { if (Minimum & Mask) { Minimum |= Mask; if (Maximum & Mask) Maximum |= Mask; return; }
Mask >>= 8; Mask |= 0xff000000; }
*NewMinimum = Minimum; *NewMaximum = Maximum;}
NTSTATUSHidParser_InitReportItem( IN PHID_REPORT Report, IN PHID_REPORT_ITEM ReportItem, IN PGLOBAL_ITEM_STATE GlobalItemState, IN PLOCAL_ITEM_STATE LocalItemState, IN PMAIN_ITEM_DATA ItemData, IN ULONG ReportItemIndex){ ULONG LogicalMinimum; ULONG LogicalMaximum; ULONG PhysicalMinimum; ULONG PhysicalMaximum; ULONG UsageMinimum; ULONG UsageMaximum; USAGE_VALUE UsageValue;
// // get logical bounds // LogicalMinimum = GlobalItemState->LogicalMinimum; LogicalMaximum = GlobalItemState->LogicialMaximum; if (LogicalMinimum > LogicalMaximum) { // // make them signed // HidParser_SignRange(LogicalMinimum, LogicalMaximum, &LogicalMinimum, &LogicalMaximum); } //ASSERT(LogicalMinimum <= LogicalMaximum);
// // get physical bounds // PhysicalMinimum = GlobalItemState->PhysicalMinimum; PhysicalMaximum = GlobalItemState->PhysicalMaximum; if (PhysicalMinimum > PhysicalMaximum) { // // make them signed // HidParser_SignRange(PhysicalMinimum, PhysicalMaximum, &PhysicalMinimum, &PhysicalMaximum); } //ASSERT(PhysicalMinimum <= PhysicalMaximum);
// // get usage bounds // UsageMinimum = 0; UsageMaximum = 0; if (ItemData->ArrayVariable == FALSE) { // // get usage bounds // UsageMinimum = LocalItemState->UsageMinimum.u.Extended; UsageMaximum = LocalItemState->UsageMaximum.u.Extended; } else { // // get usage value from stack // if (ReportItemIndex < LocalItemState->UsageStackUsed) { // // use stack item // UsageValue = LocalItemState->UsageStack[ReportItemIndex]; } else { // // get usage minimum from local state // UsageValue = LocalItemState->UsageMinimum;
// // append item index // UsageValue.u.Extended += ReportItemIndex;
if (LocalItemState->UsageMaximumSet) { if (UsageValue.u.Extended > LocalItemState->UsageMaximum.u.Extended) { // // maximum reached // UsageValue.u.Extended = LocalItemState->UsageMaximum.u.Extended; } } }
// // usage usage bounds // UsageMinimum = UsageMaximum = UsageValue.u.Extended; }
// // now store all values // ReportItem->ByteOffset = (Report->ReportSize / 8); ReportItem->Shift = (Report->ReportSize % 8); ReportItem->Mask = ~(0xFFFFFFFF << GlobalItemState->ReportSize); ReportItem->BitCount = GlobalItemState->ReportSize; ReportItem->HasData = (ItemData->DataConstant == FALSE); ReportItem->Array = (ItemData->ArrayVariable == 0); ReportItem->Relative = (ItemData->Relative != FALSE); ReportItem->Minimum = LogicalMinimum; ReportItem->Maximum = LogicalMaximum; ReportItem->UsageMinimum = UsageMinimum; ReportItem->UsageMaximum = UsageMaximum;
// // increment report size // Report->ReportSize += GlobalItemState->ReportSize;
// // completed successfully // return HIDP_STATUS_SUCCESS;}
BOOLEANHidParser_UpdateCurrentCollectionReport( IN PHID_COLLECTION Collection, IN PHID_REPORT Report, IN PHID_REPORT NewReport){ ULONG Index; BOOLEAN Found = FALSE, TempFound;
// // search in local list // for(Index = 0; Index < Collection->ReportCount; Index++) { if (Collection->Reports[Index] == Report) { // // update report // Collection->Reports[Index] = NewReport; Found = TRUE; } }
// // search in sub collections // for(Index = 0; Index < Collection->NodeCount; Index++) { // // was it found // TempFound = HidParser_UpdateCurrentCollectionReport(Collection->Nodes[Index], Report, NewReport); if (TempFound) { // // the same report should not be found in different collections // ASSERT(Found == FALSE); Found = TRUE; } }
// // done // return Found;}
BOOLEANHidParser_UpdateCollectionReport( IN PHID_PARSER_CONTEXT ParserContext, IN PHID_REPORT Report, IN PHID_REPORT NewReport){ // // update in current collection // return HidParser_UpdateCurrentCollectionReport(ParserContext->RootCollection->Nodes[ParserContext->RootCollection->NodeCount-1], Report, NewReport);}
NTSTATUSHidParser_AddMainItem( IN PHID_PARSER_CONTEXT ParserContext, IN PHID_REPORT Report, IN PGLOBAL_ITEM_STATE GlobalItemState, IN PLOCAL_ITEM_STATE LocalItemState, IN PMAIN_ITEM_DATA ItemData, IN PHID_COLLECTION Collection){ NTSTATUS Status; ULONG Index; PHID_REPORT NewReport; BOOLEAN Found;
// // first grow report item array // Status = HidParser_ReserveReportItems(Report, GlobalItemState->ReportCount, &NewReport); if (Status != HIDP_STATUS_SUCCESS) { // // failed to allocate memory // return Status; }
if (NewReport != Report) { // // update current top level collection // Found = HidParser_UpdateCollectionReport(ParserContext, Report, NewReport); ASSERT(Found); }
// // sanity check // ASSERT(NewReport->ItemCount + GlobalItemState->ReportCount <= NewReport->ItemAllocated);
for(Index = 0; Index < GlobalItemState->ReportCount; Index++) { Status = HidParser_InitReportItem(NewReport, &NewReport->Items[NewReport->ItemCount], GlobalItemState, LocalItemState, ItemData, Index); if (Status != HIDP_STATUS_SUCCESS) { // // failed to init report item // return Status; }
// // increment report item count // NewReport->ItemCount++; }
// // done // return HIDP_STATUS_SUCCESS;}
NTSTATUSHidParser_ParseReportDescriptor( IN PUCHAR ReportDescriptor, IN ULONG ReportLength, OUT PVOID *OutParser){ PGLOBAL_ITEM_STATE LinkedGlobalItemState, NextLinkedGlobalItemState; ULONG Index; PUSAGE_VALUE NewUsageStack, UsageValue; NTSTATUS Status; PHID_COLLECTION CurrentCollection, NewCollection; PUCHAR CurrentOffset, ReportEnd; PITEM_PREFIX CurrentItem; ULONG CurrentItemSize; PLONG_ITEM CurrentLongItem; PSHORT_ITEM CurrentShortItem; ULONG Data; UCHAR ReportType; PHID_REPORT Report; PMAIN_ITEM_DATA MainItemData; PHID_PARSER_CONTEXT ParserContext;
CurrentOffset = ReportDescriptor; ReportEnd = ReportDescriptor + ReportLength;
if (ReportDescriptor >= ReportEnd) return HIDP_STATUS_USAGE_NOT_FOUND;
// // allocate parser // ParserContext = AllocFunction(sizeof(HID_PARSER_CONTEXT)); if (!ParserContext) return HIDP_STATUS_INTERNAL_ERROR;
// // allocate usage stack // ParserContext->LocalItemState.UsageStackAllocated = 10; ParserContext->LocalItemState.UsageStack = (PUSAGE_VALUE)AllocFunction(ParserContext->LocalItemState.UsageStackAllocated * sizeof(USAGE_VALUE)); if (!ParserContext->LocalItemState.UsageStack) { // // no memory // FreeFunction(ParserContext); return HIDP_STATUS_INTERNAL_ERROR; }
// // now allocate root collection // Status = HidParser_AllocateCollection(NULL, COLLECTION_LOGICAL, &ParserContext->LocalItemState, &ParserContext->RootCollection); if (Status != HIDP_STATUS_SUCCESS) { // // no memory // FreeFunction(ParserContext->LocalItemState.UsageStack); ParserContext->LocalItemState.UsageStack = NULL; FreeFunction(ParserContext); return HIDP_STATUS_INTERNAL_ERROR; }
// // start parsing // CurrentCollection = ParserContext->RootCollection;
do { // // get current item // CurrentItem = (PITEM_PREFIX)CurrentOffset;
// // get item size // CurrentItemSize = ItemSize[CurrentItem->Size]; Data = 0;
if (CurrentItem->Type == ITEM_TYPE_LONG) { // // increment item size with size of data item // CurrentLongItem = (PLONG_ITEM)CurrentItem; CurrentItemSize += CurrentLongItem->DataSize; } else { // // get short item // CurrentShortItem = (PSHORT_ITEM)CurrentItem;
// // get associated data // //ASSERT(CurrentItemSize == 1 || CurrentItemSize == 2 || CurrentItemSize == 4); if (CurrentItemSize == 1) Data = CurrentShortItem->Data.UData8[0]; else if (CurrentItemSize == 2) Data = CurrentShortItem->Data.UData16[0]; else if (CurrentItemSize == 4) Data = CurrentShortItem->Data.UData32; else { // // invalid item size // //DebugFunction("CurrentItem invalid item size %lu\n", CurrentItemSize); }
} DebugFunction("Tag %x Type %x Size %x Offset %lu Length %lu\n", CurrentItem->Tag, CurrentItem->Type, CurrentItem->Size, ((ULONG_PTR)CurrentItem - (ULONG_PTR)ReportDescriptor), ReportLength); // // handle items // ASSERT(CurrentItem->Type >= ITEM_TYPE_MAIN && CurrentItem->Type <= ITEM_TYPE_LONG); switch(CurrentItem->Type) { case ITEM_TYPE_MAIN: { // preprocess the local state if relevant (usages for // collections and report items) if (CurrentItem->Tag != ITEM_TAG_MAIN_END_COLLECTION) { // make all usages extended for easier later processing for (Index = 0; Index < ParserContext->LocalItemState.UsageStackUsed; Index++) { // // is it already extended // if (ParserContext->LocalItemState.UsageStack[Index].IsExtended) continue;
// // extend usage item // ParserContext->LocalItemState.UsageStack[Index].u.s.UsagePage = ParserContext->GlobalItemState.UsagePage; ParserContext->LocalItemState.UsageStack[Index].IsExtended = TRUE; }
if (!ParserContext->LocalItemState.UsageMinimum.IsExtended) { // the specs say if one of them is extended they must // both be extended, so if the minimum isn't, the // maximum mustn't either. ParserContext->LocalItemState.UsageMinimum.u.s.UsagePage = ParserContext->LocalItemState.UsageMaximum.u.s.UsagePage = ParserContext->GlobalItemState.UsagePage; ParserContext->LocalItemState.UsageMinimum.IsExtended = ParserContext->LocalItemState.UsageMaximum.IsExtended = TRUE; }
//LocalItemState.usage_stack = usageStack; //ParserContext->LocalItemState.UsageStackUsed = UsageStackUsed; }
if (CurrentItem->Tag == ITEM_TAG_MAIN_COLLECTION) {
// // allocate new collection // Status = HidParser_AllocateCollection(CurrentCollection, (UCHAR)Data, &ParserContext->LocalItemState, &NewCollection); ASSERT(Status == HIDP_STATUS_SUCCESS);
// // add new collection to current collection // Status = HidParser_AddCollection(CurrentCollection, NewCollection); ASSERT(Status == HIDP_STATUS_SUCCESS);
// // make new collection current // CurrentCollection = NewCollection; } else if (CurrentItem->Tag == ITEM_TAG_MAIN_END_COLLECTION) { // // assert on ending the root collection // ASSERT(CurrentCollection != ParserContext->RootCollection);
// // use parent of current collection // CurrentCollection = CurrentCollection->Root; ASSERT(CurrentCollection); } else { ReportType = HID_REPORT_TYPE_ANY;
switch (CurrentItem->Tag) { case ITEM_TAG_MAIN_INPUT: ReportType = HID_REPORT_TYPE_INPUT; break;
case ITEM_TAG_MAIN_OUTPUT: ReportType = HID_REPORT_TYPE_OUTPUT; break;
case ITEM_TAG_MAIN_FEATURE: ReportType = HID_REPORT_TYPE_FEATURE; break;
default: DebugFunction("[HIDPARSE] Unknown ReportType Tag %x Type %x Size %x CurrentItemSize %x\n", CurrentItem->Tag, CurrentItem->Type, CurrentItem->Size, CurrentItemSize); ASSERT(FALSE); break; }
if (ReportType == HID_REPORT_TYPE_ANY) break;
// // get report // Status = HidParser_GetReport(ParserContext, CurrentCollection, ReportType, ParserContext->GlobalItemState.ReportId, TRUE, &Report); ASSERT(Status == HIDP_STATUS_SUCCESS);
// fill in a sensible default if the index isn't set if (!ParserContext->LocalItemState.DesignatorIndexSet) { ParserContext->LocalItemState.DesignatorIndex = ParserContext->LocalItemState.DesignatorMinimum; }
if (!ParserContext->LocalItemState.StringIndexSet) ParserContext->LocalItemState.StringIndex = ParserContext->LocalItemState.StringMinimum;
// // get main item data // MainItemData = (PMAIN_ITEM_DATA)&Data;
// // add states & data to the report // Status = HidParser_AddMainItem(ParserContext, Report, &ParserContext->GlobalItemState, &ParserContext->LocalItemState, MainItemData, CurrentCollection); ASSERT(Status == HIDP_STATUS_SUCCESS); }
// // backup stack // Index = ParserContext->LocalItemState.UsageStackAllocated; NewUsageStack = ParserContext->LocalItemState.UsageStack;
// // reset the local item state and clear the usage stack // ZeroFunction(&ParserContext->LocalItemState, sizeof(LOCAL_ITEM_STATE));
// // restore stack // ParserContext->LocalItemState.UsageStack = NewUsageStack; ParserContext->LocalItemState.UsageStackAllocated = Index; break; } case ITEM_TYPE_GLOBAL: { switch (CurrentItem->Tag) { case ITEM_TAG_GLOBAL_USAGE_PAGE: DebugFunction("[HIDPARSE] ITEM_TAG_GLOBAL_USAGE_PAGE %x\n", Data); ParserContext->GlobalItemState.UsagePage = Data; break; case ITEM_TAG_GLOBAL_LOGICAL_MINIMUM: DebugFunction("[HIDPARSE] ITEM_TAG_GLOBAL_LOGICAL_MINIMUM %x\n", Data); ParserContext->GlobalItemState.LogicalMinimum = Data; break;
case ITEM_TAG_GLOBAL_LOGICAL_MAXIMUM: DebugFunction("[HIDPARSE] ITEM_TAG_GLOBAL_LOCAL_MAXIMUM %x\n", Data); ParserContext->GlobalItemState.LogicialMaximum = Data; break;
case ITEM_TAG_GLOBAL_PHYSICAL_MINIMUM: DebugFunction("[HIDPARSE] ITEM_TAG_GLOBAL_PHYSICAL_MINIMUM %x\n", Data); ParserContext->GlobalItemState.PhysicalMinimum = Data; break;
case ITEM_TAG_GLOBAL_PHYSICAL_MAXIMUM: DebugFunction("[HIDPARSE] ITEM_TAG_GLOBAL_PHYSICAL_MAXIMUM %x\n", Data); ParserContext->GlobalItemState.PhysicalMaximum = Data; break;
case ITEM_TAG_GLOBAL_UNIT_EXPONENT: DebugFunction("[HIDPARSE] ITEM_TAG_GLOBAL_REPORT_UNIT_EXPONENT %x\n", Data); ParserContext->GlobalItemState.UnitExponent = Data; break;
case ITEM_TAG_GLOBAL_UNIT: DebugFunction("[HIDPARSE] ITEM_TAG_GLOBAL_REPORT_UNIT %x\n", Data); ParserContext->GlobalItemState.Unit = Data; break;
case ITEM_TAG_GLOBAL_REPORT_SIZE: DebugFunction("[HIDPARSE] ITEM_TAG_GLOBAL_REPORT_SIZE %x\n", Data); ParserContext->GlobalItemState.ReportSize = Data; break;
case ITEM_TAG_GLOBAL_REPORT_ID: DebugFunction("[HIDPARSE] ITEM_TAG_GLOBAL_REPORT_ID %x\n", Data); ParserContext->GlobalItemState.ReportId = Data; ParserContext->UseReportIDs = TRUE; break;
case ITEM_TAG_GLOBAL_REPORT_COUNT: DebugFunction("[HIDPARSE] ITEM_TAG_GLOBAL_REPORT_COUNT %x\n", Data); ParserContext->GlobalItemState.ReportCount = Data; break;
case ITEM_TAG_GLOBAL_PUSH: { DebugFunction("[HIDPARSE] ITEM_TAG_GLOBAL_PUSH\n"); // // allocate global item state // LinkedGlobalItemState = (PGLOBAL_ITEM_STATE)AllocFunction(sizeof(GLOBAL_ITEM_STATE)); ASSERT(LinkedGlobalItemState);
// // copy global item state // CopyFunction(LinkedGlobalItemState, &ParserContext->GlobalItemState, sizeof(GLOBAL_ITEM_STATE));
// // store pushed item in link member // ParserContext->GlobalItemState.Next = (struct __GLOBAL_ITEM_STATE__*)LinkedGlobalItemState; break; } case ITEM_TAG_GLOBAL_POP: { DebugFunction("[HIDPARSE] ITEM_TAG_GLOBAL_POP\n"); if (ParserContext->GlobalItemState.Next == NULL) { // // pop without push // ASSERT(FALSE); break; }
// // get link // LinkedGlobalItemState = (PGLOBAL_ITEM_STATE)ParserContext->GlobalItemState.Next;
// // replace current item with linked one // CopyFunction(&ParserContext->GlobalItemState, LinkedGlobalItemState, sizeof(GLOBAL_ITEM_STATE));
// // free item // FreeFunction(LinkedGlobalItemState); break; }
default: // // unknown / unsupported tag // ASSERT(FALSE); break; }
break; } case ITEM_TYPE_LOCAL: { switch (CurrentItem->Tag) { case ITEM_TAG_LOCAL_USAGE: { if (ParserContext->LocalItemState.UsageStackUsed >= ParserContext->LocalItemState.UsageStackAllocated) { // // increment stack size // ParserContext->LocalItemState.UsageStackAllocated += 10;
// // build new usage stack // NewUsageStack = (PUSAGE_VALUE)AllocFunction(sizeof(USAGE_VALUE) * ParserContext->LocalItemState.UsageStackAllocated); ASSERT(NewUsageStack);
// // copy old usage stack // CopyFunction(NewUsageStack, ParserContext->LocalItemState.UsageStack, sizeof(USAGE_VALUE) * (ParserContext->LocalItemState.UsageStackAllocated - 10));
// // free old usage stack // FreeFunction(ParserContext->LocalItemState.UsageStack);
// // replace with new usage stack // ParserContext->LocalItemState.UsageStack = NewUsageStack; }
// // get fresh usage value // UsageValue = &ParserContext->LocalItemState.UsageStack[ParserContext->LocalItemState.UsageStackUsed];
// // init usage stack // UsageValue->IsExtended = CurrentItemSize == sizeof(ULONG); UsageValue->u.Extended = Data;
// // increment usage stack usage count // ParserContext->LocalItemState.UsageStackUsed++; break; }
case ITEM_TAG_LOCAL_USAGE_MINIMUM: DebugFunction("[HIDPARSE] ITEM_TAG_LOCAL_USAGE_MINIMUM Data %x\n", Data); ParserContext->LocalItemState.UsageMinimum.u.Extended = Data; ParserContext->LocalItemState.UsageMinimum.IsExtended = CurrentItemSize == sizeof(ULONG); ParserContext->LocalItemState.UsageMinimumSet = TRUE; break;
case ITEM_TAG_LOCAL_USAGE_MAXIMUM: DebugFunction("[HIDPARSE] ITEM_TAG_LOCAL_USAGE_MAXIMUM Data %x ItemSize %x %x\n", Data, CurrentItemSize, CurrentItem->Size); ParserContext->LocalItemState.UsageMaximum.u.Extended = Data; ParserContext->LocalItemState.UsageMaximum.IsExtended = CurrentItemSize == sizeof(ULONG); ParserContext->LocalItemState.UsageMaximumSet = TRUE; break;
case ITEM_TAG_LOCAL_DESIGNATOR_INDEX: DebugFunction("[HIDPARSE] ITEM_TAG_LOCAL_DESIGNATOR_INDEX Data %x\n", Data); ParserContext->LocalItemState.DesignatorIndex = Data; ParserContext->LocalItemState.DesignatorIndexSet = TRUE; break;
case ITEM_TAG_LOCAL_DESIGNATOR_MINIMUM: DebugFunction("[HIDPARSE] ITEM_TAG_LOCAL_DESIGNATOR_MINIMUM Data %x\n", Data); ParserContext->LocalItemState.DesignatorMinimum = Data; break;
case ITEM_TAG_LOCAL_DESIGNATOR_MAXIMUM: DebugFunction("[HIDPARSE] ITEM_TAG_LOCAL_DESIGNATOR_MAXIMUM Data %x\n", Data); ParserContext->LocalItemState.DesignatorMaximum = Data; break;
case ITEM_TAG_LOCAL_STRING_INDEX: DebugFunction("[HIDPARSE] ITEM_TAG_LOCAL_STRING_INDEX Data %x\n", Data); ParserContext->LocalItemState.StringIndex = Data; ParserContext->LocalItemState.StringIndexSet = TRUE; break;
case ITEM_TAG_LOCAL_STRING_MINIMUM: DebugFunction("[HIDPARSE] ITEM_TAG_LOCAL_STRING_MINIMUM Data %x\n", Data); ParserContext->LocalItemState.StringMinimum = Data; break;
case ITEM_TAG_LOCAL_STRING_MAXIMUM: DebugFunction("[HIDPARSE] ITEM_TAG_LOCAL_STRING_MAXIMUM Data %x\n", Data); ParserContext->LocalItemState.StringMaximum = Data; break;
default: DebugFunction("Unknown Local Item Tag %x\n", CurrentItem->Tag); ASSERT(FALSE); break; } break; }
case ITEM_TYPE_LONG: { CurrentLongItem = (PLONG_ITEM)CurrentItem; DebugFunction("Unsupported ITEM_TYPE_LONG Tag %x\n", CurrentLongItem->LongItemTag); break; } }
// // move to next item // CurrentOffset += CurrentItemSize + sizeof(ITEM_PREFIX);
}while (CurrentOffset < ReportEnd);
// // cleanup global stack // LinkedGlobalItemState = (PGLOBAL_ITEM_STATE)ParserContext->GlobalItemState.Next; while(LinkedGlobalItemState != NULL) { DebugFunction("[HIDPARSE] Freeing GlobalState %p\n", LinkedGlobalItemState); // // free global item state // NextLinkedGlobalItemState = (PGLOBAL_ITEM_STATE)LinkedGlobalItemState->Next;
// // free state // FreeFunction(LinkedGlobalItemState);
// // move to next global state // LinkedGlobalItemState = NextLinkedGlobalItemState; }
// // free usage stack // FreeFunction(ParserContext->LocalItemState.UsageStack); ParserContext->LocalItemState.UsageStack = NULL;
// // store result // *OutParser = ParserContext;
// // done // return HIDP_STATUS_SUCCESS;}
PHID_COLLECTIONHidParser_GetCollection( PHID_PARSER_CONTEXT ParserContext, IN ULONG CollectionNumber){ // // 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 // DebugFunction("HIDPARSE] No such collection %lu\n", CollectionNumber); return NULL;}
ULONGHidParser_NumberOfTopCollections( IN PVOID ParserCtx){ PHID_PARSER_CONTEXT ParserContext;
// // get parser context // ParserContext = (PHID_PARSER_CONTEXT)ParserCtx;
// // sanity checks // ASSERT(ParserContext); ASSERT(ParserContext->RootCollection); ASSERT(ParserContext->RootCollection->NodeCount);
// // number of top collections // return ParserContext->RootCollection->NodeCount;}
NTSTATUSHidParser_BuildContext( IN PVOID ParserContext, IN ULONG CollectionIndex, IN ULONG ContextSize, OUT PVOID *CollectionContext){ PHID_COLLECTION Collection; PVOID Context; NTSTATUS Status;
// // lets get the collection // Collection = HidParser_GetCollection((PHID_PARSER_CONTEXT)ParserContext, CollectionIndex); ASSERT(Collection);
// // lets allocate the context // Context = AllocFunction(ContextSize); if (Context == NULL) { // // no memory // return HIDP_STATUS_INTERNAL_ERROR; }
// // lets build the context // Status = HidParser_BuildCollectionContext(Collection, Context, ContextSize); if (Status == HIDP_STATUS_SUCCESS) { // // store context // *CollectionContext = Context; }
// // done // return Status;}
ULONGHidParser_GetContextSize( IN PVOID ParserContext, IN ULONG CollectionIndex){ PHID_COLLECTION Collection; ULONG Size;
// // lets get the collection // Collection = HidParser_GetCollection((PHID_PARSER_CONTEXT)ParserContext, CollectionIndex);
// // calculate size // Size = HidParser_CalculateContextSize(Collection); return Size;}