From 74298f8ca11dc8d3b0359d1d4e124d6494c3eeac Mon Sep 17 00:00:00 2001 From: Nicolas Schodet Date: Fri, 10 Apr 2009 01:15:42 +0200 Subject: * digital/avr/modules/usb: - imported LUFA. --- .../lufa/LUFA/Drivers/USB/Class/ConfigDescriptor.c | 135 +++++++++ .../lufa/LUFA/Drivers/USB/Class/ConfigDescriptor.h | 258 ++++++++++++++++ .../usb/lufa/LUFA/Drivers/USB/Class/HIDParser.c | 326 +++++++++++++++++++++ .../usb/lufa/LUFA/Drivers/USB/Class/HIDParser.h | 252 ++++++++++++++++ .../lufa/LUFA/Drivers/USB/Class/HIDReportData.h | 128 ++++++++ 5 files changed, 1099 insertions(+) create mode 100644 digital/avr/modules/usb/lufa/LUFA/Drivers/USB/Class/ConfigDescriptor.c create mode 100644 digital/avr/modules/usb/lufa/LUFA/Drivers/USB/Class/ConfigDescriptor.h create mode 100644 digital/avr/modules/usb/lufa/LUFA/Drivers/USB/Class/HIDParser.c create mode 100644 digital/avr/modules/usb/lufa/LUFA/Drivers/USB/Class/HIDParser.h create mode 100644 digital/avr/modules/usb/lufa/LUFA/Drivers/USB/Class/HIDReportData.h (limited to 'digital/avr/modules/usb/lufa/LUFA/Drivers/USB/Class') diff --git a/digital/avr/modules/usb/lufa/LUFA/Drivers/USB/Class/ConfigDescriptor.c b/digital/avr/modules/usb/lufa/LUFA/Drivers/USB/Class/ConfigDescriptor.c new file mode 100644 index 00000000..5a40705c --- /dev/null +++ b/digital/avr/modules/usb/lufa/LUFA/Drivers/USB/Class/ConfigDescriptor.c @@ -0,0 +1,135 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, provided that the above copyright notice appear in all + copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#include "ConfigDescriptor.h" + +uint8_t USB_Host_GetDeviceConfigDescriptor(uint16_t* const ConfigSizePtr, void* BufferPtr) +{ + uint8_t ErrorCode; + + USB_HostRequest = (USB_Host_Request_Header_t) + { + bmRequestType: (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE), + bRequest: REQ_GetDescriptor, + wValue: (DTYPE_Configuration << 8), + wIndex: 0, + wLength: sizeof(USB_Descriptor_Configuration_Header_t), + }; + + if (BufferPtr == NULL) + { + uint8_t ConfigHeader[sizeof(USB_Descriptor_Configuration_Header_t)]; + + ErrorCode = USB_Host_SendControlRequest(ConfigHeader); + + #if defined(USE_NONSTANDARD_DESCRIPTOR_NAMES) + *ConfigSizePtr = DESCRIPTOR_CAST(ConfigHeader, USB_Descriptor_Configuration_Header_t).TotalConfigurationSize; + #else + *ConfigSizePtr = DESCRIPTOR_CAST(ConfigHeader, USB_Descriptor_Configuration_Header_t).wTotalLength; + #endif + } + else + { + USB_HostRequest.wLength = *ConfigSizePtr; + + ErrorCode = USB_Host_SendControlRequest(BufferPtr); + } + + return ErrorCode; +} + +void USB_Host_GetNextDescriptorOfType(uint16_t* const BytesRem, + uint8_t** const CurrConfigLoc, + const uint8_t Type) +{ + while (*BytesRem) + { + USB_Host_GetNextDescriptor(BytesRem, CurrConfigLoc); + + if (DESCRIPTOR_TYPE(*CurrConfigLoc) == Type) + return; + } +} + +void USB_Host_GetNextDescriptorOfTypeBefore(uint16_t* const BytesRem, + uint8_t** const CurrConfigLoc, + const uint8_t Type, + const uint8_t BeforeType) +{ + while (*BytesRem) + { + USB_Host_GetNextDescriptor(BytesRem, CurrConfigLoc); + + if (DESCRIPTOR_TYPE(*CurrConfigLoc) == Type) + { + return; + } + else if (DESCRIPTOR_TYPE(*CurrConfigLoc) == BeforeType) + { + *BytesRem = 0; + return; + } + } +} + +void USB_Host_GetNextDescriptorOfTypeAfter(uint16_t* const BytesRem, + uint8_t** const CurrConfigLoc, + const uint8_t Type, + const uint8_t AfterType) +{ + USB_Host_GetNextDescriptorOfType(BytesRem, CurrConfigLoc, AfterType); + + if (*BytesRem) + USB_Host_GetNextDescriptorOfType(BytesRem, CurrConfigLoc, Type); +} + +uint8_t USB_Host_GetNextDescriptorComp_P(uint16_t* BytesRem, uint8_t** CurrConfigLoc, + uint8_t (* const ComparatorRoutine)(void*)) +{ + uint8_t ErrorCode; + + while (*BytesRem) + { + uint8_t** PrevDescLoc = CurrConfigLoc; + uint16_t PrevBytesRem = *BytesRem; + + USB_Host_GetNextDescriptor(BytesRem, CurrConfigLoc); + + if ((ErrorCode = ComparatorRoutine(*CurrConfigLoc)) != Descriptor_Search_NotFound) + { + CurrConfigLoc = PrevDescLoc; + *BytesRem = PrevBytesRem; + + return ErrorCode; + } + } + + return Descriptor_Search_Comp_EndOfDescriptor; +} diff --git a/digital/avr/modules/usb/lufa/LUFA/Drivers/USB/Class/ConfigDescriptor.h b/digital/avr/modules/usb/lufa/LUFA/Drivers/USB/Class/ConfigDescriptor.h new file mode 100644 index 00000000..d1f8927f --- /dev/null +++ b/digital/avr/modules/usb/lufa/LUFA/Drivers/USB/Class/ConfigDescriptor.h @@ -0,0 +1,258 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, provided that the above copyright notice appear in all + copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * + * Configuration descriptor parser API. This section of the library gives a friendly API which can be used in + * host applications to easily parse an attached device's configuration descriptor so that endpoint, interface + * and other descriptor data can be extracted and used as needed. + */ + +#ifndef __CONFIGDESCRIPTOR_H__ +#define __CONFIGDESCRIPTOR_H__ + + /* Includes: */ + #include + + #include "../../../Common/Common.h" + #include "../LowLevel/HostChapter9.h" + #include "../HighLevel/StdDescriptors.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** Casts a pointer to a descriptor inside the configuration descriptor into a pointer to the given + * descriptor type. + * + * Usage Example: + * \code + * uint8_t* CurrDescriptor = &ConfigDescriptor[0]; // Pointing to the configuration header + * USB_Descriptor_Configuration_Header_t* ConfigHeaderPtr = DESCRIPTOR_PCAST(CurrDescriptor, + * USB_Descriptor_Configuration_Header_t); + * + * // Can now access elements of the configuration header struct using the -> indirection operator + * \endcode + */ + #define DESCRIPTOR_PCAST(DescriptorPtr, Type) ((Type*)DescriptorPtr) + + /** Casts a pointer to a descriptor inside the configuration descriptor into the given descriptor + * type (as an actual struct instance rather than a pointer to a struct). + * + * Usage Example: + * \code + * uint8_t* CurrDescriptor = &ConfigDescriptor[0]; // Pointing to the configuration header + * USB_Descriptor_Configuration_Header_t ConfigHeader = DESCRIPTOR_CAST(CurrDescriptor, + * USB_Descriptor_Configuration_Header_t); + * + * // Can now access elements of the configuration header struct using the . operator + * \endcode + */ + #define DESCRIPTOR_CAST(DescriptorPtr, Type) (*DESCRIPTOR_PCAST(DescriptorPtr, Type)) + + /** Returns the descriptor's type, expressed as the 8-bit type value in the header of the descriptor. + * This value's meaning depends on the descriptor's placement in the descriptor, but standard type + * values can be accessed in the DescriptorTypes_t enum located in USB/HighLevel/StdDescriptors.h. + */ + #if defined(USE_NONSTANDARD_DESCRIPTOR_NAMES) || defined(__DOXYGEN__) + #define DESCRIPTOR_TYPE(DescriptorPtr) DESCRIPTOR_CAST(DescriptorPtr, USB_Descriptor_Header_t).Type + #else + #define DESCRIPTOR_TYPE(DescriptorPtr) DESCRIPTOR_CAST(DescriptorPtr, USB_Descriptor_Header_t).bDescriptorType + #endif + + /** Returns the descriptor's size, expressed as the 8-bit value indicating the number of bytes. */ + #if defined(USE_NONSTANDARD_DESCRIPTOR_NAMES) || defined(__DOXYGEN__) + #define DESCRIPTOR_SIZE(DescriptorPtr) DESCRIPTOR_CAST(DescriptorPtr, USB_Descriptor_Header_t).Size + #else + #define DESCRIPTOR_SIZE(DescriptorPtr) DESCRIPTOR_CAST(DescriptorPtr, USB_Descriptor_Header_t).bLength + #endif + + /** Creates a prototype for or begins a descriptor comparitor routine. Descriptor comparitor routines are + * small search routines which are passed a pointer to the current sub descriptor in the configuration + * descriptor, and which analyse the sub descriptor to determine whether or not it matches the routine's + * search parameters. Comparitor routines provide a powerful way to scan through the config descriptor + * for certain descriptors matching unique criteria. + * + * Comparitor routines are passed in a single pointer named CurrentDescriptor, and should return a value + * of a member of the DSEARCH_Return_ErrorCodes_t enum. + */ + #define DESCRIPTOR_COMPARATOR(name) uint8_t DCOMP_##name (void* const CurrentDescriptor) + + /** Searches for the next descriptor in the given configuration descriptor using a premade comparator + * function. The routine updates the position and remaining configuration descriptor bytes values + * automatically. If a comparator routine fails a search, the descriptor pointer is retreated back + * so that the next descriptor search invocation will start from the descriptor which first caused the + * original search to fail. This behaviour allows for one comparator to be used immediately after another + * has failed, starting the second search from the descriptor which failed the first. + * + * \param DSize Pointer to an int storing the remaining bytes in the configuration descriptor + * \param DPos Pointer to the current position in the configuration descriptor + * \param DSearch Name of the comparitor search function to use on the configuration descriptor + * + * \return Value of one of the members of the DSEARCH_Comp_Return_ErrorCodes_t enum + * + * Usage Example: + * \code + * DESCRIPTOR_COMPARATOR(EndpointSearcher); // Comparator Prototype + * + * DESCRIPTOR_COMPARATOR(EndpointSearcher) + * { + * if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Endpoint) + * return Descriptor_Search_Found; + * else + * return Descriptor_Search_NotFound; + * } + * + * //... + * // After retrieving configuration descriptor: + * if (USB_Host_GetNextDescriptorComp(&BytesRemaining, &ConfigDescriptorData, EndpointSearcher) == + * Descriptor_Search_Comp_Found) + * { + * // Do something with the endpoint descriptor + * } + * \endcode + */ + #define USB_Host_GetNextDescriptorComp(DSize, DPos, DSearch) \ + USB_Host_GetNextDescriptorComp_P(DSize, DPos, DCOMP_##DSearch) + /* Enums: */ + /** Enum for return values of a descriptor comparator made with DESCRIPTOR_COMPARATOR. */ + enum DSEARCH_Return_ErrorCodes_t + { + Descriptor_Search_Found = 0, /**< Current descriptor matches comparator criteria. */ + Descriptor_Search_Fail = 1, /**< No further descriptor could possibly match criteria, fail the search. */ + Descriptor_Search_NotFound = 2, /**< Current descriptor does not match comparator criteria. */ + }; + + /** Enum for return values of USB_Host_GetNextDescriptorComp() */ + enum DSEARCH_Comp_Return_ErrorCodes_t + { + Descriptor_Search_Comp_Found = 0, /**< Configuration descriptor now points to decriptor which matches + * search criteria of the given comparator function. */ + Descriptor_Search_Comp_Fail = 1, /**< Comparator function returned Descriptor_Search_Fail. */ + Descriptor_Search_Comp_EndOfDescriptor = 2, /**< End of configuration descriptor reached before match found. */ + }; + + /* Function Prototypes: */ + /** Retrieves the configuration descriptor data or size from an attached device via a standard request. + * + * \param ConfigSizePtr Pointer to a uint16_t for either storing or retrieving the configuration + * descriptor size + * + * \param BufferPtr Pointer to the buffer for storing the configuration descriptor data. If this is + * NULL, the size of the configuration descriptor will be retrieved instead and + * placed in the variable pointed to by ConfigSizePtr. If this is non-NULL, the number + * of bytes indicated by ConfigSizePtr of the configuration descriptor will be loaded + * into the buffer + */ + uint8_t USB_Host_GetDeviceConfigDescriptor(uint16_t* const ConfigSizePtr, void* BufferPtr) + ATTR_NON_NULL_PTR_ARG(1); + + /* Inline Functions: */ + /** Skips over the current sub-descriptor inside the configuration descriptor, so that the pointer then + points to the next sub-descriptor. The bytes remaining value is automatically decremented. + * + * \param BytesRem Pointer to the number of bytes remaining of the configuration descriptor + * \param CurrConfigLoc Pointer to the current descriptor inside the configuration descriptor + */ + static inline void USB_Host_GetNextDescriptor(uint16_t* const BytesRem, + uint8_t** const CurrConfigLoc) + ATTR_NON_NULL_PTR_ARG(1, 2); + static inline void USB_Host_GetNextDescriptor(uint16_t* const BytesRem, + uint8_t** const CurrConfigLoc) + { + #if defined(USE_NONSTANDARD_DESCRIPTOR_NAMES) + uint16_t CurrDescriptorSize = DESCRIPTOR_CAST(*CurrConfigLoc, USB_Descriptor_Header_t).Size; + #else + uint16_t CurrDescriptorSize = DESCRIPTOR_CAST(*CurrConfigLoc, USB_Descriptor_Header_t).bLength; + #endif + + *CurrConfigLoc += CurrDescriptorSize; + *BytesRem -= CurrDescriptorSize; + } + + /** Skips to the next sub-descriptor inside the configuration descriptor of the specified type value. + * The bytes remaining value is automatically decremented. + * + * \param BytesRem Pointer to the number of bytes remaining of the configuration descriptor + * \param CurrConfigLoc Pointer to the current descriptor inside the configuration descriptor + * \param Type Descriptor type value to search for + */ + void USB_Host_GetNextDescriptorOfType(uint16_t* const BytesRem, + uint8_t** const CurrConfigLoc, + const uint8_t Type) + ATTR_NON_NULL_PTR_ARG(1, 2); + + /** Skips to the next sub-descriptor inside the configuration descriptor of the specified type value, + * which must come before a descriptor of the second given type value. If the BeforeType type + * descriptor is reached first, the number of bytes remaining to process is set to zero and the + * function exits. The bytes remaining value is automatically decremented. + * + * \param BytesRem Pointer to the number of bytes remaining of the configuration descriptor + * \param CurrConfigLoc Pointer to the current descriptor inside the configuration descriptor + * \param Type Descriptor type value to search for + * \param BeforeType Descriptor type value which must not be reached before the given Type descriptor + */ + void USB_Host_GetNextDescriptorOfTypeBefore(uint16_t* const BytesRem, + uint8_t** const CurrConfigLoc, + const uint8_t Type, + const uint8_t BeforeType) + ATTR_NON_NULL_PTR_ARG(1, 2); + + /** Skips to the next sub-descriptor inside the configuration descriptor of the specified type value, + * which must come after a descriptor of the second given type value. The bytes remaining value is + * automatically decremented. + * + * \param BytesRem Pointer to the number of bytes remaining of the configuration descriptor + * \param CurrConfigLoc Pointer to the current descriptor inside the configuration descriptor + * \param Type Descriptor type value to search for + * \param AfterType Descriptor type value which must be reached before the given Type descriptor + */ + void USB_Host_GetNextDescriptorOfTypeAfter(uint16_t* const BytesRem, + uint8_t** const CurrConfigLoc, + const uint8_t Type, + const uint8_t AfterType) + ATTR_NON_NULL_PTR_ARG(1, 2); + + /* Private Interface - For use in library only: */ + #if !defined(__DOXYGEN__) + /* Function Prototypes: */ + uint8_t USB_Host_GetNextDescriptorComp_P(uint16_t* BytesRem, uint8_t** CurrConfigLoc, + uint8_t (* const ComparatorRoutine)(void* const)); + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif diff --git a/digital/avr/modules/usb/lufa/LUFA/Drivers/USB/Class/HIDParser.c b/digital/avr/modules/usb/lufa/LUFA/Drivers/USB/Class/HIDParser.c new file mode 100644 index 00000000..35b280b5 --- /dev/null +++ b/digital/avr/modules/usb/lufa/LUFA/Drivers/USB/Class/HIDParser.c @@ -0,0 +1,326 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, provided that the above copyright notice appear in all + copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#include "HIDParser.h" + +uint8_t 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]; + uint16_t UsageStack[HID_USAGE_STACK_DEPTH]; + uint8_t UsageStackSize = 0; + uint16_t BitOffsetIn = 0; + uint16_t BitOffsetOut = 0; +#if defined(HID_ENABLE_FEATURE_PROCESSING) + uint16_t BitOffsetFeature = 0; +#endif + HID_CollectionPath_t* CurrCollectionPath = NULL; + + memset((void*)ParserData, 0x00, sizeof(HID_ReportInfo_t)); + memset((void*)StateTable, 0x00, sizeof(StateTable)); + + while (ReportSize) + { + uint32_t ReportItemData = 0; + + switch (*ReportData & DATA_SIZE_MASK) + { + case DATA_SIZE_4: + ReportItemData = *((uint32_t*)(ReportData + 1)); + break; + case DATA_SIZE_2: + ReportItemData = *((uint16_t*)(ReportData + 1)); + break; + case DATA_SIZE_1: + ReportItemData = *((uint8_t*)(ReportData + 1)); + break; + } + + switch (*ReportData & (TYPE_MASK | TAG_MASK)) + { + case (TYPE_GLOBAL | TAG_GLOBAL_PUSH): + if (CurrStateTable == &StateTable[HID_STATETABLE_STACK_DEPTH]) + return HID_PARSE_HIDStackOverflow; + + memcpy((CurrStateTable - 1), + CurrStateTable, + sizeof(HID_ReportItem_t)); + + CurrStateTable++; + break; + case (TYPE_GLOBAL | TAG_GLOBAL_POP): + if (CurrStateTable == &StateTable[0]) + return HID_PARSE_HIDStackUnderflow; + + CurrStateTable--; + break; + case (TYPE_GLOBAL | TAG_GLOBAL_USAGEPAGE): + CurrStateTable->Attributes.Usage.Page = ReportItemData; + break; + case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMIN): + CurrStateTable->Attributes.Logical.Minimum = ReportItemData; + break; + case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMAX): + CurrStateTable->Attributes.Logical.Maximum = ReportItemData; + break; + case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMIN): + CurrStateTable->Attributes.Physical.Minimum = ReportItemData; + break; + case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMAX): + CurrStateTable->Attributes.Physical.Maximum = ReportItemData; + break; + case (TYPE_GLOBAL | TAG_GLOBAL_UNITEXP): + CurrStateTable->Attributes.Unit.Exponent = ReportItemData; + break; + case (TYPE_GLOBAL | TAG_GLOBAL_UNIT): + CurrStateTable->Attributes.Unit.Type = ReportItemData; + break; + case (TYPE_GLOBAL | TAG_GLOBAL_REPORTSIZE): + CurrStateTable->Attributes.BitSize = ReportItemData; + break; + case (TYPE_GLOBAL | TAG_GLOBAL_REPORTCOUNT): + CurrStateTable->ReportCount = ReportItemData; + break; + case (TYPE_GLOBAL | TAG_GLOBAL_REPORTID): + CurrStateTable->ReportID = ReportItemData; + break; + case (TYPE_LOCAL | TAG_LOCAL_USAGE): + if (UsageStackSize == HID_USAGE_STACK_DEPTH) + return HID_PARSE_UsageStackOverflow; + + UsageStack[UsageStackSize++] = ReportItemData; + break; + case (TYPE_LOCAL | TAG_LOCAL_USAGEMIN): + CurrStateTable->Attributes.Usage.MinMax.Minimum = ReportItemData; + break; + case (TYPE_LOCAL | TAG_LOCAL_USAGEMAX): + CurrStateTable->Attributes.Usage.MinMax.Maximum = ReportItemData; + break; + case (TYPE_MAIN | TAG_MAIN_COLLECTION): + 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]) + return HID_PARSE_InsufficientCollectionPaths; + + CurrCollectionPath++; + } + + CurrCollectionPath->Parent = ParentCollectionPath; + } + + CurrCollectionPath->Type = ReportItemData; + CurrCollectionPath->Usage.Page = CurrStateTable->Attributes.Usage.Page; + + if (UsageStackSize) + { + CurrCollectionPath->Usage.Usage = UsageStack[0]; + + for (uint8_t i = 0; i < UsageStackSize; i++) + UsageStack[i] = UsageStack[i + 1]; + + UsageStackSize--; + } + else + { + CurrCollectionPath->Usage.Usage = 0; + } + + break; + case (TYPE_MAIN | TAG_MAIN_ENDCOLLECTION): + if (CurrCollectionPath == NULL) + return HID_PARSE_UnexpectedEndCollection; + + CurrCollectionPath = CurrCollectionPath->Parent; + + break; + case (TYPE_MAIN | TAG_MAIN_INPUT): + case (TYPE_MAIN | TAG_MAIN_OUTPUT): +#if defined(HID_ENABLE_FEATURE_PROCESSING) + case (TYPE_MAIN | TAG_MAIN_FEATURE): +#endif + for (uint8_t ReportItemNum = 0; ReportItemNum < CurrStateTable->ReportCount; ReportItemNum++) + { + HID_ReportItem_t* CurrReportItem = &ParserData->ReportItems[ParserData->TotalReportItems]; + + if (ParserData->TotalReportItems == HID_MAX_REPORTITEMS) + return HID_PARSE_InsufficientReportItems; + + memcpy(&CurrReportItem->Attributes, + &CurrStateTable->Attributes, + sizeof(HID_ReportItem_Attributes_t)); + + CurrReportItem->ItemFlags = ReportItemData; + CurrReportItem->CollectionPath = CurrCollectionPath; + CurrReportItem->ReportID = CurrStateTable->ReportID; + + if (UsageStackSize) + { + CurrReportItem->Attributes.Usage.Usage = UsageStack[0]; + + for (uint8_t i = 0; i < UsageStackSize; i++) + UsageStack[i] = UsageStack[i + 1]; + + UsageStackSize--; + } + else + { + CurrReportItem->Attributes.Usage.Usage = 0; + } + + switch (*ReportData & TAG_MASK) + { + case TAG_MAIN_INPUT: + CurrReportItem->ItemType = REPORT_ITEM_TYPE_In; + CurrReportItem->BitOffset = BitOffsetIn; + + BitOffsetIn += CurrStateTable->Attributes.BitSize; + + break; + case TAG_MAIN_OUTPUT: + CurrReportItem->ItemType = REPORT_ITEM_TYPE_Out; + CurrReportItem->BitOffset = BitOffsetOut; + + BitOffsetOut += CurrStateTable->Attributes.BitSize; + + break; +#if defined(HID_ENABLE_FEATURE_PROCESSING) + case TAG_MAIN_FEATURE: + CurrReportItem->ItemType = REPORT_ITEM_TYPE_Feature; + CurrReportItem->BitOffset = BitOffsetFeature; + + BitOffsetFeature += CurrStateTable->Attributes.BitSize; + + break; +#endif + } + +#if !defined(HID_INCLUDE_CONSTANT_DATA_ITEMS) + if (!(ReportItemData & IOF_CONSTANT)) + ParserData->TotalReportItems++; +#else + ParserData->TotalReportItems++; +#endif + } + + UsageStackSize = 0; + + break; + } + + if ((*ReportData & TYPE_MASK) == TYPE_MAIN) + { + CurrStateTable->Attributes.Usage.MinMax.Minimum = 0; + CurrStateTable->Attributes.Usage.MinMax.Maximum = 0; + UsageStackSize = 0; + } + + switch (*ReportData & DATA_SIZE_MASK) + { + case DATA_SIZE_4: + ReportSize -= 5; + ReportData += 5; + break; + case DATA_SIZE_2: + ReportSize -= 3; + ReportData += 3; + break; + case DATA_SIZE_1: + ReportSize -= 2; + ReportData += 2; + break; + case DATA_SIZE_0: + ReportSize -= 1; + ReportData += 1; + break; + } + } + + return HID_PARSE_Successful; +} + +bool GetReportItemInfo(const uint8_t* ReportData, HID_ReportItem_t* const ReportItem) +{ + uint16_t DataBitsRem = ReportItem->Attributes.BitSize; + uint16_t CurrentBit = ReportItem->BitOffset; + uint32_t BitMask = (1 << 0); + + ReportItem->Value = 0; + + if (ReportItem->ReportID) + { + if (ReportItem->ReportID != ReportData[0]) + return false; + + ReportData++; + } + + while (DataBitsRem--) + { + if (ReportData[CurrentBit / 8] & (1 << (CurrentBit % 8))) + ReportItem->Value |= BitMask; + + CurrentBit++; + BitMask <<= 1; + } + + return true; +} + +void SetReportItemInfo(uint8_t* ReportData, const HID_ReportItem_t* ReportItem) +{ + uint16_t DataBitsRem = ReportItem->Attributes.BitSize; + uint16_t CurrentBit = ReportItem->BitOffset; + uint32_t BitMask = (1 << 0); + + if (ReportItem->ReportID) + { + ReportData[0] = ReportItem->ReportID; + ReportData++; + } + + while (DataBitsRem--) + { + if (ReportItem->Value & (1 << (CurrentBit % 8))) + ReportData[CurrentBit / 8] |= BitMask; + + CurrentBit++; + BitMask <<= 1; + } +} diff --git a/digital/avr/modules/usb/lufa/LUFA/Drivers/USB/Class/HIDParser.h b/digital/avr/modules/usb/lufa/LUFA/Drivers/USB/Class/HIDParser.h new file mode 100644 index 00000000..314d0807 --- /dev/null +++ b/digital/avr/modules/usb/lufa/LUFA/Drivers/USB/Class/HIDParser.h @@ -0,0 +1,252 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, provided that the above copyright notice appear in all + copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * + * USB Human Interface Device (HID) Class report descriptor processing routines. This file allows for the easy + * parsing of the complex HID report descriptor, which describes the data that the device transmits to the host. + * + * The processed report is presented back to the user application as a flat structure containing each report + * item's IN, OUT and FEATURE (if desired) items along with each item's attributes. + * + * This library portion also allows for easy setting and retrieval of data from a HID report, including devices + * with multiple reports on the one HID interface. + * + * By default, FEATURE reports and IN/OUT reports with constant data are ignored in the HID report when processed + * to save on memory. This can be overridden by defining the HID_ENABLE_FEATURE_PROCESSING or + * HID_INCLUDE_CONSTANT_DATA_ITEMS tokens in the user project makefile, passing them to the compiler via the -D + * switch. + */ + +#ifndef __HIDPARSER_H__ +#define __HIDPARSER_H__ + + /* Includes: */ + #include + #include + + #include "HIDReportData.h" + + #include "../../../Common/Common.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor checks and defines: */ + #if !defined(HID_STATETABLE_STACK_DEPTH) || defined(__DOXYGEN__) + /** Constant indicating the maximum stack depth of the state table. A larger state table + * allows for more PUSH/POP report items to be nested, but consumes more memory. By default + * this is set to 3 levels (allowing for two PUSHes to be nested) but this can be overridden by + * defining HID_STATETABLE_STACK_DEPTH to another value in the user project makefile, passing the + * define to the compiler using the -D compiler switch. + */ + #define HID_STATETABLE_STACK_DEPTH 3 + #endif + + #if !defined(HID_USAGE_STACK_DEPTH) || defined(__DOXYGEN__) + /** Constant indicating the maximum stack depth of the usage table. A larger usage table + * allows for more USAGE items to be indicated sequentially for REPORT COUNT entries of more than + * one, but requires more stack space. By default this is set to 8 levels (allowing for a report + * item with a count of 8) but this can be overridden by defining HID_USAGE_STACK_DEPTH to another + * value in the user project makefile, passing the define to the compiler using the -D compiler + * switch. + */ + #define HID_USAGE_STACK_DEPTH 8 + #endif + + #if !defined(HID_MAX_COLLECTIONS) || defined(__DOXYGEN__) + /** Constant indicating the maximum number of COLLECTION items (nested or unnested) that can be + * processed in the report item descriptor. A large value allows for more COLLECTION items to be + * processed, but consumes more memory. By default this is set to 5 collections, but this can be + * overridden by defining HID_MAX_COLLECTIONS to another value in the user project makefile, passing + * the define to the compiler using the -D compiler switch. + */ + #define HID_MAX_COLLECTIONS 5 + #endif + + #if !defined(HID_MAX_REPORTITEMS) || defined(__DOXYGEN__) + /** Constant indicating the maximum number of report items (IN, OUT or FEATURE if enabled) that can be + * processed in the report item descriptor. A large value allows for more report items to be + * processed, but consumes more memory. By default this is set to 30 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. + */ + #define HID_MAX_REPORTITEMS 30 + #endif + + /* Public Interface - May be used in end-application: */ + /* Enums: */ + /** Enum for indicating what type of report item an entry in a HID_ReportInfo_t ReportItem array is */ + enum HID_ReportItemTypes_t + { + REPORT_ITEM_TYPE_In = 0, /**< Indicates that the item is an IN report type. */ + REPORT_ITEM_TYPE_Out = 1, /**< Indicates that the item is an OUT report type. */ + REPORT_ITEM_TYPE_Feature = 2, /**< Indicates that the item is a FEATURE report type. */ + }; + + /** Enum for the possible error codes in the return value of the ProcessHIDReport() function */ + enum HID_Parse_ErrorCodes_t + { + HID_PARSE_Successful = 0, /**< Successful parse of the HID report descriptor, no error. */ + HID_PARSE_HIDStackOverflow = 1, /**< More than HID_STATETABLE_STACK_DEPTH nested PUSHes in the report. */ + HID_PARSE_HIDStackUnderflow = 2, /**< A POP was found when the state table stack was empty. */ + HID_PARSE_InsufficientReportItems = 3, /**< More than HID_MAX_REPORTITEMS report items in the report. */ + HID_PARSE_UnexpectedEndCollection = 4, /**< END COLLECTION found without matching COLLECTION item. */ + HID_PARSE_InsufficientCollectionPaths = 5, /**< More than HID_MAX_COLLECTIONS collections in the report. */ + HID_PARSE_UsageStackOverflow = 6, /**< More than HID_USAGE_STACK_DEPTH usages listed in a row. */ + }; + + /* Type Defines: */ + /** Type define for an attribute with both minimum and maximum values (e.g. Logical Min/Max). */ + typedef struct + { + uint32_t Minimum; /**< Minimum value for the attribute. */ + uint32_t Maximum; /**< Maximum value for the attribute. */ + } HID_MinMax_t; + + /** Type define for the Unit attributes of a report item. */ + typedef struct + { + uint32_t Type; /**< Unit type (refer to HID specifications for details). */ + uint8_t Exponent; /**< Unit exponent (refer to HID specifications for details). */ + } HID_Unit_t; + + /** Type define for the Usage attributes of a report item. */ + typedef struct + { + uint16_t Page; /**< Usage page of the report item. */ + uint16_t Usage; /**< Usage of the report item. */ + HID_MinMax_t MinMax; /**< Usage minimum and maximum of the report item. */ + } HID_Usage_t; + + /** Type define for a COLLECTION object. Contains the collection attributes and a reference to the + * parent collection if any. + */ + typedef struct CollectionPath + { + uint8_t Type; /**< Collection type (for example "Generic Desktop"). */ + HID_Usage_t Usage; /**< Collection usage. */ + struct CollectionPath* Parent; /**< Reference to parent collection, or NULL if root collection. */ + } HID_CollectionPath_t; + + /** Type define for all the data attributes of a report item, except flags. */ + typedef struct + { + uint8_t BitSize; /**< Size in bits of the report item's data. */ + + HID_Usage_t Usage; /**< Usage of the report item. */ + HID_Unit_t Unit; /**< Unit type and exponent of the report item. */ + HID_MinMax_t Logical; /**< Logical minimum and maximum of the report item. */ + HID_MinMax_t Physical; /**< Physical minimum and maximum of the report item. */ + } HID_ReportItem_Attributes_t; + + /** Type define for a report item (IN, OUT or FEATURE) attributes and other details. */ + typedef struct + { + uint16_t BitOffset; /**< Bit offset in the IN, OUT or FEATURE report of the item. */ + uint8_t ItemType; /**< Report item type, a value in HID_Types_t. */ + uint16_t ItemFlags; /**< Item data flags, such as constant/variable, etc. */ + uint8_t ReportID; /**< Report ID this item belongs to, or 0x00 if device has only one report */ + HID_CollectionPath_t* CollectionPath; /**< Collection path of the item. */ + + HID_ReportItem_Attributes_t Attributes; /**< Report item attributes. */ + + uint32_t Value; /**< Current value of the report item. */ + } HID_ReportItem_t; + + /** Type define for a complete processed HID report, including all report item data and collections. */ + typedef struct + { + uint8_t TotalReportItems; /**< Total number of report items stored in the + * ReportItems array. */ + + HID_ReportItem_t ReportItems[HID_MAX_REPORTITEMS]; /**< Report items array, including + * all IN, OUT and FEATURE items. */ + + HID_CollectionPath_t CollectionPaths[HID_MAX_COLLECTIONS]; /**< All collection items, referenced + * by the report items. */ + } HID_ReportInfo_t; + + /* Function Prototypes: */ + /** Function to process a given HID report returned from an attached device, and store it into a given + * HID_ReportInfo_t structure. + * + * \param ReportData Buffer containing the device's HID report table + * \param ReportSize Size in bytes of the HID report table + * \param ParserData Pointer to a HID_ReportInfo_t instance for the parser output + * + * \return A value in the HID_Parse_ErrorCodes_t enum + */ + uint8_t ProcessHIDReport(const uint8_t* ReportData, uint16_t ReportSize, HID_ReportInfo_t* const ParserData) + ATTR_NON_NULL_PTR_ARG(1, 3); + + /** Extracts the given report item's value out of the given HID report and places it into the Value + * member of the report item's HID_ReportItem_t structure. + * + * \param ReportData Buffer containing an IN or FEATURE report from an attached device + * \param ReportItem Pointer to the report item of interest in a HID_ReportInfo_t ReportItem array + * + * \returns Boolean true if the item to retrieve was located in the given report, false otherwise + */ + bool GetReportItemInfo(const uint8_t* ReportData, HID_ReportItem_t* const ReportItem) + ATTR_NON_NULL_PTR_ARG(1, 2); + + /** Retreives the given report item's value out of the Value member of the report item's + * HID_ReportItem_t structure and places it into the correct position in the HID report + * buffer. The report buffer is assumed to have the appropriate bits cleared before calling + * this function (i.e., the buffer should be explicitly cleared before report values are added). + * + * If the device has multiple HID reports, the report ID is set to the report ID of the given item. + * + * \param ReportData Buffer holding the current OUT report data + * \param ReportItem Pointer to the report item of interest in a HID_ReportInfo_t ReportItem array + */ + void SetReportItemInfo(uint8_t* ReportData, const HID_ReportItem_t* ReportItem) + ATTR_NON_NULL_PTR_ARG(1, 2); + + /* Private Interface - For use in library only: */ + #if !defined(__DOXYGEN__) + /* Type Defines: */ + typedef struct + { + HID_ReportItem_Attributes_t Attributes; + uint8_t ReportCount; + uint8_t ReportID; + } HID_StateTable_t; + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif diff --git a/digital/avr/modules/usb/lufa/LUFA/Drivers/USB/Class/HIDReportData.h b/digital/avr/modules/usb/lufa/LUFA/Drivers/USB/Class/HIDReportData.h new file mode 100644 index 00000000..1bb8676d --- /dev/null +++ b/digital/avr/modules/usb/lufa/LUFA/Drivers/USB/Class/HIDReportData.h @@ -0,0 +1,128 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, provided that the above copyright notice appear in all + copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * + * Constants for HID report item attributes. Refer to the HID specification for details on each + * flag's meaning when applied to an IN, OUT or FEATURE item. + */ + +#ifndef __HIDREPORTDATA_H__ +#define __HIDREPORTDATA_H__ + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** HID_ReportItem_t.ItemFlags flag for constant data. */ + #define IOF_CONSTANT (1 << 0) + + /** HID_ReportItem_t.ItemFlags flag for data. */ + #define IOF_DATA (0 << 0) + + /** HID_ReportItem_t.ItemFlags flag for variable data. */ + #define IOF_VARIABLE (1 << 1) + + /** HID_ReportItem_t.ItemFlags flag for array data. */ + #define IOF_ARRAY (0 << 1) + + /** HID_ReportItem_t.ItemFlags flag for relative data. */ + #define IOF_RELATIVE (1 << 2) + + /** HID_ReportItem_t.ItemFlags flag for absolute data. */ + #define IOF_ABSOLUTE (0 << 2) + + /** HID_ReportItem_t.ItemFlags flag for wrapped value data. */ + #define IOF_WRAP (1 << 3) + + /** HID_ReportItem_t.ItemFlags flag for non-wrapped value data. */ + #define IOF_NOWRAP (0 << 3) + + /** HID_ReportItem_t.ItemFlags flag for non linear data. */ + #define IOF_NONLINEAR (1 << 4) + + /** HID_ReportItem_t.ItemFlags flag for linear data. */ + #define IOF_LINEAR (0 << 4) + + /** HID_ReportItem_t.ItemFlags flag for no preferred state. */ + #define IOF_NOPREFERRED (1 << 5) + + /** HID_ReportItem_t.ItemFlags flag for preferred state items. */ + #define IOF_PREFERREDSTATE (0 << 5) + + /** HID_ReportItem_t.ItemFlags flag for null state items. */ + #define IOF_NULLSTATE (1 << 6) + + /** HID_ReportItem_t.ItemFlags flag for no null position data. */ + #define IOF_NONULLPOSITION (0 << 6) + + /** HID_ReportItem_t.ItemFlags flag for buffered bytes. */ + #define IOF_BUFFEREDBYTES (1 << 8) + + /** HID_ReportItem_t.ItemFlags flag for bitfield data. */ + #define IOF_BITFIELD (0 << 8) + + /* Private Interface - For use in library only: */ + #if !defined(__DOXYGEN__) + /* Macros: */ + #define DATA_SIZE_MASK 0b00000011 + #define TYPE_MASK 0b00001100 + #define TAG_MASK 0b11110000 + + #define DATA_SIZE_0 0b00000000 + #define DATA_SIZE_1 0b00000001 + #define DATA_SIZE_2 0b00000010 + #define DATA_SIZE_4 0b00000011 + + #define TYPE_MAIN 0b00000000 + #define TYPE_GLOBAL 0b00000100 + #define TYPE_LOCAL 0b00001000 + + #define TAG_MAIN_INPUT 0b10000000 + #define TAG_MAIN_OUTPUT 0b10010000 + #define TAG_MAIN_COLLECTION 0b10100000 + #define TAG_MAIN_FEATURE 0b10110000 + #define TAG_MAIN_ENDCOLLECTION 0b11000000 + #define TAG_GLOBAL_USAGEPAGE 0b00000000 + #define TAG_GLOBAL_LOGICALMIN 0b00010000 + #define TAG_GLOBAL_LOGICALMAX 0b00100000 + #define TAG_GLOBAL_PHYSMIN 0b00110000 + #define TAG_GLOBAL_PHYSMAX 0b01000000 + #define TAG_GLOBAL_UNITEXP 0b01010000 + #define TAG_GLOBAL_UNIT 0b01100000 + #define TAG_GLOBAL_REPORTSIZE 0b01110000 + #define TAG_GLOBAL_REPORTID 0b10000000 + #define TAG_GLOBAL_REPORTCOUNT 0b10010000 + #define TAG_GLOBAL_PUSH 0b10100000 + #define TAG_GLOBAL_POP 0b10110000 + #define TAG_LOCAL_USAGE 0b00000000 + #define TAG_LOCAL_USAGEMIN 0b00010000 + #define TAG_LOCAL_USAGEMAX 0b00100000 + #endif + +#endif -- cgit v1.2.3