static BOOL USB_HID_KEYBOARD_DataCollectionHandler(BYTE deviceAddress) { BYTE NumOfReportItem; BYTE i; USB_HID_ITEM_LIST *pitemListPtrs; USB_HID_DEVICE_RPT_INFO *pDeviceRptinfo; HID_REPORTITEM *reportItem; HID_USAGEITEM *hidUsageItem; BYTE usageIndex; BYTE reportIndex; BOOL foundLEDIndicator = FALSE; BOOL foundModifierKey = FALSE; BOOL foundNormalKey = FALSE; BOOL status; pDeviceRptinfo = USBHostHID_GetCurrentReportInfo(); // Get current Report Info pointer pitemListPtrs = USBHostHID_GetItemListPointers(); // Get pointer to list of item pointers foundLEDIndicator = foundModifierKey = foundNormalKey = FALSE; status = FALSE; reportIndex = 0; NumOfReportItem = pDeviceRptinfo->reportItems; for(i=0;i<NumOfReportItem;i++){ reportItem = &pitemListPtrs->reportItemList[i]; if((reportItem->reportType==hidReportInput) && (reportItem->dataModes == HIDData_Variable)&& (reportItem->globals.usagePage==USAGE_PAGE_KEY_CODES)){ usageIndex = reportItem->firstUsageItem; hidUsageItem = &pitemListPtrs->usageItemList[usageIndex]; if((hidUsageItem->usageMinimum == USAGE_MIN_MODIFIER_KEY) &&(hidUsageItem->usageMaximum == USAGE_MAX_MODIFIER_KEY)){ //else application cannot suuport reportIndex = reportItem->globals.reportIndex; Appl_ModifierKeysDetails[deviceAddress].reportLength = (pitemListPtrs->reportList[reportIndex].inputBits + 7)/8; Appl_ModifierKeysDetails[deviceAddress].reportID = (BYTE)reportItem->globals.reportID; Appl_ModifierKeysDetails[deviceAddress].bitOffset = (BYTE)reportItem->startBit; Appl_ModifierKeysDetails[deviceAddress].bitLength = (BYTE)reportItem->globals.reportsize; Appl_ModifierKeysDetails[deviceAddress].count=(BYTE)reportItem->globals.reportCount; Appl_ModifierKeysDetails[deviceAddress].interfaceNum= USBHostHID_ApiGetCurrentInterfaceNum(); foundModifierKey = TRUE; } }else if((reportItem->reportType==hidReportInput) && (reportItem->dataModes == HIDData_Array)&& (reportItem->globals.usagePage==USAGE_PAGE_KEY_CODES)){ usageIndex = reportItem->firstUsageItem; hidUsageItem = &pitemListPtrs->usageItemList[usageIndex]; if((hidUsageItem->usageMinimum == USAGE_MIN_NORMAL_KEY) &&(hidUsageItem->usageMaximum <= USAGE_MAX_NORMAL_KEY)){ //else application cannot suuport reportIndex = reportItem->globals.reportIndex; Appl_NormalKeysDetails[deviceAddress].reportLength = (pitemListPtrs->reportList[reportIndex].inputBits + 7)/8; Appl_NormalKeysDetails[deviceAddress].reportID = (BYTE)reportItem->globals.reportID; Appl_NormalKeysDetails[deviceAddress].bitOffset = (BYTE)reportItem->startBit; Appl_NormalKeysDetails[deviceAddress].bitLength = (BYTE)reportItem->globals.reportsize; Appl_NormalKeysDetails[deviceAddress].count=(BYTE)reportItem->globals.reportCount; Appl_NormalKeysDetails[deviceAddress].interfaceNum= USBHostHID_ApiGetCurrentInterfaceNum(); foundNormalKey = TRUE; } }else if((reportItem->reportType==hidReportOutput) && (reportItem->globals.usagePage==USAGE_PAGE_LEDS)){ usageIndex = reportItem->firstUsageItem; hidUsageItem = &pitemListPtrs->usageItemList[usageIndex]; reportIndex = reportItem->globals.reportIndex; Appl_LED_Indicator[deviceAddress].reportLength = (pitemListPtrs->reportList[reportIndex].outputBits + 7)/8; Appl_LED_Indicator[deviceAddress].reportID = (BYTE)reportItem->globals.reportID; Appl_LED_Indicator[deviceAddress].bitOffset = (BYTE)reportItem->startBit; Appl_LED_Indicator[deviceAddress].bitLength = (BYTE)reportItem->globals.reportsize; Appl_LED_Indicator[deviceAddress].count=(BYTE)reportItem->globals.reportCount; Appl_LED_Indicator[deviceAddress].interfaceNum= USBHostHID_ApiGetCurrentInterfaceNum(); foundLEDIndicator = TRUE; } } if(pDeviceRptinfo->reports == 1){ Appl_raw_report_buffer[deviceAddress].Report_ID = 0; Appl_raw_report_buffer[deviceAddress].ReportSize = (pitemListPtrs->reportList[reportIndex].inputBits + 7)/8; Appl_raw_report_buffer[deviceAddress].ReportData = (BYTE*)USB_MALLOC(Appl_raw_report_buffer[deviceAddress].ReportSize); Appl_raw_report_buffer[deviceAddress].ReportPollRate = pDeviceRptinfo->reportPollingRate; if((foundNormalKey == TRUE)&&(foundModifierKey == TRUE)) status = TRUE; } return(status); }
/**************************************************************************** Function: USB_HID_RPT_DESC_ERROR _USBHostHID_Parse_Report(uint8_t* hidReportDescriptor ,uint16_t lengthOfDescriptor, uint16_t pollRate, uint8_t interfaceNum) Description: This function is called by usb_host_hid.c after a valid configuration device is found. This function parses the report descriptor and stores data in data structures. Application can access these data structures to understand report format and device capabilities Precondition: None Parameters: uint8_t* hidReportDescriptor - Pointer to raw report descriptor uint16_t lengthOfDescriptor - Length of Report Descriptor uint16_t pollRate - Poll rate of the report uint8_t interfaceNum - interface number of the respective report descriptor. Return Values: USB_HID_RPT_DESC_ERROR - Returns error code(enum) if found while parsing the report descriptor Remarks: None ***************************************************************************/ USB_HID_RPT_DESC_ERROR _USBHostHID_Parse_Report(uint8_t* hidReportDescriptor , uint16_t lengthOfDescriptor , uint16_t pollRate, uint8_t interfaceNum) { uint16_t sizeRequired = 0; uint16_t len_to_be_parsed =0; uint8_t* currentRptDescPtr = NULL; uint8_t* assignMem = NULL; /* Main Item Vars */ HID_COLLECTION *collectionLocal = NULL; HID_REPORT *reportLocal = NULL; /* Global Item Vars */ HID_REPORT *lreport = NULL; uint8_t lreportIndex = (uint8_t)0; /* Local Item Vars */ HID_DESIGITEM *ldesignatorItem = NULL; HID_STRINGITEM *lstringItem = NULL; HID_USAGEITEM *lusageItem = NULL; /*HID Error */ USB_HID_RPT_DESC_ERROR lhidError = HID_ERR; HID_ITEM_INFO item; uint8_t i=0; uint8_t dataByte=0 ; uint8_t ldataSize=0; if((hidReportDescriptor == NULL) ||(lengthOfDescriptor == 0)) { /* set error flag */ return(HID_ERR_NullPointer); } memset( &deviceRptInfo, 0x00, sizeof( USB_HID_DEVICE_RPT_INFO ) ); _USBHostHID_InitDeviceRptInfo(); deviceRptInfo.interfaceNumber = interfaceNum; // update interface number for the report deviceRptInfo.reportPollingRate = pollRate; len_to_be_parsed = lengthOfDescriptor; currentRptDescPtr = hidReportDescriptor; while(len_to_be_parsed > 0) /* First parse to calculate the space required for all the items */ { item.ItemDetails.val = *currentRptDescPtr; /* Data need not be parsed at this point */ ldataSize = item.ItemDetails.ItemSize ; if(item.ItemDetails.ItemSize == 3) ldataSize = 4; currentRptDescPtr += (ldataSize+1) ; /* point to next item i.e size of item data + 1(item detail) */ len_to_be_parsed -= (ldataSize+1); /* remaining bytes = current - (length of data + 1)*/ switch (item.ItemDetails.ItemType) { case HIDType_Main: /* Main Items */ switch (item.ItemDetails.ItemTag) { case HIDTag_Collection: deviceRptInfo.collections++; deviceRptInfo.collectionNesting++; if (deviceRptInfo.collectionNesting > deviceRptInfo.maxCollectionNesting) deviceRptInfo.maxCollectionNesting = deviceRptInfo.collectionNesting; break; case HIDTag_EndCollection: if (deviceRptInfo.collectionNesting-- == 0) lhidError = HID_ERR_UnexpectedEndCollection ;/* Error: UnexpectedEndCollection */ break; case HIDTag_Input: case HIDTag_Output: case HIDTag_Feature: deviceRptInfo.reportItems++; break; default : break; } break; case HIDType_Global: /* Global Items */ switch (item.ItemDetails.ItemTag) { case HIDTag_ReportID: deviceRptInfo.reports++; break; case HIDTag_Push: deviceRptInfo.globalsNesting++; if (deviceRptInfo.globalsNesting > deviceRptInfo.maxGlobalsNesting) deviceRptInfo.maxGlobalsNesting = deviceRptInfo.globalsNesting; break; case HIDTag_Pop: deviceRptInfo.globalsNesting--; if (deviceRptInfo.globalsNesting > deviceRptInfo.maxGlobalsNesting) lhidError = HID_ERR_UnexpectedPop ;/* Error: global nesting rolled to negative ... */ break; default : break; } break; case HIDType_Local: /* Local Item */ switch (item.ItemDetails.ItemTag) { case HIDTag_Usage: deviceRptInfo.usages++; break; case HIDTag_UsageMinimum: case HIDTag_UsageMaximum: deviceRptInfo.usageRanges++; break; case HIDTag_StringIndex: deviceRptInfo.strings++; break; case HIDTag_StringMinimum: case HIDTag_StringMaximum: deviceRptInfo.stringRanges++; break; case HIDTag_DesignatorIndex: deviceRptInfo.designators++; break; case HIDTag_DesignatorMinimum: case HIDTag_DesignatorMaximum: deviceRptInfo.designatorRanges++; break; default : break; } break; default : break; } } if(lhidError) { return(lhidError); } if (deviceRptInfo.collectionNesting != 0) return(HID_ERR_MissingEndCollection) /* HID_RPT_DESC_FORMAT_IMPROPER */; if (deviceRptInfo.collections == 1) return(HID_ERR_MissingTopLevelCollection) /* HID_RPT_DESC_FORMAT_IMPROPER */; if (deviceRptInfo.reportItems == 0) return(HID_ERR_NoReports)/* HID_RPT_DESC_FORMAT_IMPROPER */; if ((deviceRptInfo.usageRanges & 1) == 1) return(HID_ERR_UnmatchedUsageRange)/* HID_RPT_DESC_FORMAT_IMPROPER */; if ((deviceRptInfo.stringRanges & 1) == 1) return(HID_ERR_UnmatchedStringRange)/* HID_RPT_DESC_FORMAT_IMPROPER */; if ((deviceRptInfo.designatorRanges & 1) == 1) return(HID_ERR_UnmatchedDesignatorRange)/* HID_RPT_DESC_FORMAT_IMPROPER */; /* usages , strings & descriptors are in pair */ deviceRptInfo.usages += (deviceRptInfo.usageRanges/2); deviceRptInfo.strings += (deviceRptInfo.stringRanges/2); deviceRptInfo.designators += (deviceRptInfo.designatorRanges/2); /* Calculate space required */ sizeRequired = (sizeof(HID_COLLECTION) * deviceRptInfo.collections) + (sizeof(HID_REPORTITEM) * deviceRptInfo.reportItems) + (sizeof(HID_REPORT) * deviceRptInfo.reports) + (sizeof(HID_USAGEITEM) * deviceRptInfo.usages) + (sizeof(HID_STRINGITEM) * deviceRptInfo.strings) + (sizeof(HID_DESIGITEM) * deviceRptInfo.designators) + (sizeof(int) * deviceRptInfo.maxCollectionNesting) + (sizeof(HID_GLOBALS) * deviceRptInfo.maxGlobalsNesting); if (parsedDataMem != NULL) { USB_FREE_AND_CLEAR( parsedDataMem ); } parsedDataMem = (uint8_t*) USB_MALLOC(sizeRequired); #ifdef DEBUG_MODE UART2PrintString( "HID: Memory for Report Descriptor: " ); UART2PutHex( sizeRequired ); #endif if (parsedDataMem == NULL) return(HID_ERR_NotEnoughMemory); /* Error: Not enough memory */ assignMem = (uint8_t*) parsedDataMem; /* Allocate Space */ itemListPtrs.collectionList = (HID_COLLECTION *) assignMem; assignMem += (sizeof(HID_COLLECTION) * deviceRptInfo.collections); itemListPtrs.reportItemList = (HID_REPORTITEM *) assignMem; assignMem += (sizeof(HID_REPORTITEM) * deviceRptInfo.reportItems); itemListPtrs.reportList = (HID_REPORT *) assignMem; assignMem += (sizeof(HID_REPORT) * deviceRptInfo.reports); itemListPtrs.usageItemList = (HID_USAGEITEM *) assignMem; assignMem += (sizeof(HID_USAGEITEM) * deviceRptInfo.usages); itemListPtrs.stringItemList = (HID_STRINGITEM *) assignMem; assignMem += (sizeof(HID_STRINGITEM) * deviceRptInfo.strings); itemListPtrs.designatorItemList = (HID_DESIGITEM *) assignMem; assignMem += (sizeof(HID_DESIGITEM) * deviceRptInfo.designators); itemListPtrs.collectionStack = (uint8_t *) assignMem; assignMem += (sizeof(int) * deviceRptInfo.maxCollectionNesting); itemListPtrs.globalsStack = (HID_GLOBALS *) assignMem; _USBHostHID_InitDeviceRptInfo(); // Initialize the virtual collection collectionLocal = itemListPtrs.collectionList; collectionLocal->data = 0; collectionLocal->firstChild = 0; collectionLocal->firstReportItem = 0; collectionLocal->firstUsageItem = 0; collectionLocal->nextSibling = 0; collectionLocal->parent = 0; collectionLocal->reportItems = 0; collectionLocal->usageItems = 0; collectionLocal->usagePage = 0; // Initialize the default report reportLocal = itemListPtrs.reportList; reportLocal->featureBits = 0; reportLocal->inputBits = 0; reportLocal->outputBits = 0; reportLocal->reportID = 0; /* re-init ptr to Rpt Descp & Length of Descp */ len_to_be_parsed = lengthOfDescriptor; currentRptDescPtr = hidReportDescriptor; #ifdef DEBUG_MODE UART2PrintString( "HID-HOST: ... 2nd Parse \n" ); #endif while(len_to_be_parsed > 0) /* Second parse to fill the tables with each item detail */ { item.ItemDetails.val = *currentRptDescPtr; item.Data.uItemData = 0; ldataSize = item.ItemDetails.ItemSize ; if(item.ItemDetails.ItemSize == 3) ldataSize = 4; currentRptDescPtr++; /* ptr points to data */ for (i = 0; i < ldataSize; i++) { dataByte = *currentRptDescPtr++; /* signed data will be taken care in ItemTag it is expected */ item.Data.uItemData |= ((uint32_t)dataByte << (i*8)); } len_to_be_parsed -= (ldataSize+1); /* remaining bytes = current - (length of current item + 1)*/ switch(item.ItemDetails.ItemType) { case HIDType_Main: /* look for Main Items*/ switch(item.ItemDetails.ItemTag) { case HIDTag_Input : case HIDTag_Output : case HIDTag_Feature : lhidError = _USBHostHID_Parse_ReportType(&item); break; case HIDTag_Collection : _USBHostHID_Parse_Collection(&item); break; case HIDTag_EndCollection : _USBHostHID_Parse_EndCollection(&item); break; } break; case HIDType_Global: /* look for Global Items*/ switch(item.ItemDetails.ItemTag) { case HIDTag_UsagePage : deviceRptInfo.globals.usagePage = item.Data.uItemData; break; case HIDTag_LogicalMinimum : /* convert to signed val */ // Sign extend one value _USBHostHID_ConvertDataToSigned(&item); deviceRptInfo.globals.logicalMinimum = item.Data.sItemData; break; case HIDTag_LogicalMaximum :/* convert to signed val */ // Sign extend one value _USBHostHID_ConvertDataToSigned(&item); deviceRptInfo.globals.logicalMaximum = item.Data.uItemData; break; case HIDTag_PhysicalMinimum :/* convert to signed val */ // Sign extend one value _USBHostHID_ConvertDataToSigned(&item); deviceRptInfo.globals.physicalMinimum = item.Data.uItemData; break; case HIDTag_PhysicalMaximum :/* convert to signed val */ // Sign extend one value _USBHostHID_ConvertDataToSigned(&item); deviceRptInfo.globals.physicalMaximum = item.Data.uItemData; break; case HIDTag_UnitExponent : deviceRptInfo.globals.unitExponent = item.Data.uItemData; break; case HIDTag_ReportSize : deviceRptInfo.globals.reportsize = item.Data.uItemData; if (deviceRptInfo.globals.reportsize == 0) lhidError = HID_ERR_ZeroReportSize; break; case HIDTag_ReportID : if (item.Data.uItemData) { // Look for the Report ID in the table lreportIndex = 0; while ((lreportIndex < deviceRptInfo.reports) && (itemListPtrs.reportList[lreportIndex].reportID != item.Data.uItemData)) lreportIndex++; // initialize the entry if it's new and there's room for it // Start with 8 bits for the Report ID if (lreportIndex == deviceRptInfo.reports) { lreport = &itemListPtrs.reportList[deviceRptInfo.reports++]; lreport->reportID = item.Data.uItemData; lreport->inputBits = 8; lreport->outputBits = 8; lreport->featureBits = 8; } // remember which report is being processed deviceRptInfo.globals.reportID = item.Data.uItemData; deviceRptInfo.globals.reportIndex = lreportIndex; } else { lhidError = HID_ERR_ZeroReportID; } break; case HIDTag_ReportCount : if (item.Data.uItemData) { deviceRptInfo.globals.reportCount = item.Data.uItemData; } else { lhidError = HID_ERR_ZeroReportCount; } break; case HIDTag_Push : itemListPtrs.globalsStack[deviceRptInfo.globalsNesting++] = deviceRptInfo.globals; break; case HIDTag_Pop : deviceRptInfo.globals = itemListPtrs.globalsStack[--deviceRptInfo.globalsNesting] ; break; } break; case HIDType_Local: /* look for Local Items*/ switch(item.ItemDetails.ItemTag) { case HIDTag_Usage : lusageItem = &itemListPtrs.usageItemList[deviceRptInfo.usageItems++]; lusageItem->isRange = false; if (item.ItemDetails.ItemSize == 3) /* 4 data bytes */ { lusageItem->usagePage = item.Data.uItemData >> 16; lusageItem->usage = item.Data.uItemData & 0x00FF; } else { lusageItem->usagePage = deviceRptInfo.globals.usagePage; lusageItem->usage = item.Data.uItemData; } break; case HIDTag_UsageMinimum : if(deviceRptInfo.haveUsageMax) { lusageItem = &itemListPtrs.usageItemList[deviceRptInfo.usageItems++]; lusageItem->isRange = true; if(item.ItemDetails.ItemSize == 3) { lusageItem->usagePage = item.Data.uItemData >> 16; lusageItem->usageMinimum = item.Data.uItemData & 0x00FFL; } else {