HID_RI_REPORT_COUNT(8, 0x01), HID_RI_REPORT_SIZE(8, 0x08), HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE), HID_RI_END_COLLECTION(0), HID_RI_END_COLLECTION(0), }; #endif #ifdef EXTRAKEY_ENABLE const USB_Descriptor_HIDReport_Datatype_t PROGMEM ExtrakeyReport[] = { HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */ HID_RI_USAGE(8, 0x80), /* System Control */ HID_RI_COLLECTION(8, 0x01), /* Application */ HID_RI_REPORT_ID(8, REPORT_ID_SYSTEM), HID_RI_LOGICAL_MINIMUM(16, 0x0081), HID_RI_LOGICAL_MAXIMUM(16, 0x00B7), HID_RI_USAGE_MINIMUM(16, 0x0081), /* System Power Down */ HID_RI_USAGE_MAXIMUM(16, 0x00B7), /* System Display LCD Autoscale */ HID_RI_REPORT_SIZE(8, 16), HID_RI_REPORT_COUNT(8, 1), HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE), HID_RI_END_COLLECTION(0), HID_RI_USAGE_PAGE(8, 0x0C), /* Consumer */ HID_RI_USAGE(8, 0x01), /* Consumer Control */ HID_RI_COLLECTION(8, 0x01), /* Application */ HID_RI_REPORT_ID(8, REPORT_ID_CONSUMER), HID_RI_LOGICAL_MINIMUM(16, 0x0001), HID_RI_LOGICAL_MAXIMUM(16, 0x029C),
uint8_t USB_ProcessHIDReport(const uint8_t* ReportData, uint16_t ReportSize, HID_ReportInfo_t* const ParserData) { 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 UsageList[HID_USAGE_STACK_DEPTH]; uint8_t UsageListSize = 0; HID_MinMax_t UsageMinMax = {0, 0}; memset(ParserData, 0x00, sizeof(HID_ReportInfo_t)); memset(CurrStateTable, 0x00, sizeof(HID_StateTable_t)); memset(CurrReportIDInfo, 0x00, sizeof(HID_ReportSizeInfo_t)); ParserData->TotalDeviceReports = 1; while (ReportSize) { uint8_t HIDReportItem = *ReportData; uint32_t ReportItemData = 0; ReportData++; ReportSize--; switch (HIDReportItem & HID_RI_DATA_SIZE_MASK) { case HID_RI_DATA_BITS_32: ReportItemData = le32_to_cpu(*((uint32_t*)ReportData)); ReportSize -= 4; ReportData += 4; break; case HID_RI_DATA_BITS_16: ReportItemData = le16_to_cpu(*((uint16_t*)ReportData)); ReportSize -= 2; ReportData += 2; break; case HID_RI_DATA_BITS_8: ReportItemData = *((uint8_t*)ReportData); ReportSize -= 1; ReportData += 1; break; } switch (HIDReportItem & (HID_RI_TYPE_MASK | HID_RI_TAG_MASK)) { case HID_RI_PUSH(0): if (CurrStateTable == &StateTable[HID_STATETABLE_STACK_DEPTH - 1]) return HID_PARSE_HIDStackOverflow; memcpy((CurrStateTable + 1), CurrStateTable, sizeof(HID_ReportItem_t)); CurrStateTable++; break; case HID_RI_POP(0): if (CurrStateTable == &StateTable[0]) return HID_PARSE_HIDStackUnderflow; CurrStateTable--; break; case HID_RI_USAGE_PAGE(0): if ((HIDReportItem & HID_RI_DATA_SIZE_MASK) == HID_RI_DATA_BITS_32) CurrStateTable->Attributes.Usage.Page = (ReportItemData >> 16); CurrStateTable->Attributes.Usage.Page = ReportItemData; break; case HID_RI_LOGICAL_MINIMUM(0): CurrStateTable->Attributes.Logical.Minimum = ReportItemData; break; case HID_RI_LOGICAL_MAXIMUM(0): CurrStateTable->Attributes.Logical.Maximum = ReportItemData; break; case HID_RI_PHYSICAL_MINIMUM(0): CurrStateTable->Attributes.Physical.Minimum = ReportItemData; break; case HID_RI_PHYSICAL_MAXIMUM(0): CurrStateTable->Attributes.Physical.Maximum = ReportItemData; break; case HID_RI_UNIT_EXPONENT(0): CurrStateTable->Attributes.Unit.Exponent = ReportItemData; break; case HID_RI_UNIT(0): CurrStateTable->Attributes.Unit.Type = ReportItemData; break; case HID_RI_REPORT_SIZE(0): CurrStateTable->Attributes.BitSize = ReportItemData; break; case HID_RI_REPORT_COUNT(0): CurrStateTable->ReportCount = ReportItemData; break; case HID_RI_REPORT_ID(0): CurrStateTable->ReportID = ReportItemData; 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++]; memset(CurrReportIDInfo, 0x00, sizeof(HID_ReportSizeInfo_t)); } } ParserData->UsingReportIDs = true; CurrReportIDInfo->ReportID = CurrStateTable->ReportID; break; case HID_RI_USAGE(0): if (UsageListSize == HID_USAGE_STACK_DEPTH) return HID_PARSE_UsageListOverflow; UsageList[UsageListSize++] = ReportItemData; break; case HID_RI_USAGE_MINIMUM(0): UsageMinMax.Minimum = ReportItemData; break; case HID_RI_USAGE_MAXIMUM(0): UsageMinMax.Maximum = ReportItemData; break; case HID_RI_COLLECTION(0): if (CurrCollectionPath == NULL) { CurrCollectionPath = &ParserData->CollectionPaths[0]; } else { HID_CollectionPath_t* ParentCollectionPath = CurrCollectionPath; CurrCollectionPath = &ParserData->CollectionPaths[1]; while (CurrCollectionPath->Parent != NULL) { if (CurrCollectionPath == &ParserData->CollectionPaths[HID_MAX_COLLECTIONS - 1]) return HID_PARSE_InsufficientCollectionPaths; CurrCollectionPath++; } CurrCollectionPath->Parent = ParentCollectionPath; } CurrCollectionPath->Type = ReportItemData; CurrCollectionPath->Usage.Page = CurrStateTable->Attributes.Usage.Page; if (UsageListSize) { CurrCollectionPath->Usage.Usage = UsageList[0]; for (uint8_t i = 0; i < UsageListSize; i++) UsageList[i] = UsageList[i + 1]; UsageListSize--; } else if (UsageMinMax.Minimum <= UsageMinMax.Maximum) { CurrCollectionPath->Usage.Usage = UsageMinMax.Minimum++; } break; case HID_RI_END_COLLECTION(0): if (CurrCollectionPath == NULL) return HID_PARSE_UnexpectedEndCollection; CurrCollectionPath = CurrCollectionPath->Parent; break; case HID_RI_INPUT(0): case HID_RI_OUTPUT(0): case HID_RI_FEATURE(0): for (uint8_t ReportItemNum = 0; ReportItemNum < CurrStateTable->ReportCount; ReportItemNum++) { HID_ReportItem_t NewReportItem; memcpy(&NewReportItem.Attributes, &CurrStateTable->Attributes, sizeof(HID_ReportItem_Attributes_t)); NewReportItem.ItemFlags = ReportItemData; NewReportItem.CollectionPath = CurrCollectionPath; NewReportItem.ReportID = CurrStateTable->ReportID; if (UsageListSize) { NewReportItem.Attributes.Usage.Usage = UsageList[0]; for (uint8_t i = 0; i < UsageListSize; i++) UsageList[i] = UsageList[i + 1]; UsageListSize--; } else if (UsageMinMax.Minimum <= UsageMinMax.Maximum) { NewReportItem.Attributes.Usage.Usage = UsageMinMax.Minimum++; } uint8_t ItemTypeTag = (HIDReportItem & (HID_RI_TYPE_MASK | HID_RI_TAG_MASK)); if (ItemTypeTag == HID_RI_INPUT(0)) NewReportItem.ItemType = HID_REPORT_ITEM_In; else if (ItemTypeTag == HID_RI_OUTPUT(0)) NewReportItem.ItemType = HID_REPORT_ITEM_Out; else NewReportItem.ItemType = HID_REPORT_ITEM_Feature; NewReportItem.BitOffset = CurrReportIDInfo->ReportSizeBits[NewReportItem.ItemType]; CurrReportIDInfo->ReportSizeBits[NewReportItem.ItemType] += CurrStateTable->Attributes.BitSize; ParserData->LargestReportSizeBits = MAX(ParserData->LargestReportSizeBits, CurrReportIDInfo->ReportSizeBits[NewReportItem.ItemType]); if (ParserData->TotalReportItems == HID_MAX_REPORTITEMS) return HID_PARSE_InsufficientReportItems; memcpy(&ParserData->ReportItems[ParserData->TotalReportItems], &NewReportItem, sizeof(HID_ReportItem_t)); if (!(ReportItemData & HID_IOF_CONSTANT) && CALLBACK_HIDParser_FilterHIDReportItem(&NewReportItem)) ParserData->TotalReportItems++; } break; } if ((HIDReportItem & HID_RI_TYPE_MASK) == HID_RI_TYPE_MAIN) { UsageMinMax.Minimum = 0; UsageMinMax.Maximum = 0; UsageListSize = 0; } } if (!(ParserData->TotalReportItems)) return HID_PARSE_NoUnfilteredReportItems; return HID_PARSE_Successful; }
/** HID class report descriptor. This is a special descriptor constructed with values from the * USBIF HID class specification to describe the reports and capabilities of the HID device. This * descriptor is parsed by the host and its contents used to determine what data (and in what encoding) * the device will send, and what it may be sent back from the host. Refer to the HID specification for * more details on HID report descriptors. * * This descriptor describes the multiple possible reports of the HID interface's report structure. */ const USB_Descriptor_HIDReport_Datatype_t PROGMEM HIDReport[] = { /* Mouse Report */ HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */ HID_RI_USAGE(8, 0x02), /* Mouse */ HID_RI_COLLECTION(8, 0x01), /* Application */ HID_RI_REPORT_ID(8, HID_REPORTID_MouseReport), HID_RI_USAGE(8, 0x01), /* Pointer */ HID_RI_COLLECTION(8, 0x00), /* Physical */ HID_RI_USAGE_PAGE(8, 0x09), /* Button */ HID_RI_USAGE_MINIMUM(8, 0x01), HID_RI_USAGE_MAXIMUM(8, 0x03), HID_RI_LOGICAL_MINIMUM(8, 0x00), HID_RI_LOGICAL_MAXIMUM(8, 0x01), HID_RI_REPORT_COUNT(8, 0x03), HID_RI_REPORT_SIZE(8, 0x01), HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), HID_RI_REPORT_COUNT(8, 0x01), HID_RI_REPORT_SIZE(8, 0x05), HID_RI_INPUT(8, HID_IOF_CONSTANT), HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */ HID_RI_USAGE(8, 0x30), /* Usage X */
#endif /******************************************************************************* * HID Report Descriptors ******************************************************************************/ #ifdef KEYBOARD_SHARED_EP const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = { #define SHARED_REPORT_STARTED #else const USB_Descriptor_HIDReport_Datatype_t PROGMEM KeyboardReport[] = { #endif HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */ HID_RI_USAGE(8, 0x06), /* Keyboard */ HID_RI_COLLECTION(8, 0x01), /* Application */ # ifdef KEYBOARD_SHARED_EP HID_RI_REPORT_ID(8, REPORT_ID_KEYBOARD), # endif HID_RI_USAGE_PAGE(8, 0x07), /* Key Codes */ HID_RI_USAGE_MINIMUM(8, 0xE0), /* Keyboard Left Control */ HID_RI_USAGE_MAXIMUM(8, 0xE7), /* Keyboard Right GUI */ HID_RI_LOGICAL_MINIMUM(8, 0x00), HID_RI_LOGICAL_MAXIMUM(8, 0x01), HID_RI_REPORT_COUNT(8, 0x08), HID_RI_REPORT_SIZE(8, 0x01), HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), HID_RI_REPORT_COUNT(8, 0x01), HID_RI_REPORT_SIZE(8, 0x08), HID_RI_INPUT(8, HID_IOF_CONSTANT), /* reserved */ HID_RI_USAGE_PAGE(8, 0x08), /* LEDs */
/** HID class report descriptor. This is a special descriptor constructed with values from the * USBIF HID class specification to describe the reports and capabilities of the HID device. This * descriptor is parsed by the host and its contents used to determine what data (and in what encoding) * the device will send, and what it may be sent back from the host. Refer to the HID specification for * more details on HID report descriptors. * * This descriptor describes the multiple possible reports of the HID interface's report structure. */ const USB_Descriptor_HIDReport_Datatype_t PROGMEM HIDReport[] = { /* Joystick Report */ HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */ HID_RI_USAGE(8, 0x04), /* Joystick */ HID_RI_COLLECTION(8, 0x01), /* Application */ HID_RI_REPORT_ID(8, HID_REPORTID_JoystickReport), HID_RI_USAGE(8, 0x01), /* Pointer */ HID_RI_COLLECTION(8, 0x00), /* Physical */ HID_RI_USAGE(8, 0x30), /* Usage X */ HID_RI_USAGE(8, 0x31), /* Usage Y */ HID_RI_USAGE(8, 0x32), /* Usage X */ //JW added - can add more as 34, 35 etc HID_RI_USAGE(8, 0x33), /* Usage Y */ HID_RI_LOGICAL_MINIMUM(8, -128), HID_RI_LOGICAL_MAXIMUM(8, 127), HID_RI_PHYSICAL_MINIMUM(8, -1), HID_RI_PHYSICAL_MAXIMUM(8, 1), //HID_RI_REPORT_COUNT(8, 0x02), //increase axis from 2 to 4 HID_RI_REPORT_COUNT(8, 0x04), HID_RI_REPORT_SIZE(8, 0x08), HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), HID_RI_END_COLLECTION(0),
* USBIF HID class specification to describe the reports and capabilities of the HID device. This * descriptor is parsed by the host and its contents used to determine what data (and in what encoding) * the device will send, and what it may be sent back from the host. Refer to the HID specification for * more details on HID report descriptors. * * This descriptor describes the multiple possible reports of the HID interface's report structure. */ //Keyboard and media report const USB_Descriptor_HIDReport_Datatype_t PROGMEM KeyboardReport[] = { /* Keyboard Report */ HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */ HID_RI_USAGE(8, 0x06), /* Keyboard */ HID_RI_COLLECTION(8, 0x01), /* Application */ HID_RI_REPORT_ID(8, KEYBOARD_REPORTID_KeyboardReport), HID_RI_USAGE_PAGE(8, 0x07), /* Key Codes */ HID_RI_USAGE_MINIMUM(8, 0xE0), /* Keyboard Left Control */ HID_RI_USAGE_MAXIMUM(8, 0xE7), /* Keyboard Right GUI */ HID_RI_LOGICAL_MINIMUM(8, 0x00), HID_RI_LOGICAL_MAXIMUM(8, 0x01), HID_RI_REPORT_SIZE(8, 0x01), HID_RI_REPORT_COUNT(8, 0x08), HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), HID_RI_REPORT_COUNT(8, 0x01), HID_RI_REPORT_SIZE(8, 0x08), HID_RI_INPUT(8, HID_IOF_CONSTANT), HID_RI_USAGE_PAGE(8, 0x08), /* LEDs */ HID_RI_USAGE_MINIMUM(8, 0x01), /* Num Lock */ HID_RI_USAGE_MAXIMUM(8, 0x05), /* Kana */ HID_RI_REPORT_COUNT(8, 0x05),