diff --git a/Demos/Host/LowLevel/KeyboardHostWithParser/KeyboardHostWithParser.c b/Demos/Host/LowLevel/KeyboardHostWithParser/KeyboardHostWithParser.c index 3c9f304910..3e6aa28cb0 100644 --- a/Demos/Host/LowLevel/KeyboardHostWithParser/KeyboardHostWithParser.c +++ b/Demos/Host/LowLevel/KeyboardHostWithParser/KeyboardHostWithParser.c @@ -182,6 +182,20 @@ void Keyboard_HID_Task(void) break; } + printf("Total Reports: %d\r\n", HIDReportInfo.TotalDeviceReports); + + for (uint8_t i = 0; i < HIDReportInfo.TotalDeviceReports; i++) + { + HID_ReportSizeInfo_t* CurrReportIDInfo = &HIDReportInfo.ReportIDSizes[i]; + + /* Print out the byte sizes of each report within the device */ + printf_P(PSTR(" + Report ID %d - In: %d bytes, Out: %d bytes, Feature: %d bytes\r\n"), + CurrReportIDInfo->ReportID, + ((CurrReportIDInfo->BitsIn >> 3) + (CurrReportIDInfo->BitsIn & 0x07)), + ((CurrReportIDInfo->BitsOut >> 3) + (CurrReportIDInfo->BitsOut & 0x07)), + ((CurrReportIDInfo->BitsFeature >> 3) + (CurrReportIDInfo->BitsFeature & 0x07))); + } + puts_P(PSTR("Keyboard Enumerated.\r\n")); USB_HostState = HOST_STATE_Configured; diff --git a/Demos/Host/LowLevel/MouseHostWithParser/MouseHostWithParser.c b/Demos/Host/LowLevel/MouseHostWithParser/MouseHostWithParser.c index 69ba64b138..670cab919c 100644 --- a/Demos/Host/LowLevel/MouseHostWithParser/MouseHostWithParser.c +++ b/Demos/Host/LowLevel/MouseHostWithParser/MouseHostWithParser.c @@ -181,6 +181,20 @@ void Mouse_HID_Task(void) USB_HostState = HOST_STATE_WaitForDeviceRemoval; break; } + + printf("Total Reports: %d\r\n", HIDReportInfo.TotalDeviceReports); + + for (uint8_t i = 0; i < HIDReportInfo.TotalDeviceReports; i++) + { + HID_ReportSizeInfo_t* CurrReportIDInfo = &HIDReportInfo.ReportIDSizes[i]; + + /* Print out the byte sizes of each report within the device */ + printf_P(PSTR(" + Report ID %d - In: %d bytes, Out: %d bytes, Feature: %d bytes\r\n"), + CurrReportIDInfo->ReportID, + ((CurrReportIDInfo->BitsIn >> 3) + (CurrReportIDInfo->BitsIn & 0x07)), + ((CurrReportIDInfo->BitsOut >> 3) + (CurrReportIDInfo->BitsOut & 0x07)), + ((CurrReportIDInfo->BitsFeature >> 3) + (CurrReportIDInfo->BitsFeature & 0x07))); + } puts_P(PSTR("Mouse Enumerated.\r\n")); @@ -190,7 +204,7 @@ void Mouse_HID_Task(void) /* Select and unfreeze mouse data pipe */ Pipe_SelectPipe(MOUSE_DATAPIPE); Pipe_Unfreeze(); - + /* Check to see if a packet has been received */ if (Pipe_IsINReceived()) { diff --git a/LUFA/Drivers/USB/Class/Host/HIDParser.c b/LUFA/Drivers/USB/Class/Host/HIDParser.c index 5174b59f93..4293a3d98f 100644 --- a/LUFA/Drivers/USB/Class/Host/HIDParser.c +++ b/LUFA/Drivers/USB/Class/Host/HIDParser.c @@ -38,19 +38,19 @@ uint8_t USB_ProcessHIDReport(const uint8_t* ReportData, uint16_t ReportSize, HID HID_StateTable_t StateTable[HID_STATETABLE_STACK_DEPTH]; HID_StateTable_t* CurrStateTable = &StateTable[0]; HID_CollectionPath_t* CurrCollectionPath = NULL; + HID_ReportSizeInfo_t* CurrReportIDInfo = &ParserData->ReportIDSizes[0]; uint16_t UsageStack[HID_USAGE_STACK_DEPTH]; uint8_t UsageStackSize = 0; - uint16_t BitOffsetIn = 0; - uint16_t BitOffsetOut = 0; - uint16_t BitOffsetFeature = 0; - ParserData->TotalReportItems = 0; - ParserData->UsingMultipleReports = false; + ParserData->TotalReportItems = 0; + ParserData->TotalDeviceReports = 1; + ParserData->UsingReportIDs = false; for (uint8_t CurrCollection = 0; CurrCollection < HID_MAX_COLLECTIONS; CurrCollection++) ParserData->CollectionPaths[CurrCollection].Parent = NULL; - memset(&StateTable[0], 0x00, sizeof(HID_StateTable_t)); + memset(CurrStateTable, 0x00, sizeof(HID_StateTable_t)); + memset(CurrReportIDInfo, 0x00, sizeof(HID_ReportSizeInfo_t)); while (ReportSize) { @@ -126,10 +126,33 @@ uint8_t USB_ProcessHIDReport(const uint8_t* ReportData, uint16_t ReportSize, HID break; case (TYPE_GLOBAL | TAG_GLOBAL_REPORTID): CurrStateTable->ReportID = ReportItemData; - ParserData->UsingMultipleReports = true; - BitOffsetIn = 0; - BitOffsetOut = 0; - BitOffsetFeature = 0; + + if (ParserData->UsingReportIDs) + { + CurrReportIDInfo = NULL; + + for (uint8_t i = 0; i < ParserData->TotalDeviceReports; i++) + { + if (ParserData->ReportIDSizes[i].ReportID == CurrStateTable->ReportID) + { + CurrReportIDInfo = &ParserData->ReportIDSizes[i]; + break; + } + } + + if (CurrReportIDInfo == NULL) + { + if (ParserData->TotalDeviceReports++ > HID_MAX_REPORT_IDS) + return HID_PARSE_InsufficientReportIDItems; + + CurrReportIDInfo = &ParserData->ReportIDSizes[ParserData->TotalDeviceReports - 1]; + memset(CurrReportIDInfo, 0x00, sizeof(HID_ReportSizeInfo_t)); + } + } + + ParserData->UsingReportIDs = true; + + CurrReportIDInfo->ReportID = CurrStateTable->ReportID; break; case (TYPE_LOCAL | TAG_LOCAL_USAGE): if (UsageStackSize == HID_USAGE_STACK_DEPTH) @@ -223,21 +246,21 @@ uint8_t USB_ProcessHIDReport(const uint8_t* ReportData, uint16_t ReportSize, HID { case TAG_MAIN_INPUT: NewReportItem.ItemType = REPORT_ITEM_TYPE_In; - NewReportItem.BitOffset = BitOffsetIn; + NewReportItem.BitOffset = CurrReportIDInfo->BitsIn; - BitOffsetIn += CurrStateTable->Attributes.BitSize; + CurrReportIDInfo->BitsIn += CurrStateTable->Attributes.BitSize; break; case TAG_MAIN_OUTPUT: NewReportItem.ItemType = REPORT_ITEM_TYPE_Out; - NewReportItem.BitOffset = BitOffsetOut; + NewReportItem.BitOffset = CurrReportIDInfo->BitsOut; - BitOffsetOut += CurrStateTable->Attributes.BitSize; + CurrReportIDInfo->BitsOut += CurrStateTable->Attributes.BitSize; break; case TAG_MAIN_FEATURE: NewReportItem.ItemType = REPORT_ITEM_TYPE_Feature; - NewReportItem.BitOffset = BitOffsetFeature; + NewReportItem.BitOffset = CurrReportIDInfo->BitsFeature; - BitOffsetFeature += CurrStateTable->Attributes.BitSize; + CurrReportIDInfo->BitsFeature += CurrStateTable->Attributes.BitSize; break; } diff --git a/LUFA/Drivers/USB/Class/Host/HIDParser.h b/LUFA/Drivers/USB/Class/Host/HIDParser.h index 8d3fbf212d..d9adae34d1 100644 --- a/LUFA/Drivers/USB/Class/Host/HIDParser.h +++ b/LUFA/Drivers/USB/Class/Host/HIDParser.h @@ -107,10 +107,21 @@ * in the report item descriptor and stored in the user HID Report Info structure. A large value allows * for more report items to be stored, but consumes more memory. By default this is set to 20 items, * but this can be overridden by defining HID_MAX_REPORTITEMS to another value in the user project - * makefile, passing the define to the compiler using the -D compiler switch. + * makefile, and passing the define to the compiler using the -D compiler switch. */ #define HID_MAX_REPORTITEMS 20 #endif + + #if !defined(HID_MAX_REPORT_IDS) || defined(__DOXYGEN__) + /** Constant indicating the maximum number of unique report IDs that can be processed in the report item + * descriptor for the report size information array in the user HID Report Info structure. A large value + * allows for more report ID report sizes to be stored, but consumes more memory. By default this is set + * to 5 items, but this can be overridden by defining HID_MAX_REPORT_IDS to another value in the user project + * makefile, and passing the define to the compiler using the -D compiler switch. Note that IN, OUT and FEATURE + * items sharing the same report ID consume only one size item in the array. + */ + #define HID_MAX_REPORT_IDS 5 + #endif /* Public Interface - May be used in end-application: */ /* Enums: */ @@ -132,6 +143,7 @@ HID_PARSE_UnexpectedEndCollection = 4, /**< An END COLLECTION item found without matching COLLECTION item. */ HID_PARSE_InsufficientCollectionPaths = 5, /**< More than \ref HID_MAX_COLLECTIONS collections in the report. */ HID_PARSE_UsageStackOverflow = 6, /**< More than \ref HID_USAGE_STACK_DEPTH usages listed in a row. */ + HID_PARSE_InsufficientReportIDItems = 7, /**< More than \ref HID_MAX_REPORT_IDS report IDs in the device. */ }; /* Type Defines: */ @@ -191,6 +203,15 @@ uint32_t Value; /**< Current value of the report item. */ } HID_ReportItem_t; + + /** Type define for a report item size information structure */ + typedef struct + { + uint8_t ReportID; /** Report ID of the report within the HID interface */ + uint8_t BitsIn; /** Total number of IN data bits in the current report ID */ + uint8_t BitsOut; /** Total number of OUT data bits in the current report ID */ + uint8_t BitsFeature; /** Total number of FEATURE data bits in the current report ID */ + } HID_ReportSizeInfo_t; /** Type define for a complete processed HID report, including all report item data and collections. */ typedef struct @@ -204,9 +225,11 @@ HID_CollectionPath_t CollectionPaths[HID_MAX_COLLECTIONS]; /**< All collection items, referenced * by the report items. */ - bool UsingMultipleReports; /**< Indicates if the device has at least one REPORT ID - * element in its HID report descriptor. - */ + uint8_t TotalDeviceReports; /** Number of reports within the HID interface */ + HID_ReportSizeInfo_t ReportIDSizes[HID_MAX_REPORT_IDS]; /** Report sizes for each report in the interface */ + bool UsingReportIDs; /**< Indicates if the device has at least one REPORT ID + * element in its HID report descriptor. + */ } HID_ReportInfo_t; /* Function Prototypes: */ diff --git a/LUFA/ManPages/ChangeLog.txt b/LUFA/ManPages/ChangeLog.txt index 76e939067f..9bbfba113a 100644 --- a/LUFA/ManPages/ChangeLog.txt +++ b/LUFA/ManPages/ChangeLog.txt @@ -39,6 +39,7 @@ * - The Benito Programmer project now has its own unique VID/PID pair allocated from the Atmel donated LUFA VID/PID pool * - Add in new invalid event hook check targets to project makefiles to produce compilation errors when invalid event names * are used in a project + * - The HID Report Parser now gives information on the total length of each report within a HID interface * * Fixed: * - Fixed possible lockup in the CDC device class driver, when the host sends data that is a multiple of the diff --git a/LUFA/ManPages/CompileTimeTokens.txt b/LUFA/ManPages/CompileTimeTokens.txt index ee18d27c8e..fb051b8c89 100644 --- a/LUFA/ManPages/CompileTimeTokens.txt +++ b/LUFA/ManPages/CompileTimeTokens.txt @@ -51,6 +51,13 @@ * If a item has a multiple count (i.e. a REPORT COUNT of more than 1), each item in the report count is placed separately in the * processed HID report table. If not defined, this defaults to the value indicated in the HID.h file documentation. * + * HID_MAX_REPORT_IDS - ( \ref Group_HIDParser ) \n + * HID reports may contain several report IDs, to logically distinguish grouped device data from one another - for example, a combination + * keyboard and mouse might use report IDs to seperate the keyboard reports from the mouse reports. In order to determine the size of each + * report, and thus know how many bytes must be read or written, the size of each report (IN, OUT and FEATURE) must be calculated and + * stored. This token may be defined to a non-zero 8-bit value to set the maximum number of report IDs in a device which can be processed + * and their sizes calculated/stored into the resultant processed report structure. If not defined, this defaults to the value indicated in + * the HID.h file documentation. * * \section Sec_SummaryUSBTokens USB Driver Related Tokens * This section describes compile tokens which affect USB driver stack as a whole in the LUFA library.