HIDCountDescriptorItems.c [plain text]
#include "HIDLib.h"
OSStatus HIDCountDescriptorItems(HIDReportDescriptor *ptDescriptor, HIDPreparsedDataPtr ptPreparsedData)
{
OSStatus iStatus;
ByteCount iSpaceRequired;
HIDItem *ptItem;
Byte *pMem;
int collectionCount = 1;
int reportItemCount = 0;
int iUsages = 0;
int iUsageRanges = 0;
int iStrings = 0;
int iStringRanges = 0;
int iDesigs = 0;
int iDesigRanges = 0;
int reportCount = 1;
int globalsNesting = 0;
int iMaxGlobalsNesting = 0;
int collectionNesting = 0;
int iMaxCollectionNesting = 0;
if ((ptDescriptor == NULL) || (ptPreparsedData == NULL))
return kHIDNullPointerErr;
ptPreparsedData->rawMemPtr = NULL;
ptDescriptor->index = 0;
ptItem = &ptDescriptor->item;
while ((iStatus = HIDNextItem(ptDescriptor)) == kHIDSuccess)
{
switch (ptItem->itemType)
{
case kHIDTypeMain:
switch (ptItem->tag)
{
case kHIDTagCollection:
collectionCount++;
collectionNesting++;
if (collectionNesting > iMaxCollectionNesting)
iMaxCollectionNesting = collectionNesting;
break;
case kHIDTagEndCollection:
if (collectionNesting-- == 0)
return kHIDInvalidPreparsedDataErr;
break;
case kHIDTagInput:
case kHIDTagOutput:
case kHIDTagFeature:
reportItemCount++;
break;
}
break;
case kHIDTypeGlobal:
switch (ptItem->tag)
{
case kHIDTagReportID:
reportCount++;
break;
case kHIDTagPush:
globalsNesting++;
if (globalsNesting > iMaxGlobalsNesting)
iMaxGlobalsNesting = globalsNesting;
break;
case kHIDTagPop:
globalsNesting--;
if (globalsNesting < 0)
return kHIDInvalidPreparsedDataErr;
break;
}
break;
case kHIDTypeLocal:
switch (ptItem->tag)
{
case kHIDTagUsage:
iUsages++;
break;
case kHIDTagUsageMinimum:
case kHIDTagUsageMaximum:
iUsageRanges++;
break;
case kHIDTagStringIndex:
iStrings++;
break;
case kHIDTagStringMinimum:
case kHIDTagStringMaximum:
iStringRanges++;
break;
case kHIDTagDesignatorIndex:
iDesigs++;
break;
case kHIDTagDesignatorMinimum:
case kHIDTagDesignatorMaximum:
iDesigRanges++;
break;
}
}
}
if ((collectionNesting != 0)
|| (collectionCount == 1)
|| (reportItemCount == 0)
|| ((iUsageRanges & 1) == 1)
|| ((iStringRanges & 1) == 1)
|| ((iDesigRanges & 1) == 1))
return kHIDInvalidPreparsedDataErr;
iUsages += (iUsageRanges/2);
iStrings += (iStringRanges/2);
iDesigs += (iDesigRanges/2);
iSpaceRequired = (sizeof(HIDCollection) * collectionCount)
+ (sizeof(HIDReportItem) * reportItemCount)
+ (sizeof(HIDReportSizes) * reportCount)
+ (sizeof(HIDP_UsageItem) * iUsages)
+ (sizeof(HIDStringItem) * iStrings)
+ (sizeof(HIDDesignatorItem) * iDesigs)
+ (sizeof(int) * iMaxCollectionNesting)
+ (sizeof(HIDGlobalItems) * iMaxGlobalsNesting);
pMem = malloc(iSpaceRequired);
if (pMem == NULL)
return kHIDNotEnoughMemoryErr;
memset(pMem, 0, iSpaceRequired); ptPreparsedData->rawMemPtr = pMem;
ptPreparsedData->collections = (HIDCollection *) pMem;
ptPreparsedData->collectionCount = 0;
pMem += (sizeof(HIDCollection) * collectionCount);
ptPreparsedData->reportItems = (HIDReportItem *) pMem;
ptPreparsedData->reportItemCount = 0;
pMem += (sizeof(HIDReportItem) * reportItemCount);
ptPreparsedData->reports = (HIDReportSizes *) pMem;
ptPreparsedData->reportCount = 0;
pMem += (sizeof(HIDReportSizes) * reportCount);
ptPreparsedData->usageItems = (HIDP_UsageItem *) pMem;
ptPreparsedData->usageItemCount = 0;
pMem += (sizeof(HIDP_UsageItem) * iUsages);
ptPreparsedData->stringItems = (HIDStringItem *) pMem;
ptPreparsedData->stringItemCount = 0;
pMem += (sizeof(HIDStringItem) * iStrings);
ptPreparsedData->desigItems = (HIDDesignatorItem *) pMem;
ptPreparsedData->desigItemCount = 0;
pMem += (sizeof(HIDDesignatorItem) * iDesigs);
ptDescriptor->collectionStack = (SInt32 *) pMem;
ptDescriptor->collectionNesting = 0;
pMem += (sizeof(SInt32) * iMaxCollectionNesting);
ptDescriptor->globalsStack = (HIDGlobalItems *) pMem;
ptDescriptor->globalsNesting = 0;
if (iStatus == kHIDEndOfDescriptorErr)
return kHIDSuccess;
return iStatus;
}