Commit 524decde authored by Dean Camera's avatar Dean Camera
Browse files

Change HID report parser so that it can calculate and record the sizes (IN,...

Change HID report parser so that it can calculate and record the sizes (IN, OUT and FEATURE) of each report within the device, by report ID. This will be required in host mode, so that the host can determine how many bytes of data must be read in for each report.

Add to MouseHostWithParser and KeyboardHostWithParser demos to print out the report sizes when a valid device is connected.
parent 33192983
......@@ -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;
......
......@@ -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())
{
......
......@@ -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;
}
......
......@@ -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: */
......
......@@ -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
*
* <b>Fixed:</b>
* - Fixed possible lockup in the CDC device class driver, when the host sends data that is a multiple of the
......
......@@ -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.
*
* <b>HID_MAX_REPORT_IDS</b> - ( \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.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment