Change HID report parser so that it can calculate and record the sizes (IN, OUT and...
authorDean Camera <dean@fourwalledcubicle.com>
Wed, 9 Sep 2009 08:34:24 +0000 (08:34 +0000)
committerDean Camera <dean@fourwalledcubicle.com>
Wed, 9 Sep 2009 08:34:24 +0000 (08:34 +0000)
Add to MouseHostWithParser and KeyboardHostWithParser demos to print out the report sizes when a valid device is connected.

Demos/Host/LowLevel/KeyboardHostWithParser/KeyboardHostWithParser.c
Demos/Host/LowLevel/MouseHostWithParser/MouseHostWithParser.c
LUFA/Drivers/USB/Class/Host/HIDParser.c
LUFA/Drivers/USB/Class/Host/HIDParser.h
LUFA/ManPages/ChangeLog.txt
LUFA/ManPages/CompileTimeTokens.txt

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