diff options
Diffstat (limited to 'LUFA/Drivers/USB')
31 files changed, 7759 insertions, 0 deletions
diff --git a/LUFA/Drivers/USB/Class/ConfigDescriptor.c b/LUFA/Drivers/USB/Class/ConfigDescriptor.c new file mode 100644 index 000000000..d79106916 --- /dev/null +++ b/LUFA/Drivers/USB/Class/ConfigDescriptor.c @@ -0,0 +1,138 @@ +/*
+ 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)
+ {
+ if (ErrorCode == Descriptor_Search_Fail)
+ {
+ *CurrConfigLoc = PrevDescLoc;
+ *BytesRem = PrevBytesRem;
+ }
+
+ return ErrorCode;
+ }
+ }
+
+ return Descriptor_Search_Comp_EndOfDescriptor;
+}
diff --git a/LUFA/Drivers/USB/Class/ConfigDescriptor.h b/LUFA/Drivers/USB/Class/ConfigDescriptor.h new file mode 100644 index 000000000..d1f8927f8 --- /dev/null +++ b/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 <avr/io.h>
+
+ #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/LUFA/Drivers/USB/Class/HIDParser.c b/LUFA/Drivers/USB/Class/HIDParser.c new file mode 100644 index 000000000..35b280b5c --- /dev/null +++ b/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/LUFA/Drivers/USB/Class/HIDParser.h b/LUFA/Drivers/USB/Class/HIDParser.h new file mode 100644 index 000000000..314d08072 --- /dev/null +++ b/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 <string.h>
+ #include <stdbool.h>
+
+ #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/LUFA/Drivers/USB/Class/HIDReportData.h b/LUFA/Drivers/USB/Class/HIDReportData.h new file mode 100644 index 000000000..1bb8676d7 --- /dev/null +++ b/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
diff --git a/LUFA/Drivers/USB/HighLevel/Events.c b/LUFA/Drivers/USB/HighLevel/Events.c new file mode 100644 index 000000000..dbc428aae --- /dev/null +++ b/LUFA/Drivers/USB/HighLevel/Events.c @@ -0,0 +1,39 @@ +/*
+ 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 "../LowLevel/USBMode.h"
+
+#define INCLUDE_FROM_EVENTS_C
+#include "Events.h"
+
+void USB_Event_Stub(void)
+{
+
+}
diff --git a/LUFA/Drivers/USB/HighLevel/Events.h b/LUFA/Drivers/USB/HighLevel/Events.h new file mode 100644 index 000000000..eeb0ed37a --- /dev/null +++ b/LUFA/Drivers/USB/HighLevel/Events.h @@ -0,0 +1,440 @@ +/*
+ 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.
+*/
+
+/** Library events module. This module contains macros and functions relating to the management of library
+ * events, which are small pieces of code similar to ISRs which are run when a given condition is met. Each
+ * event can be fired from multiple places in the user or library code, which may or may not be inside an ISR,
+ * thus each handler should be written to be as small and fast as possible to prevent possible problems.
+ *
+ * Events can be hooked by the user application using the EVENT_HANDLER() and HANDLES_EVENT() macros. If an
+ * event with no associated handler is fired within the library, it by default fires an internal empty stub
+ * function. This is achieved through the use of the GCC compiler's "alias" attribute.
+ *
+ * Each event must only have one associated event handler, but can be raised by multiple sources.
+ */
+
+#ifndef __USBEVENTS_H__
+#define __USBEVENTS_H__
+
+ /* Includes: */
+ #include <avr/io.h>
+
+ #include "../../../Common/Common.h"
+ #include "../LowLevel/USBMode.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Raises a given event name, with the specified parameters. For events with no parameters the
+ * only argument to the macro is the event name, events with parameters list the parameter values
+ * after the name as a comma seperated list.
+ *
+ * When a given event is fired, its corresponding event handler code is executed.
+ *
+ * Usage Examples:
+ * \code
+ * // Raise the USB_VBUSChange event, which takes no parameters
+ * RAISE_EVENT(USB_VBUSChange);
+ *
+ * // Raise the USB_UnhandledControlPacket event which takes two parameters
+ * RAISE_EVENT(USB_UnhandledControlPacket, 0, 1);
+ * \endcode
+ *
+ * \see RAISES_EVENT()
+ */
+ #define RAISE_EVENT(e, ...) Event_ ## e (__VA_ARGS__)
+
+ /** Indicates that a given module can raise a given event. This is the equivelent of putting the
+ * event function's prototype into the module, but in a cleaner way. Each event which may be
+ * fired via the RAISE_EVENT macro in the module should have an accompanying RAISES_EVENT
+ * prototype in the module's header file.
+ *
+ * Usage Examples:
+ * \code
+ * // Module can raise the USB_VBUSChange event
+ * RAISES_EVENT(USB_VBUSChange);
+ *
+ * // ...
+ * // Inside a block of code in a function of the module, raise the USB_VBUSChange event
+ * RAISE_EVENT(USB_VBUSChange);
+ * \endcode
+ *
+ * \see RAISE_EVENT()
+ */
+ #define RAISES_EVENT(e) HANDLES_EVENT(e)
+
+ /** Defines an event handler for the given event. Event handlers should be short in length, as they
+ * may be raised from inside an ISR. The user application can react to each event as it sees fit,
+ * such as logging the event, indicating the change to the user or performing some other action.
+ *
+ * Only one event handler may be defined in any user project for each individual event. Events may
+ * or may not have parameters - for each event, refer to its documentation elsewhere in this module
+ * to determine the presense and purpose of any event parameters.
+ *
+ * Usage Example:
+ * \code
+ * // Create an event handler for the USB_VBUSChange event
+ * EVENT_HANDLER(USB_VBUSChange)
+ * {
+ * // Code to execute when the VBUS level changes
+ * }
+ * \endcode
+ *
+ * \see HANDLES_EVENT()
+ */
+ #define EVENT_HANDLER(e) void Event_ ## e e ## _P
+
+ /** Indicates that a given module handles an event. This is the equivelent of putting the
+ * event function's prototype into the module, but in a cleaner way. Each event which may be
+ * handled via the EVENT_HANDLER macro in the module should have an accompanying HANDLES_EVENT
+ * prototype in the module's header file.
+ *
+ * Usage Examples:
+ * \code
+ * // Module handles the USB_VBUSChange event
+ * HANDLES_EVENT(USB_VBUSChange);
+ *
+ * // Create the USB_VBUSChange event handler
+ * EVENT_HANDLER(USB_VBUSChange)
+ * {
+ * // Event handler code here
+ * }
+ * \endcode
+ *
+ * \see EVENT_HANDLER()
+ */
+ #define HANDLES_EVENT(e) EVENT_HANDLER(e)
+
+ /* Psudo-Functions for Doxygen: */
+ #if defined(__DOXYGEN__)
+ /** Event for VBUS level change. This event fires when the VBUS line of the USB AVR changes from
+ * high to low or vice-versa.
+ *
+ * \note This event is only available on USB AVR models which support VBUS notification interrupts.
+ */
+ void USB_VBUSChange(void);
+
+ /** Event for VBUS attachment. This event fires when the VBUS line of the USB AVR changes from
+ * low to high, signalling the attachment of the USB device to a host, before the enumeration
+ * process has begun.
+ *
+ * \note This event is only available on USB AVR models which support VBUS notification interrupts.
+ */
+ void USB_VBUSConnect(void);
+
+ /** Event for VBUS detachment. This event fires when the VBUS line of the USB AVR changes from
+ * high to low, signalling the USB device has been removed from a host whether it has been enumerated
+ * or not.
+ *
+ * \note This event is only available on USB AVR models which support VBUS notification interrupts.
+ */
+ void USB_VBUSDisconnect(void);
+
+ /** Event for USB device connection. This event fires when the AVR is in USB host mode and a device
+ * has been attached (but not yet fully enumerated), or when in device mode and the device is connected
+ * to a host, beginning the enumeration process.
+ *
+ * When in device mode, this can be used to progmatically start the USB management task to reduce
+ * CPU usage.
+ *
+ * \note For the smaller USB AVRs (AT90USBXX2) with limited USB controllers, VBUS is not available to the USB controller.
+ * this means that the current connection state is derived from the bus suspension and wake up events by default,
+ * which is not always accurate (host may suspend the bus while still connected). If the actual connection state
+ * needs to be determined, VBUS should be routed to an external pin, and the auto-detect behaviour turned off by
+ * passing the NO_LIMITED_CONTROLLER_CONNECT token to the compiler via the -D switch at compile time. The connection
+ * and disconnection events may be manually fired by RAISE_EVENT(), and the USB_IsConnected global changed manually.
+ *
+ * \see USBTask.h for more information on the USB management task and reducing CPU usage.
+ */
+ void USB_Connect(void);
+
+ /** Event for USB device disconnection. This event fires when the AVR is in USB host mode and an
+ * attached and enumerated device has been disconnected, or when in device mode and the device is
+ * disconnected from the host.
+ *
+ * When in device mode, this can be used to progmatically stop the USB management task to reduce
+ * CPU usage.
+ *
+ * \note For the smaller USB AVRs (AT90USBXX2) with limited USB controllers, VBUS is not available to the USB controller.
+ * this means that the current connection state is derived from the bus suspension and wake up events by default,
+ * which is not always accurate (host may suspend the bus while still connected). If the actual connection state
+ * needs to be determined, VBUS should be routed to an external pin, and the auto-detect behaviour turned off by
+ * passing the NO_LIMITED_CONTROLLER_CONNECT token to the compiler via the -D switch at compile time. The connection
+ * and disconnection events may be manually fired by RAISE_EVENT(), and the USB_IsConnected global changed manually.
+ *
+ * \see USBTask.h for more information on the USB management task and reducing CPU usage.
+ */
+ void USB_Disconnect(void);
+
+ /** Event for USB device power on failure. This event fires when the USB interface fails to
+ * initialize correctly due to a hardware or software fault.
+ *
+ * \param ErrorCode Error code indicating the failure reason, a value in USB_PowerOnErrorCodes_t
+ * located in LowLevel.h.
+ */
+ void USB_PowerOnFail(const uint8_t ErrorCode);
+
+ /** Event for USB mode pin level change. This event fires when the USB interface is set to dual role
+ * mode, and the UID pin level has changed to indicate a new mode (device or host). This event fires
+ * before the mode is switched to the newly indicated mode.
+ *
+ * \note This event only exists on USB AVR models which support dual role modes.
+ *
+ * \note This event does not exist if the USB_DEVICE_ONLY or USB_HOST_ONLY tokens have been supplied
+ * to the compiler (see LowLevel.h documentation).
+ */
+ void USB_UIDChange(void);
+
+ /** Event for USB host error. This event fires when a hardware fault has occurred whilst the USB
+ * interface is in host mode.
+ *
+ * \param ErrorCode Error code indicating the failure reason, a value in USB_Host_ErrorCodes_t
+ * located in Host.h.
+ *
+ * \note This event only exists on USB AVR models which supports host mode.
+ *
+ * \note This event does not exist if the USB_DEVICE_ONLY token is supplied to the compiler (see
+ * LowLevel.h documentation).
+ */
+ void USB_HostError(const uint8_t ErrorCode);
+
+ /** Event for USB device attachment. This event fires when a the USB interface is in host mode, and
+ * a USB device has been connected to the USB interface. This is interrupt driven, thus fires before
+ * the standard USB_DeviceConnect event and so can be used to programatically start the USB management
+ * task to reduce CPU consumption.
+ *
+ * \note This event only exists on USB AVR models which supports host mode.
+ *
+ * \note This event does not exist if the USB_DEVICE_ONLY token is supplied to the compiler (see
+ * LowLevel.h documentation).
+ *
+ * \see USBTask.h for more information on the USB management task and reducing CPU usage.
+ */
+ void USB_DeviceAttached(void);
+
+ /** Event for USB device removal. This event fires when a the USB interface is in host mode, and
+ * a USB device has been removed the USB interface whether or not it has been enumerated. This
+ * can be used to programatically stop the USB management task to reduce CPU consumption.
+ *
+ * \note This event only exists on USB AVR models which supports host mode.
+ *
+ * \note This event does not exist if the USB_DEVICE_ONLY token is supplied to the compiler (see
+ * LowLevel.h documentation).
+ *
+ * \see USBTask.h for more information on the USB management task and reducing CPU usage.
+ */
+ void USB_DeviceUnattached(void);
+
+ /** Event for USB device enumeration failure. This event fires when a the USB interface is
+ * in host mode, and an attached USB device has failed to enumerate completely.
+ *
+ * \param ErrorCode Error code indicating the failure reason, a value in
+ * USB_Host_EnumerationErrorCodes_t located in Host.h.
+ *
+ * \param SubErrorCode Sub error code indicating the reason for failure - for example, if the
+ * ErrorCode parameter indicates a control error, this will give the error
+ * code returned by the USB_Host_SendControlRequest() function.
+ *
+ * \note This event only exists on USB AVR models which supports host mode.
+ *
+ * \note This event does not exist if the USB_DEVICE_ONLY token is supplied to the compiler (see
+ * LowLevel.h documentation).
+ */
+ void USB_DeviceEnumerationFailed(const uint8_t ErrorCode, const uint8_t SubErrorCode);
+
+ /** Event for USB device enumeration completion. This event fires when a the USB interface is
+ * in host mode and an attached USB device has been completely enumerated and is ready to be
+ * controlled by the user application, or when the library is in device mode, and the Host
+ * has finished enumerating the device.
+ */
+ void USB_DeviceEnumerationComplete(void);
+
+ /** Event for unhandled control requests. This event fires when a the USB host issues a control
+ * request to the control endpoint (address 0) that the library does not handle. This may either
+ * be a standard request that the library has no handler code for, or a class specific request
+ * issued to the device which must be handled appropriately. Due to the strict timing requirements
+ * on control transfers, interrupts are disabled during control request processing.
+ *
+ * \param bRequest Request value, indicating what command the host has issued.
+ * \param bmRequestType Mask indicating the request data direction (if any), type and recipient.
+ *
+ * \note This event does not exist if the USB_HOST_ONLY token is supplied to the compiler (see
+ * LowLevel.h documentation).
+ *
+ * \note Requests should be handled in the same manner as described in the USB 2.0 Specification,
+ * or appropriate class' specification. In all instances, the library has already read the
+ * request bmRequestType and bRequest values out (into the Request and RequestType parameters
+ * respectively) so that it can correctly determine if it is able to handle the request
+ * internally, or hand off the request to the user application via this event. Other request
+ * parameters (wValue, wIndex, wLength, and Data) remain in the control endpoint bank until
+ * read out by the user application for processing.
+ */
+ void USB_UnhandledControlPacket(const uint8_t bRequest, const uint8_t bmRequestType);
+
+ /** Event for USB configuration number changed. This event fires when a the USB host changes the
+ * selected configuration number while in device mode. This event should be hooked in device
+ * applications to create the endpoints and configure the device for the selected configuration.
+ *
+ * This event fires after the value of USB_ConfigurationNumber has been changed.
+ *
+ * \note This event does not exist if the USB_HOST_ONLY token is supplied to the compiler (see
+ * LowLevel.h documentation).
+ */
+ void USB_ConfigurationChanged(void);
+
+ /** Event for USB suspend. This event fires when a the USB host suspends the device by halting its
+ * transmission of Start Of Frame pulses to the device. This is generally hooked in order to move
+ * the device over to a low power state until the host wakes up the device.
+ *
+ * \note This event does not exist if the USB_HOST_ONLY token is supplied to the compiler (see
+ * LowLevel.h documentation).
+ *
+ * \see USB_WakeUp() event for accompanying Wake Up event.
+ */
+ void USB_Suspend(void);
+
+ /** Event for USB wake up. This event fires when a the USB interface is suspended while in device
+ * mode, and the host wakes up the device by supplying Start Of Frame pulses. This is generally
+ * hooked to pull the user application out of a lowe power state and back into normal operating
+ * mode.
+ *
+ * \note This event does not exist if the USB_HOST_ONLY token is supplied to the compiler (see
+ * LowLevel.h documentation).
+ *
+ * \see USB_Suspend() event for accompanying Suspend event.
+ */
+ void USB_WakeUp(void);
+
+ /** Event for USB interface reset. This event fires when a the USB interface is in device mode, and
+ * a the USB host requests that the device reset its interface. This is generally hooked so that
+ * the USB control endpoint can be switched to interrupt driven mode, by selecting it and calling
+ * USB_INT_Enable(ENDPOINT_INT_SETUP). Before this event fires, all device endpoints are reset and
+ * disabled.
+ *
+ * \note This event does not exist if the USB_HOST_ONLY token is supplied to the compiler (see
+ * LowLevel.h documentation).
+ */
+ void USB_Reset(void);
+
+ /** Event for USB device mode error. This event fires when the USB interface is in device mode,
+ * and an error occurs which prevents it from operating normally.
+ *
+ * \param ErrorCode Error code indicating the source of the error. One of the values in the
+ * USB_Device_ErrorCodes_t enum located in Device.h.
+ *
+ * \note This event does not exist if the USB_HOST_ONLY token is supplied to the compiler (see
+ * LowLevel.h documentation).
+ */
+ void USB_DeviceError(const uint8_t ErrorCode);
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define ALIAS_STUB(e) EVENT_HANDLER(e) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub)
+
+ #if defined(USB_FULL_CONTROLLER) || defined(USB_MODIFIED_FULL_CONTROLLER)
+ #define USB_VBUSChange_P (void)
+ #define USB_VBUSConnect_P (void)
+ #define USB_VBUSDisconnect_P (void)
+ #endif
+
+ #define USB_Connect_P (void)
+ #define USB_Disconnect_P (void)
+ #define USB_DeviceEnumerationComplete_P (void)
+
+ #if defined(USB_CAN_BE_BOTH)
+ #define USB_PowerOnFail_P (const uint8_t ErrorCode)
+ #define USB_UIDChange_P (void)
+ #endif
+
+ #if defined(USB_CAN_BE_HOST)
+ #define USB_HostError_P (const uint8_t ErrorCode)
+ #define USB_DeviceAttached_P (void)
+ #define USB_DeviceUnattached_P (void)
+ #define USB_DeviceEnumerationFailed_P (const uint8_t ErrorCode, const uint8_t SubErrorCode)
+ #endif
+
+ #if defined(USB_CAN_BE_DEVICE)
+ #define USB_UnhandledControlPacket_P (const uint8_t bRequest, const uint8_t bmRequestType)
+ #define USB_ConfigurationChanged_P (void)
+ #define USB_Suspend_P (void)
+ #define USB_WakeUp_P (void)
+ #define USB_Reset_P (void)
+ #define USB_DeviceError_P (const uint8_t ErrorCode)
+ #endif
+
+ /* Function Prototypes: */
+ #if defined(INCLUDE_FROM_EVENTS_C)
+ void USB_Event_Stub (void) ATTR_CONST;
+
+ #if defined(USB_FULL_CONTROLLER) || defined(USB_MODIFIED_FULL_CONTROLLER)
+ ALIAS_STUB(USB_VBUSChange);
+ ALIAS_STUB(USB_VBUSConnect);
+ ALIAS_STUB(USB_VBUSDisconnect);
+ #endif
+
+ ALIAS_STUB(USB_Connect);
+ ALIAS_STUB(USB_Disconnect);
+ ALIAS_STUB(USB_DeviceEnumerationComplete);
+
+ #if defined(USB_CAN_BE_BOTH)
+ ALIAS_STUB(USB_PowerOnFail);
+ ALIAS_STUB(USB_UIDChange);
+ #endif
+
+ #if defined(USB_CAN_BE_HOST)
+ ALIAS_STUB(USB_HostError);
+ ALIAS_STUB(USB_DeviceAttached);
+ ALIAS_STUB(USB_DeviceUnattached);
+ ALIAS_STUB(USB_DeviceEnumerationFailed);
+ #endif
+
+ #if defined(USB_CAN_BE_DEVICE)
+ ALIAS_STUB(USB_UnhandledControlPacket);
+ ALIAS_STUB(USB_ConfigurationChanged);
+ ALIAS_STUB(USB_Suspend);
+ ALIAS_STUB(USB_WakeUp);
+ ALIAS_STUB(USB_Reset);
+ ALIAS_STUB(USB_DeviceError);
+ #endif
+ #endif
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
diff --git a/LUFA/Drivers/USB/HighLevel/StdDescriptors.c b/LUFA/Drivers/USB/HighLevel/StdDescriptors.c new file mode 100644 index 000000000..5fdc72e80 --- /dev/null +++ b/LUFA/Drivers/USB/HighLevel/StdDescriptors.c @@ -0,0 +1,43 @@ +/*
+ 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 "../LowLevel/USBMode.h"
+#if defined(USB_CAN_BE_DEVICE)
+
+#include "StdDescriptors.h"
+
+uint16_t USB_GetDescriptor(const uint16_t wValue, const uint8_t wIndex, void** const DescriptorAddress)
+{
+ RAISE_EVENT(USB_DeviceError, DEVICE_ERROR_GetDescriptorNotHooked);
+
+ return 0;
+};
+
+#endif
diff --git a/LUFA/Drivers/USB/HighLevel/StdDescriptors.h b/LUFA/Drivers/USB/HighLevel/StdDescriptors.h new file mode 100644 index 000000000..d9075cc75 --- /dev/null +++ b/LUFA/Drivers/USB/HighLevel/StdDescriptors.h @@ -0,0 +1,523 @@ +/*
+ 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
+ *
+ * Standard USB device descriptor defines and retrieval routines, for USB devices. This module contains
+ * strucutures and macros for the easy creation of standard USB descriptors in USB device projects.
+ *
+ * All standard descriptors have their elements named in an identical manner to the official USB specification,
+ * however slightly more verbose alternate (non-standard) names are also supplied if the macro
+ * USE_NONSTANDARD_DESCRIPTOR_NAMES is defined in the user project makefile and passed to the compiler at
+ * compilation time using the -D option.
+ *
+ * The non-standard names are documented here - if USE_NONSTANDARD_DESCRIPTOR_NAMES is not defined, then all
+ * descriptors will contain elements named identically to the official USB specification. The alternately
+ * named descriptor elements are placed in the same order inside the descriptor structures as their officially
+ * named counterparts, thus they can be correlated easily with the official USB specification.
+ */
+
+#ifndef __USBDESCRIPTORS_H__
+#define __USBDESCRIPTORS_H__
+
+ /* Includes: */
+ #include <avr/pgmspace.h>
+ #include <stdbool.h>
+
+ #include "../../../Common/Common.h"
+ #include "../LowLevel/USBMode.h"
+ #include "Events.h"
+
+ #if defined(USB_CAN_BE_DEVICE)
+ #include "../LowLevel/Device.h"
+ #endif
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates that a given descriptor does not exist in the device. This can be used inside descriptors
+ * for string descriptor indexes, or may be use as a return value for GetDescriptor when the specified
+ * descriptor does not exist.
+ */
+ #define NO_DESCRIPTOR 0
+
+ /** Macro to calculate the power value for the device descriptor, from a given number of milliamps. */
+ #define USB_CONFIG_POWER_MA(x) (x >> 1)
+
+ /** Macro to calculate the Unicode length of a string with a given number of Unicode characters.
+ * Should be used in string descriptor's headers for giving the string descriptor's byte length.
+ */
+ #define USB_STRING_LEN(x) (sizeof(USB_Descriptor_Header_t) + (x << 1))
+
+ /** Macro to encode a given four digit floating point version number (e.g. 01.23) into Binary Coded
+ * Decimal format for descriptor fields requiring BCD encoding, such as the USB version number in the
+ * standard device descriptor.
+ */
+ #define VERSION_BCD(x) ((((VERSION_TENS(x) << 4) | VERSION_ONES(x)) << 8) | \
+ ((VERSION_TENTHS(x) << 4) | VERSION_HUNDREDTHS(x)))
+
+ /** String language ID for the English language. Should be used in USB_Descriptor_Language_t descriptors
+ * to indicate that the English language is supported by the device in its string descriptors.
+ */
+ #define LANGUAGE_ID_ENG 0x0409
+
+ /** Can be masked with an endpoint address for a USB_Descriptor_Endpoint_t endpoint descriptor's
+ * EndpointAddress value to indicate to the host that the endpoint is of the IN direction (i.e, from
+ * device to host).
+ */
+ #define ENDPOINT_DESCRIPTOR_DIR_IN 0x80
+
+ /** Can be masked with an endpoint address for a USB_Descriptor_Endpoint_t endpoint descriptor's
+ * EndpointAddress value to indicate to the host that the endpoint is of the OUT direction (i.e, from
+ * host to device).
+ */
+ #define ENDPOINT_DESCRIPTOR_DIR_OUT 0x00
+
+ /** Can be masked with other configuration descriptor attributes for a USB_Descriptor_Configuration_Header_t
+ * descriptor's ConfigAttributes value to indicate that the specified configuration can draw its power
+ * from the host's VBUS line.
+ */
+ #define USB_CONFIG_ATTR_BUSPOWERED 0b10000000
+
+ /** Can be masked with other configuration descriptor attributes for a USB_Descriptor_Configuration_Header_t
+ * descriptor's ConfigAttributes value to indicate that the specified configuration can draw its power
+ * from the device's own power source.
+ */
+ #define USB_CONFIG_ATTR_SELFPOWERED 0b11000000
+
+ /** Can be masked with other configuration descriptor attributes for a USB_Descriptor_Configuration_Header_t
+ * descriptor's ConfigAttributes value to indicate that the specified configuration supports the
+ * remote wakeup feature of the USB standard, allowing a suspended USB device to wake up the host upon
+ * request.
+ */
+ #define USB_CONFIG_ATTR_REMOTEWAKEUP 0b10100000
+
+ /** Can be masked with other endpoint descriptor attributes for a USB_Descriptor_Endpoint_t descriptor's
+ * Attributes value to indicate that the specified endpoint is not synchronized.
+ *
+ * \see The USB specification for more details on the possible Endpoint attributes.
+ */
+ #define ENDPOINT_ATTR_NO_SYNC (0b00 << 2)
+
+ /** Can be masked with other endpoint descriptor attributes for a USB_Descriptor_Endpoint_t descriptor's
+ * Attributes value to indicate that the specified endpoint is asynchronous.
+ *
+ * \see The USB specification for more details on the possible Endpoint attributes.
+ */
+ #define ENDPOINT_ATTR_ASYNC (0b01 << 2)
+
+ /** Can be masked with other endpoint descriptor attributes for a USB_Descriptor_Endpoint_t descriptor's
+ * Attributes value to indicate that the specified endpoint is adaptive.
+ *
+ * \see The USB specification for more details on the possible Endpoint attributes.
+ */
+ #define ENDPOINT_ATTR_ADAPTIVE (0b10 << 2)
+
+ /** Can be masked with other endpoint descriptor attributes for a USB_Descriptor_Endpoint_t descriptor's
+ * Attributes value to indicate that the specified endpoint is synchronized.
+ *
+ * \see The USB specification for more details on the possible Endpoint attributes.
+ */
+ #define ENDPOINT_ATTR_SYNC (0b11 << 2)
+
+ /** Can be masked with other endpoint descriptor attributes for a USB_Descriptor_Endpoint_t descriptor's
+ * Attributes value to indicate that the specified endpoint is used for data transfers.
+ *
+ * \see The USB specification for more details on the possible Endpoint usage attributes.
+ */
+ #define ENDPOINT_USAGE_DATA (0b00 << 4)
+
+ /** Can be masked with other endpoint descriptor attributes for a USB_Descriptor_Endpoint_t descriptor's
+ * Attributes value to indicate that the specified endpoint is used for feedback.
+ *
+ * \see The USB specification for more details on the possible Endpoint usage attributes.
+ */
+ #define ENDPOINT_USAGE_FEEDBACK (0b01 << 4)
+
+ /** Can be masked with other endpoint descriptor attributes for a USB_Descriptor_Endpoint_t descriptor's
+ * Attributes value to indicate that the specified endpoint is used for implicit feedback.
+ *
+ * \see The USB specification for more details on the possible Endpoint usage attributes.
+ */
+ #define ENDPOINT_USAGE_IMPLICIT_FEEDBACK (0b10 << 4)
+
+ /** Gives a void pointer to the specified descriptor (of any type). */
+ #define DESCRIPTOR_ADDRESS(Descriptor) ((void*)&Descriptor)
+
+ /* Events: */
+ #if defined(USB_CAN_BE_DEVICE) || defined(__DOXYGEN__)
+ /** This module raises the Device Error event while in device mode, if the USB_GetDescriptor()
+ * routine is not hooked in the user application to properly return descriptors to the library.
+ *
+ * \see Events.h for more information on this event.
+ */
+ RAISES_EVENT(USB_DeviceError);
+ #endif
+
+ /* Enums: */
+ /** Enum for the possible standard descriptor types, as given in each descriptor's header. */
+ enum USB_DescriptorTypes_t
+ {
+ DTYPE_Device = 0x01, /**< Indicates that the descriptor is a device descriptor. */
+ DTYPE_Configuration = 0x02, /**< Indicates that the descriptor is a configuration descriptor. */
+ DTYPE_String = 0x03, /**< Indicates that the descriptor is a string descriptor. */
+ DTYPE_Interface = 0x04, /**< Indicates that the descriptor is an interface descriptor. */
+ DTYPE_Endpoint = 0x05, /**< Indicates that the descriptor is an endpoint descriptor. */
+ DTYPE_DeviceQualifier = 0x06, /**< Indicates that the descriptor is a device qualifier descriptor. */
+ DTYPE_Other = 0x07, /**< Indicates that the descriptor is of other type. */
+ DTYPE_InterfacePower = 0x08, /**< Indicates that the descriptor is an interface power descriptor. */
+ DTYPE_InterfaceAssociation = 0x0B, /**< Indicates that the descriptor is an interface association descriptor. */
+ };
+
+ /* Type Defines: */
+ /** Type define for all descriptor's header, indicating the descriptor's length and type.
+ *
+ * \note The non-standard structure element names are documented here - see the StdDescriptors.h file
+ * documentation for more information on the two descriptor naming schemes. If the
+ * USE_NONSTANDARD_DESCRIPTOR_NAMES token is not set, this structure contains elements with names
+ * identical to those listed in the USB standard.
+ */
+ typedef struct
+ {
+ #if defined(USE_NONSTANDARD_DESCRIPTOR_NAMES) || defined(__DOXYGEN__)
+ uint8_t Size; /**< Size of the descriptor, in bytes. */
+ uint8_t Type; /**< Type of the descriptor, either a value in DescriptorTypes_t or a value
+ * given by the specific class.
+ */
+ #else
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ #endif
+ } USB_Descriptor_Header_t;
+
+ /** Type define for a standard device descriptor.
+ *
+ * \note The non-standard structure element names are documented here - see the StdDescriptors.h file
+ * documentation for more information on the two descriptor naming schemes. If the
+ * USE_NONSTANDARD_DESCRIPTOR_NAMES token is not set, this structure contains elements with names
+ * identical to those listed in the USB standard.
+ */
+ typedef struct
+ {
+ #if defined(USE_NONSTANDARD_DESCRIPTOR_NAMES) || defined(__DOXYGEN__)
+ USB_Descriptor_Header_t Header; /**< Descriptor header, including type and size. */
+
+ uint16_t USBSpecification; /**< BCD of the supported USB specification. */
+ uint8_t Class; /**< USB device class. */
+ uint8_t SubClass; /**< USB device subclass. */
+ uint8_t Protocol; /**< USB device protocol. */
+
+ uint8_t Endpoint0Size; /**< Size of the control (address 0) endpoint's bank in bytes. */
+
+ uint16_t VendorID; /**< Vendor ID for the USB product. */
+ uint16_t ProductID; /**< Unique product ID for the USB product. */
+ uint16_t ReleaseNumber; /**< Product release (version) number. */
+
+ uint8_t ManufacturerStrIndex; /**< String index for the manufacturer's name. The
+ * host will request this string via a seperate
+ * control request for the string descriptor.
+ *
+ * \note If no string supplied, use NO_DESCRIPTOR.
+ */
+ uint8_t ProductStrIndex; /**< String index for the product name/details.
+ *
+ * \see ManufacturerStrIndex structure entry.
+ */
+ uint8_t SerialNumStrIndex; /**< String index for the product's globally unique hexadecimal
+ * serial number, in uppercase Unicoded ASCII.
+ *
+ * \see ManufacturerStrIndex structure entry.
+ */
+
+ uint8_t NumberOfConfigurations; /**< Total number of configurations supported by
+ * the device.
+ */
+ #else
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint16_t bcdUSB;
+ uint8_t bDeviceClass;
+ uint8_t bDeviceSubClass;
+ uint8_t bDeviceProtocol;
+ uint8_t bMaxPacketSize0;
+ uint16_t idVendor;
+ uint16_t idProduct;
+ uint16_t bcdDevice;
+ uint8_t iManufacturer;
+ uint8_t iProduct;
+ uint8_t iSerialNumber;
+ uint8_t bNumConfigurations;
+ #endif
+ } USB_Descriptor_Device_t;
+
+ /** Type define for a standard configuration descriptor.
+ *
+ * \note The non-standard structure element names are documented here - see the StdDescriptors.h file
+ * documentation for more information on the two descriptor naming schemes. If the
+ * USE_NONSTANDARD_DESCRIPTOR_NAMES token is not set, this structure contains elements with names
+ * identical to those listed in the USB standard.
+ */
+ typedef struct
+ {
+ #if defined(USE_NONSTANDARD_DESCRIPTOR_NAMES) || defined(__DOXYGEN__)
+ USB_Descriptor_Header_t Header; /**< Descriptor header, including type and size. */
+
+ uint16_t TotalConfigurationSize; /**< Size of the configuration descriptor header,
+ * and all sub descriptors inside the configuration.
+ */
+ uint8_t TotalInterfaces; /**< Total number of interfaces in the configuration. */
+
+ uint8_t ConfigurationNumber; /**< Configuration index of the current configuration. */
+ uint8_t ConfigurationStrIndex; /**< Index of a string descriptor describing the configuration. */
+
+ uint8_t ConfigAttributes; /**< Configuration attributes, comprised of a mask of zero or
+ * more USB_CONFIG_ATTR_* masks.
+ */
+
+ uint8_t MaxPowerConsumption; /**< Maximum power consumption of the device while in the
+ * current configuration, calculated by the USB_CONFIG_POWER_MA()
+ * macro.
+ */
+ #else
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint16_t wTotalLength;
+ uint8_t bNumInterfaces;
+ uint8_t bConfigurationValue;
+ uint8_t iConfiguration;
+ uint8_t bmAttributes;
+ uint8_t bMaxPower;
+ #endif
+ } USB_Descriptor_Configuration_Header_t;
+
+ /** Type define for a standard interface descriptor.
+ *
+ * \note The non-standard structure element names are documented here - see the StdDescriptors.h file
+ * documentation for more information on the two descriptor naming schemes. If the
+ * USE_NONSTANDARD_DESCRIPTOR_NAMES token is not set, this structure contains elements with names
+ * identical to those listed in the USB standard.
+ */
+ typedef struct
+ {
+ #if defined(USE_NONSTANDARD_DESCRIPTOR_NAMES) || defined(__DOXYGEN__)
+ USB_Descriptor_Header_t Header; /**< Descriptor header, including type and size. */
+
+ uint8_t InterfaceNumber; /**< Index of the interface in the current configuration. */
+ uint8_t AlternateSetting; /**< Alternate setting for the interface number. The same
+ * interface number can have multiple alternate settings
+ * with different endpoint configurations, which can be
+ * selected by the host.
+ */
+ uint8_t TotalEndpoints; /**< Total number of endpoints in the interface. */
+
+ uint8_t Class; /**< Interface class ID. */
+ uint8_t SubClass; /**< Interface subclass ID. */
+ uint8_t Protocol; /**< Interface protocol ID. */
+
+ uint8_t InterfaceStrIndex; /**< Index of the string descriptor describing the
+ * interface.
+ */
+ #else
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bInterfaceNumber;
+ uint8_t bAlternateSetting;
+ uint8_t bNumEndpoints;
+ uint8_t bInterfaceClass;
+ uint8_t bInterfaceSubClass;
+ uint8_t bInterfaceProtocol;
+ uint8_t iInterface;
+ #endif
+ } USB_Descriptor_Interface_t;
+
+ /** Type define for a standard interface association descriptor.
+ *
+ * This descriptor has been added as a suppliment to the USB2.0 standard, in the ECN located at
+ * <a>http://www.usb.org/developers/docs/InterfaceAssociationDescriptor_ecn.pdf</a>. It allows compound
+ * devices with multiple interfaces related to the same function to have the multiple interfaces bound
+ * together at the point of enumeration, loading one generic driver for all the interfaces in the single
+ * function. Read the ECN for more information.
+ *
+ * \note The non-standard structure element names are documented here - see the StdDescriptors.h file
+ * documentation for more information on the two descriptor naming schemes. If the
+ * USE_NONSTANDARD_DESCRIPTOR_NAMES token is not set, this structure contains elements with names
+ * identical to those listed in the USB standard.
+ */
+ typedef struct
+ {
+ #if defined(USE_NONSTANDARD_DESCRIPTOR_NAMES) || defined(__DOXYGEN__)
+ USB_Descriptor_Header_t Header; /**< Descriptor header, including type and size. */
+
+ uint8_t FirstInterfaceIndex; /**< Index of the first associated interface. */
+ uint8_t TotalInterfaces; /** Total number of associated interfaces. */
+
+ uint8_t Class; /**< Interface class ID. */
+ uint8_t SubClass; /**< Interface subclass ID. */
+ uint8_t Protocol; /**< Interface protocol ID. */
+
+ uint8_t IADStrIndex; /**< Index of the string descriptor describing the
+ * interface association.
+ */
+ #else
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bFirstInterface;
+ uint8_t bInterfaceCount;
+ uint8_t bFunctionClass;
+ uint8_t bFunctionSubClass;
+ uint8_t bFunctionProtocol;
+ uint8_t iFunction;
+ #endif
+ } USB_Descriptor_Interface_Association_t;
+
+ /** Type define for a standard endpoint descriptor.
+ *
+ * \note The non-standard structure element names are documented here - see the StdDescriptors.h file
+ * documentation for more information on the two descriptor naming schemes. If the
+ * USE_NONSTANDARD_DESCRIPTOR_NAMES token is not set, this structure contains elements with names
+ * identical to those listed in the USB standard.
+ */
+ typedef struct
+ {
+ #if defined(USE_NONSTANDARD_DESCRIPTOR_NAMES) || defined(__DOXYGEN__)
+ USB_Descriptor_Header_t Header; /**< Descriptor header, including type and size. */
+
+ uint8_t EndpointAddress; /**< Logical address of the endpoint within the device
+ * for the current configuration, including direction
+ * mask.
+ */
+ uint8_t Attributes; /**< Endpoint attributes, comprised of a mask of the
+ * endpoint type (EP_TYPE_*) and attributes (ENDPOINT_ATTR_*)
+ * masks.
+ */
+ uint16_t EndpointSize; /**< Size of the endpoint bank, in bytes. This indicates the
+ * maximum packet size that the endpoint can receive at a time.
+ */
+
+ uint8_t PollingIntervalMS; /**< Polling interval in milliseconds for the endpont
+ * if it is an INTERRUPT or ISOCHRONOUS type.
+ */
+ #else
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bEndpointAddress;
+ uint8_t bmAttributes;
+ uint16_t wMaxPacketSize;
+ uint8_t bInterval;
+ #endif
+ } USB_Descriptor_Endpoint_t;
+
+ /** Type define for a standard string descriptor. Unlike other standard descriptors, the length
+ * of the descriptor for placement in the descriptor header must be determined by the USB_STRING_LEN()
+ * macro rather than by the size of the descriptor structure, as the length is not fixed.
+ *
+ * This structure should also be used for string index 0, which contains the supported language IDs for
+ * the device as an array.
+ *
+ * \note The non-standard structure element names are documented here - see the StdDescriptors.h file
+ * documentation for more information on the two descriptor naming schemes. If the
+ * USE_NONSTANDARD_DESCRIPTOR_NAMES token is not set, this structure contains elements with names
+ * identical to those listed in the USB standard.
+ */
+ typedef struct
+ {
+ #if defined(USE_NONSTANDARD_DESCRIPTOR_NAMES) || defined(__DOXYGEN__)
+ USB_Descriptor_Header_t Header; /**< Descriptor header, including type and size. */
+
+ int16_t UnicodeString[]; /**< String data, as unicode characters (alternatively,
+ * string language IDs). If normal ASCII characters are
+ * to be used, they must be added as an array of characters
+ * rather than a normal C string so that they are widened to
+ * Unicode size.
+ *
+ * Under GCC, strings prefixed with the "L" character (before
+ * the opening string quotation mark) are considered to be
+ * Unicode strings, and may be used instead of an explicit
+ * array of ASCII characters.
+ */
+ #else
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ int16_t bString[];
+ #endif
+ } USB_Descriptor_String_t;
+
+ typedef struct
+ {
+ uint16_t Size;
+ void* Address;
+ } USB_Descriptor_Details_t;
+
+ /* Function Prototypes: */
+ /** Function to retrieve a given descriptor's size and memory location from the given descriptor type value,
+ * index and language ID. This function MUST be overridden in the user application (added with full, identical
+ * prototype and name except for the ATTR_WEAK attribute) so that the library can call it to retrieve descriptor
+ * data.
+ *
+ * \param wValue The type of the descriptor to retrieve in the upper byte, and the index in the
+ * lower byte (when more than one descriptor of the given type exists, such as the
+ * case of string descriptors). The type may be one of the standard types defined
+ * in the DescriptorTypes_t enum, or may be a class-specific descriptor type value.
+ * \param wIndex The language ID of the string to return if the wValue type indicates DTYPE_String,
+ * otherwise zero for standard descriptors, or as defined in a class-specific
+ * standards.
+ * \param DescriptorAddress Pointer to the descriptor in memory. This should be set by the routine to
+ * the location of the descriptor, found by the DESCRIPTOR_ADDRESS macro.
+ *
+ * \note By default, the library expects all descriptors to be located in flash memory via the PROGMEM attribute.
+ * If descriptors should be located in RAM or EEPROM instead (to speed up access in the case of RAM, or to
+ * allow the descriptors to be changed dynamically at runtime) either the USE_SRAM_DESCRIPTORS or the
+ * USE_EEPROM_DESCRIPTORS tokens may be defined in the project makefile and passed to the compiler by the -D
+ * switch.
+ *
+ * \return Size in bytes of the descriptor if it exists, zero or NO_DESCRIPTOR otherwise
+ */
+ uint16_t USB_GetDescriptor(const uint16_t wValue, const uint8_t wIndex, void** const DescriptorAddress)
+ ATTR_WARN_UNUSED_RESULT ATTR_WEAK ATTR_NON_NULL_PTR_ARG(3);
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define VERSION_TENS(x) (int)(x / 10)
+ #define VERSION_ONES(x) (int)(x - (10 * VERSION_TENS(x)))
+ #define VERSION_TENTHS(x) (int)((x - (int)x) * 10)
+ #define VERSION_HUNDREDTHS(x) (int)(((x - (int)x) * 100) - (10 * VERSION_TENTHS(x)))
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
diff --git a/LUFA/Drivers/USB/HighLevel/USBInterrupt.c b/LUFA/Drivers/USB/HighLevel/USBInterrupt.c new file mode 100644 index 000000000..58faa69de --- /dev/null +++ b/LUFA/Drivers/USB/HighLevel/USBInterrupt.c @@ -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.
+*/
+
+#include "../LowLevel/USBMode.h"
+#include "USBInterrupt.h"
+
+void USB_INT_DisableAllInterrupts(void)
+{
+ #if defined(USB_FULL_CONTROLLER)
+ USBCON &= ~((1 << VBUSTE) | (1 << IDTE));
+ #elif defined(USB_MODIFIED_FULL_CONTROLLER)
+ USBCON &= ~(1 << VBUSTE);
+ #endif
+
+ #if defined(USB_CAN_BE_HOST)
+ UHIEN = 0;
+ OTGIEN = 0;
+ #endif
+
+ #if defined(USB_CAN_BE_DEVICE)
+ UDIEN = 0;
+ #endif
+}
+
+void USB_INT_ClearAllInterrupts(void)
+{
+ #if defined(USB_FULL_CONTROLLER) || defined(USB_MODIFIED_FULL_CONTROLLER)
+ USBINT = 0;
+ #endif
+
+ #if defined(USB_CAN_BE_HOST)
+ UHINT = 0;
+ OTGINT = 0;
+ #endif
+
+ #if defined(USB_CAN_BE_DEVICE)
+ UDINT = 0;
+ #endif
+}
+
+ISR(USB_GEN_vect, ISR_BLOCK)
+{
+ #if defined(USB_CAN_BE_DEVICE)
+ #if defined(USB_FULL_CONTROLLER) || defined(USB_MODIFIED_FULL_CONTROLLER)
+ if (USB_INT_HasOccurred(USB_INT_VBUS) && USB_INT_IsEnabled(USB_INT_VBUS))
+ {
+ USB_INT_Clear(USB_INT_VBUS);
+
+ RAISE_EVENT(USB_VBUSChange);
+
+ if (USB_VBUS_GetStatus())
+ {
+ RAISE_EVENT(USB_VBUSConnect);
+
+ if (USB_IsConnected)
+ RAISE_EVENT(USB_Disconnect);
+
+ USB_ResetInterface();
+
+ USB_IsConnected = true;
+
+ RAISE_EVENT(USB_Connect);
+ }
+ else
+ {
+ RAISE_EVENT(USB_Disconnect);
+
+ USB_Detach();
+ USB_CLK_Freeze();
+ USB_PLL_Off();
+ USB_REG_Off();
+
+ USB_IsConnected = false;
+
+ RAISE_EVENT(USB_VBUSDisconnect);
+
+ USB_INT_Clear(USB_INT_VBUS);
+ }
+ }
+ #endif
+
+ if (USB_INT_HasOccurred(USB_INT_SUSPEND) && USB_INT_IsEnabled(USB_INT_SUSPEND))
+ {
+ USB_INT_Clear(USB_INT_SUSPEND);
+
+ USB_INT_Disable(USB_INT_SUSPEND);
+ USB_INT_Enable(USB_INT_WAKEUP);
+
+ USB_CLK_Freeze();
+
+ if (!(USB_Options & USB_OPT_MANUAL_PLL))
+ USB_PLL_Off();
+
+ USB_IsSuspended = true;
+
+ RAISE_EVENT(USB_Suspend);
+
+ #if defined(USB_LIMITED_CONTROLLER) && !defined(NO_LIMITED_CONTROLLER_CONNECT)
+ if (USB_IsConnected)
+ {
+ USB_IsConnected = false;
+ RAISE_EVENT(USB_Disconnect);
+ }
+ #endif
+ }
+
+ if (USB_INT_HasOccurred(USB_INT_WAKEUP) && USB_INT_IsEnabled(USB_INT_WAKEUP))
+ {
+ if (!(USB_Options & USB_OPT_MANUAL_PLL))
+ {
+ USB_PLL_On();
+ while (!(USB_PLL_IsReady()));
+ }
+
+ USB_CLK_Unfreeze();
+
+ USB_INT_Clear(USB_INT_WAKEUP);
+
+ USB_INT_Disable(USB_INT_WAKEUP);
+ USB_INT_Enable(USB_INT_SUSPEND);
+
+ #if defined(USB_LIMITED_CONTROLLER) && !defined(NO_LIMITED_CONTROLLER_CONNECT)
+ if (!(USB_IsConnected))
+ {
+ USB_IsConnected = true;
+ RAISE_EVENT(USB_Connect);
+ }
+ #endif
+
+ USB_IsSuspended = false;
+
+ RAISE_EVENT(USB_WakeUp);
+ }
+
+ if (USB_INT_HasOccurred(USB_INT_EORSTI) && USB_INT_IsEnabled(USB_INT_EORSTI))
+ {
+ USB_INT_Clear(USB_INT_EORSTI);
+
+ USB_ConfigurationNumber = 0;
+
+ USB_INT_Clear(USB_INT_SUSPEND);
+ USB_INT_Disable(USB_INT_SUSPEND);
+ USB_INT_Enable(USB_INT_WAKEUP);
+
+ Endpoint_ClearEndpoints();
+
+ Endpoint_ConfigureEndpoint(ENDPOINT_CONTROLEP, EP_TYPE_CONTROL,
+ ENDPOINT_DIR_OUT, USB_ControlEndpointSize,
+ ENDPOINT_BANK_SINGLE);
+
+ RAISE_EVENT(USB_Reset);
+ }
+ #endif
+
+ #if defined(USB_CAN_BE_HOST)
+ if (USB_INT_HasOccurred(USB_INT_DDISCI) && USB_INT_IsEnabled(USB_INT_DDISCI))
+ {
+ USB_INT_Clear(USB_INT_DDISCI);
+ USB_INT_Clear(USB_INT_DCONNI);
+ USB_INT_Disable(USB_INT_DDISCI);
+
+ RAISE_EVENT(USB_DeviceUnattached);
+ RAISE_EVENT(USB_Disconnect);
+
+ USB_ResetInterface();
+ }
+
+ if (USB_INT_HasOccurred(USB_INT_VBERRI) && USB_INT_IsEnabled(USB_INT_VBERRI))
+ {
+ USB_INT_Clear(USB_INT_VBERRI);
+
+ USB_Host_VBUS_Manual_Off();
+ USB_Host_VBUS_Auto_Off();
+
+ RAISE_EVENT(USB_HostError, HOST_ERROR_VBusVoltageDip);
+ RAISE_EVENT(USB_DeviceUnattached);
+
+ USB_HostState = HOST_STATE_Unattached;
+ }
+
+ if (USB_INT_HasOccurred(USB_INT_SRPI) && USB_INT_IsEnabled(USB_INT_SRPI))
+ {
+ USB_INT_Clear(USB_INT_SRPI);
+ USB_INT_Disable(USB_INT_SRPI);
+
+ RAISE_EVENT(USB_DeviceAttached);
+
+ USB_INT_Enable(USB_INT_DDISCI);
+
+ USB_HostState = HOST_STATE_Attached;
+ }
+
+ if (USB_INT_HasOccurred(USB_INT_BCERRI) && USB_INT_IsEnabled(USB_INT_BCERRI))
+ {
+ USB_INT_Clear(USB_INT_BCERRI);
+
+ RAISE_EVENT(USB_DeviceEnumerationFailed, HOST_ENUMERROR_NoDeviceDetected, 0);
+ RAISE_EVENT(USB_DeviceUnattached);
+
+ if (USB_IsConnected)
+ RAISE_EVENT(USB_Disconnect);
+
+ USB_ResetInterface();
+ }
+ #endif
+
+ #if defined(USB_CAN_BE_BOTH)
+ if (USB_INT_HasOccurred(USB_INT_IDTI) && USB_INT_IsEnabled(USB_INT_IDTI))
+ {
+ USB_INT_Clear(USB_INT_IDTI);
+
+ if (USB_IsConnected)
+ {
+ if (USB_CurrentMode == USB_MODE_HOST)
+ RAISE_EVENT(USB_DeviceUnattached);
+ else
+ RAISE_EVENT(USB_Disconnect);
+ }
+
+ RAISE_EVENT(USB_UIDChange);
+
+ USB_ResetInterface();
+ }
+ #endif
+}
diff --git a/LUFA/Drivers/USB/HighLevel/USBInterrupt.h b/LUFA/Drivers/USB/HighLevel/USBInterrupt.h new file mode 100644 index 000000000..8438a589e --- /dev/null +++ b/LUFA/Drivers/USB/HighLevel/USBInterrupt.h @@ -0,0 +1,224 @@ +/*
+ 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
+ *
+ * Main USB interrupt vector handler. This file manages the main USB interrupt vector, for handling such
+ * events as VBUS interrupts (on supported USB AVR models), device connections and disconnections, etc.
+ */
+
+#ifndef __USBINTERRUPT_H__
+#define __USBINTERRUPT_H__
+
+ /* Includes: */
+ #include <avr/io.h>
+ #include <stdbool.h>
+
+ #include "../../../Common/Common.h"
+ #include "../LowLevel/LowLevel.h"
+ #include "../LowLevel/USBMode.h"
+ #include "Events.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Vector name for the common endpoint and pipe vector. This can be used to write an ISR handler
+ * for the endpoint and pipe events, to make certain USB functions interrupt rather than poll
+ * driven.
+ */
+ #define ENDPOINT_PIPE_vect USB_COM_vect
+
+ /** Enables the given USB interrupt vector (such as the ENDPOINT_INT_* and PIPE_INT_* vectors in
+ * Endpoint.h and Pipe.h).
+ */
+ #define USB_INT_Enable(int) MACROS{ USB_INT_GET_EN_REG(int) |= USB_INT_GET_EN_MASK(int); }MACROE
+
+ /** Disables the given USB interrupt vector.
+ *
+ * \see USB_INT_Enable()
+ */
+ #define USB_INT_Disable(int) MACROS{ USB_INT_GET_EN_REG(int) &= ~(USB_INT_GET_EN_MASK(int)); }MACROE
+
+ /** Resets the given USB interrupt flag, so that the interrupt is re-primed for the next firing. */
+ #define USB_INT_Clear(int) MACROS{ USB_INT_GET_INT_REG(int) &= ~(USB_INT_GET_INT_MASK(int)); }MACROE
+
+ /** Returns boolean false if the given USB interrupt is disabled, or true if the interrupt is currently
+ * enabled.
+ */
+ #define USB_INT_IsEnabled(int) ((USB_INT_GET_EN_REG(int) & USB_INT_GET_EN_MASK(int)) ? true : false)
+
+ /** Returns boolean true if the given interrupt flag is set (i.e. the condition for the interrupt has occurred,
+ * but the interrupt vector is not neccesarily enabled), otherwise returns false.
+ */
+ #define USB_INT_HasOccurred(int) ((USB_INT_GET_INT_REG(int) & USB_INT_GET_INT_MASK(int)) ? true : false)
+
+ /* Throwable Events: */
+ /** This module raises the USB Connected interrupt when the AVR is attached to a host while in device
+ * USB mode.
+ *
+ * \note For the smaller USB AVRs (AT90USBXX2) with limited USB controllers, VBUS is not available to the USB controller.
+ * this means that the current connection state is derived from the bus suspension and wake up events by default,
+ * which is not always accurate (host may suspend the bus while still connected). If the actual connection state
+ * needs to be determined, VBUS should be routed to an external pin, and the auto-detect behaviour turned off by
+ * passing the NO_LIMITED_CONTROLLER_CONNECT token to the compiler via the -D switch at compile time. The connection
+ * and disconnection events may be manually fired by RAISE_EVENT(), and the USB_IsConnected global changed manually.
+ */
+ RAISES_EVENT(USB_Connect);
+
+ /** This module raises the USB Disconnected interrupt when the AVR is removed from a host while in
+ * device USB mode.
+ *
+ * \note For the smaller USB AVRs (AT90USBXX2) with limited USB controllers, VBUS is not available to the USB controller.
+ * this means that the current connection state is derived from the bus suspension and wake up events by default,
+ * which is not always accurate (host may suspend the bus while still connected). If the actual connection state
+ * needs to be determined, VBUS should be routed to an external pin, and the auto-detect behaviour turned off by
+ * passing the NO_LIMITED_CONTROLLER_CONNECT token to the compiler via the -D switch at compile time. The connection
+ * and disconnection events may be manually fired by RAISE_EVENT(), and the USB_IsConnected global changed manually.
+ */
+ RAISES_EVENT(USB_Disconnect);
+
+ #if defined(USB_FULL_CONTROLLER) || defined(USB_MODIFIED_FULL_CONTROLLER) || defined(__DOXYGEN__)
+ /** This module raises the VBUS Change event when the current VBUS status (present or not present) has
+ * changed.
+ *
+ * \note Not all USB AVR models support VBUS interrupts; this event only exists on supported AVRs.
+ *
+ * \see Events.h for more information on this event.
+ */
+ RAISES_EVENT(USB_VBUSChange);
+
+ /** This module raises the VBUS Connect event when the VBUS line is powered.
+ *
+ * \note Not all USB AVR models support VBUS interrupts; this event only exists on supported AVRs.
+ *
+ * \see Events.h for more information on this event.
+ */
+ RAISES_EVENT(USB_VBUSConnect);
+
+ /** This module raises the VBUS Disconnect event when power is removed from the VBUS line.
+ *
+ * \note Not all USB AVR models support VBUS interrupts; this event only exists on supported AVRs.
+ *
+ * \see Events.h for more information on this event.
+ */
+ RAISES_EVENT(USB_VBUSDisconnect);
+ #endif
+
+ #if defined(USB_CAN_BE_DEVICE) || defined(__DOXYGEN__)
+ /** This module raises the Suspended event when the host suspends the USB interface of the AVR
+ * whilst running in device mode.
+ *
+ * \see Events.h for more information on this event.
+ */
+ RAISES_EVENT(USB_Suspend);
+
+ /** This module raises the Wake Up event when the host resumes the USB interface of the AVR
+ * whilst running in device mode.
+ *
+ * \see Events.h for more information on this event.
+ */
+ RAISES_EVENT(USB_WakeUp);
+
+ /** This module raises the USB Reset event when the host resets the USB interface of the AVR
+ * whilst running in device mode.
+ *
+ * \see Events.h for more information on this event.
+ */
+ RAISES_EVENT(USB_Reset);
+ #endif
+
+ #if defined(USB_CAN_BE_HOST) || defined(__DOXYGEN__)
+ /** This module raises the Host Error event when the VBUS line voltage dips below the minimum threshold
+ * while running in host mode.
+ *
+ * \note Not all USB AVR models support host mode; this event only exists on supported AVRs.
+ *
+ * \see Events.h for more information on this event.
+ */
+ RAISES_EVENT(USB_HostError);
+
+ /** This module raises the Device Unattached event when an attached device is removed from the AVR whilst
+ * running in host mode.
+ *
+ * \note Not all USB AVR models support host mode; this event only exists on supported AVRs.
+ *
+ * \see Events.h for more information on this event.
+ */
+ RAISES_EVENT(USB_DeviceUnattached);
+ #endif
+
+ #if defined(USB_CAN_BE_BOTH) || defined(__DOXYGEN__)
+ /** This module raises the UID Change event when the UID line changes in value on dual-role devices.
+ *
+ * \note Not all USB AVR models support host mode and thus the UID pin; this event only exists on
+ * supported AVRs.
+ *
+ * \see Events.h for more information on this event.
+ */
+ RAISES_EVENT(USB_UIDChange);
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define USB_INT_GET_EN_REG(a, b, c, d) a
+ #define USB_INT_GET_EN_MASK(a, b, c, d) b
+ #define USB_INT_GET_INT_REG(a, b, c, d) c
+ #define USB_INT_GET_INT_MASK(a, b, c, d) d
+
+ #define USB_INT_VBUS USBCON, (1 << VBUSTE) , USBINT, (1 << VBUSTI)
+ #define USB_INT_IDTI USBCON, (1 << IDTE) , USBINT, (1 << IDTI)
+ #define USB_INT_WAKEUP UDIEN , (1 << WAKEUPE), UDINT , (1 << WAKEUPI)
+ #define USB_INT_SUSPEND UDIEN , (1 << SUSPE) , UDINT , (1 << SUSPI)
+ #define USB_INT_EORSTI UDIEN , (1 << EORSTE) , UDINT , (1 << EORSTI)
+ #define USB_INT_DCONNI UHIEN , (1 << DCONNE) , UHINT , (1 << DCONNI)
+ #define USB_INT_DDISCI UHIEN , (1 << DDISCE) , UHINT , (1 << DDISCI)
+ #define USB_INT_BCERRI OTGIEN, (1 << BCERRE) , OTGINT, (1 << BCERRI)
+ #define USB_INT_VBERRI OTGIEN, (1 << VBERRE) , OTGINT, (1 << VBERRI)
+ #define USB_INT_SOFI UDIEN, (1 << SOFE) , UDINT , (1 << SOFI)
+ #define USB_INT_HSOFI UHIEN, (1 << HSOFE) , UHINT , (1 << HSOFI)
+ #define USB_INT_RSTI UHIEN , (1 << RSTE) , UHINT , (1 << RSTI)
+ #define USB_INT_SRPI OTGIEN, (1 << SRPE) , OTGINT, (1 << SRPI)
+
+ /* Function Prototypes: */
+ void USB_INT_ClearAllInterrupts(void);
+ void USB_INT_DisableAllInterrupts(void);
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
diff --git a/LUFA/Drivers/USB/HighLevel/USBTask.c b/LUFA/Drivers/USB/HighLevel/USBTask.c new file mode 100644 index 000000000..69670232b --- /dev/null +++ b/LUFA/Drivers/USB/HighLevel/USBTask.c @@ -0,0 +1,253 @@ +/*
+ 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 "../LowLevel/USBMode.h"
+
+#define INCLUDE_FROM_USBTASK_C
+#include "USBTask.h"
+
+volatile bool USB_IsSuspended;
+volatile bool USB_IsConnected;
+volatile bool USB_IsInitialized;
+
+#if defined(USB_CAN_BE_HOST)
+volatile uint8_t USB_HostState;
+#endif
+
+TASK(USB_USBTask)
+{
+ #if defined(USB_HOST_ONLY)
+ USB_HostTask();
+ #elif defined(USB_DEVICE_ONLY)
+ USB_DeviceTask();
+ #else
+ if (USB_CurrentMode == USB_MODE_DEVICE)
+ USB_DeviceTask();
+ else if (USB_CurrentMode == USB_MODE_HOST)
+ USB_HostTask();
+ #endif
+}
+
+#if defined(USB_CAN_BE_DEVICE)
+static void USB_DeviceTask(void)
+{
+ if (USB_IsConnected)
+ {
+ uint8_t PrevEndpoint = Endpoint_GetCurrentEndpoint();
+
+ Endpoint_SelectEndpoint(ENDPOINT_CONTROLEP);
+
+ if (Endpoint_IsSetupReceived())
+ {
+ ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
+ {
+ USB_Device_ProcessControlPacket();
+ }
+ }
+
+ Endpoint_SelectEndpoint(PrevEndpoint);
+ }
+}
+#endif
+
+#if defined(USB_CAN_BE_HOST)
+static void USB_HostTask(void)
+{
+ uint8_t ErrorCode = HOST_ENUMERROR_NoError;
+ uint8_t SubErrorCode = HOST_ENUMERROR_NoError;
+
+ static uint16_t WaitMSRemaining;
+ static uint8_t PostWaitState;
+
+ switch (USB_HostState)
+ {
+ case HOST_STATE_WaitForDevice:
+ if (WaitMSRemaining)
+ {
+ if ((SubErrorCode = USB_Host_WaitMS(1)) != HOST_WAITERROR_Successful)
+ {
+ USB_HostState = PostWaitState;
+ ErrorCode = HOST_ENUMERROR_WaitStage;
+ break;
+ }
+
+ WaitMSRemaining--;
+ }
+ else
+ {
+ USB_HostState = PostWaitState;
+ }
+
+ break;
+ case HOST_STATE_Attached:
+ WaitMSRemaining = HOST_DEVICE_SETTLE_DELAY_MS;
+
+ USB_HostState = HOST_STATE_Attached_WaitForDeviceSettle;
+ break;
+ case HOST_STATE_Attached_WaitForDeviceSettle:
+ _delay_ms(1);
+
+ if (!(WaitMSRemaining--))
+ {
+ USB_Host_VBUS_Manual_Off();
+
+ USB_OTGPAD_On();
+ USB_Host_VBUS_Auto_Enable();
+ USB_Host_VBUS_Auto_On();
+
+ USB_HostState = HOST_STATE_Attached_WaitForConnect;
+ }
+
+ break;
+ case HOST_STATE_Attached_WaitForConnect:
+ if (USB_INT_HasOccurred(USB_INT_DCONNI))
+ {
+ USB_INT_Clear(USB_INT_DCONNI);
+ USB_INT_Clear(USB_INT_DDISCI);
+
+ USB_INT_Clear(USB_INT_VBERRI);
+ USB_INT_Enable(USB_INT_VBERRI);
+
+ USB_IsConnected = true;
+ RAISE_EVENT(USB_Connect);
+
+ USB_Host_ResumeBus();
+ Pipe_ClearPipes();
+
+ HOST_TASK_NONBLOCK_WAIT(100, HOST_STATE_Attached_DoReset);
+ }
+
+ break;
+ case HOST_STATE_Attached_DoReset:
+ USB_Host_ResetDevice();
+
+ HOST_TASK_NONBLOCK_WAIT(200, HOST_STATE_Powered);
+ break;
+ case HOST_STATE_Powered:
+ Pipe_ConfigurePipe(PIPE_CONTROLPIPE, EP_TYPE_CONTROL,
+ PIPE_TOKEN_SETUP, PIPE_CONTROLPIPE,
+ PIPE_CONTROLPIPE_DEFAULT_SIZE, PIPE_BANK_SINGLE);
+
+ if (!(Pipe_IsConfigured()))
+ {
+ ErrorCode = HOST_ENUMERROR_PipeConfigError;
+ SubErrorCode = 0;
+ break;
+ }
+
+ USB_HostState = HOST_STATE_Default;
+ break;
+ case HOST_STATE_Default:
+ USB_HostRequest = (USB_Host_Request_Header_t)
+ {
+ bmRequestType: (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE),
+ bRequest: REQ_GetDescriptor,
+ wValue: (DTYPE_Device << 8),
+ wIndex: 0,
+ wLength: PIPE_CONTROLPIPE_DEFAULT_SIZE,
+ };
+
+ uint8_t DataBuffer[PIPE_CONTROLPIPE_DEFAULT_SIZE];
+
+ if ((SubErrorCode = USB_Host_SendControlRequest(DataBuffer)) != HOST_SENDCONTROL_Successful)
+ {
+ ErrorCode = HOST_ENUMERROR_ControlError;
+ break;
+ }
+
+ #if defined(USE_NONSTANDARD_DESCRIPTOR_NAMES)
+ USB_ControlPipeSize = DataBuffer[offsetof(USB_Descriptor_Device_t, Endpoint0Size)];
+ #else
+ USB_ControlPipeSize = DataBuffer[offsetof(USB_Descriptor_Device_t, bMaxPacketSize0)];
+ #endif
+
+ USB_Host_ResetDevice();
+
+ HOST_TASK_NONBLOCK_WAIT(200, HOST_STATE_Default_PostReset);
+ break;
+ case HOST_STATE_Default_PostReset:
+ Pipe_DisablePipe();
+ Pipe_DeallocateMemory();
+ Pipe_ResetPipe(PIPE_CONTROLPIPE);
+
+ Pipe_ConfigurePipe(PIPE_CONTROLPIPE, EP_TYPE_CONTROL,
+ PIPE_TOKEN_SETUP, PIPE_CONTROLPIPE,
+ USB_ControlPipeSize, PIPE_BANK_SINGLE);
+
+ if (!(Pipe_IsConfigured()))
+ {
+ ErrorCode = HOST_ENUMERROR_PipeConfigError;
+ SubErrorCode = 0;
+ break;
+ }
+
+ Pipe_SetInfiniteINRequests();
+
+ USB_HostRequest = (USB_Host_Request_Header_t)
+ {
+ bmRequestType: (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_DEVICE),
+ bRequest: REQ_SetAddress,
+ wValue: USB_HOST_DEVICEADDRESS,
+ wIndex: 0,
+ wLength: 0,
+ };
+
+ if ((SubErrorCode = USB_Host_SendControlRequest(NULL)) != HOST_SENDCONTROL_Successful)
+ {
+ ErrorCode = HOST_ENUMERROR_ControlError;
+ break;
+ }
+
+ HOST_TASK_NONBLOCK_WAIT(100, HOST_STATE_Default_PostAddressSet);
+ break;
+ case HOST_STATE_Default_PostAddressSet:
+ USB_Host_SetDeviceAddress(USB_HOST_DEVICEADDRESS);
+
+ RAISE_EVENT(USB_DeviceEnumerationComplete);
+ USB_HostState = HOST_STATE_Addressed;
+
+ break;
+ }
+
+ if ((ErrorCode != HOST_ENUMERROR_NoError) && (USB_HostState != HOST_STATE_Unattached))
+ {
+ RAISE_EVENT(USB_DeviceEnumerationFailed, ErrorCode, SubErrorCode);
+
+ USB_Host_VBUS_Auto_Off();
+
+ RAISE_EVENT(USB_DeviceUnattached);
+
+ if (USB_IsConnected)
+ RAISE_EVENT(USB_Disconnect);
+
+ USB_ResetInterface();
+ }
+}
+#endif
diff --git a/LUFA/Drivers/USB/HighLevel/USBTask.h b/LUFA/Drivers/USB/HighLevel/USBTask.h new file mode 100644 index 000000000..1fcc2bbb3 --- /dev/null +++ b/LUFA/Drivers/USB/HighLevel/USBTask.h @@ -0,0 +1,198 @@ +/*
+ 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
+ *
+ * Main library USB management task for both Host and Device mode operations. This contains the master
+ * USB_USBTask task which should be periodically run to service both host and device USB projects.
+ */
+
+#ifndef __USBTASK_H__
+#define __USBTASK_H__
+
+ /* Includes: */
+ #include <avr/io.h>
+ #include <avr/interrupt.h>
+ #include <util/atomic.h>
+ #include <stdbool.h>
+ #include <stddef.h>
+
+ #include "../../../Scheduler/Scheduler.h"
+ #include "../LowLevel/LowLevel.h"
+ #include "../LowLevel/HostChapter9.h"
+ #include "../LowLevel/USBMode.h"
+ #include "Events.h"
+ #include "StdDescriptors.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Global Variables: */
+ /** Indicates if the USB interface is currently connected to a host if in device mode, or to a
+ * device while running in host mode.
+ *
+ * \note This variable should be treated as read-only in the user application, and never manually
+ * changed in value.
+ *
+ * \note For the smaller USB AVRs (AT90USBXX2) with limited USB controllers, VBUS is not available to the USB controller.
+ * this means that the current connection state is derived from the bus suspension and wake up events by default,
+ * which is not always accurate (host may suspend the bus while still connected). If the actual connection state
+ * needs to be determined, VBUS should be routed to an external pin, and the auto-detect behaviour turned off by
+ * passing the NO_LIMITED_CONTROLLER_CONNECT token to the compiler via the -D switch at compile time. The connection
+ * and disconnection events may be manually fired by RAISE_EVENT(), and the USB_IsConnected global changed manually.
+ */
+ extern volatile bool USB_IsConnected;
+
+ /** Indicates if the USB interface is currently initialized but not neccesarily connected to a host
+ * or device (i.e. if USB_Init() has been run). If this is false, all other library globals are invalid.
+ *
+ * \note This variable should be treated as read-only in the user application, and never manually
+ * changed in value.
+ */
+ extern volatile bool USB_IsInitialized;
+
+ #if defined(USB_CAN_BE_DEVICE) || defined(__DOXYGEN__)
+ /** Indicates if the USB interface is currently suspended by the host when in device mode. When suspended,
+ * the device should consume minimal power, and cannot communicate to the host. If Remote Wakeup is
+ * supported by the device and USB_RemoteWakeupEnabled is true, suspension can be terminated by the device
+ * by issuing a Remote Wakup request.
+ *
+ * \note This global is only present if the user application can be a USB device.
+ *
+ * \note This variable should be treated as read-only in the user application, and never manually
+ * changed in value.
+ */
+ extern volatile bool USB_IsSuspended;
+ #endif
+
+ #if defined(USB_CAN_BE_HOST) || defined(__DOXYGEN__)
+ /** Indicates the current host state machine state. When in host mode, this indicates the state
+ * via one of the values of the USB_Host_States_t enum values in Host.h.
+ *
+ * This value may be altered by the user application to implement the HOST_STATE_Addressed,
+ * HOST_STATE_Configured, HOST_STATE_Ready and HOST_STATE_Suspended states which are not implemented
+ * by the library.
+ *
+ * \note This global is only present if the user application can be a USB host.
+ */
+ extern volatile uint8_t USB_HostState;
+ #endif
+
+ /* Throwable Events: */
+ #if defined(USB_CAN_BE_HOST) || defined(__DOXYGEN__)
+ /** This module raises the USB Connect event when a USB device has been connected whilst in host
+ * mode, but not yet enumerated.
+ *
+ * \see Events.h for more information on this event.
+ */
+ RAISES_EVENT(USB_Connect);
+
+ /** This module raises the USB Device Attached event when in host mode, and a device is attached
+ * to the AVR's USB interface.
+ *
+ * \see Events.h for more information on this event.
+ */
+ RAISES_EVENT(USB_DeviceAttached);
+
+ /** This module raises the USB Device Unattached event when in host mode, and a device is removed
+ * from the AVR's USB interface.
+ *
+ * \see Events.h for more information on this event.
+ */
+ RAISES_EVENT(USB_DeviceUnattached);
+
+ /** This module raises the USB Device Enumeration Failed event when in host mode, and an
+ * attached USB device has failed to successfully enumerated.
+ *
+ * \see Events.h for more information on this event.
+ */
+ RAISES_EVENT(USB_DeviceEnumerationFailed);
+
+ /** This module raises the USB Device Enumeration Complete event when in host mode, and an
+ * attached USB device has been successfully enumerated and ready to be used by the user
+ * application.
+ *
+ * \see Events.h for more information on this event.
+ */
+ RAISES_EVENT(USB_DeviceEnumerationComplete);
+
+ /** This module raises the USB Disconnect event when an attached USB device is removed from the USB
+ * bus.
+ *
+ * \see Events.h for more information on this event.
+ */
+ RAISES_EVENT(USB_Disconnect);
+ #endif
+
+ /* Tasks: */
+ /** This is the main USB management task. The USB driver requires that this task be executed
+ * continuously when the USB system is active (device attached in host mode, or attached to a host
+ * in device mode) in order to manage USB communications. This task may be executed inside an RTOS,
+ * scheduler (e.g. the simple LUFA Scheduler), fast timer ISR or the main user application loop.
+ *
+ * The USB task must be serviced within 50mS in all modes, when needed. The task may be serviced
+ * at all times, or (for minimum CPU consumption):
+ *
+ * - In device mode, it may be disabled at startup, enabled on the firing of the USB_Connect event
+ * and disabled again on the firing of the USB_Disconnect event.
+ *
+ * - In host mode, it may be disabled at startup, enabled on the firing of the USB_DeviceAttached
+ * event and disabled again on the firing of the USB_DeviceUnattached event.
+ *
+ * \see Events.h for more information on the USB events.
+ */
+ TASK(USB_USBTask);
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Function Prototypes: */
+ #if defined(INCLUDE_FROM_USBTASK_C)
+ #if defined(USB_CAN_BE_HOST)
+ static void USB_HostTask(void);
+ #endif
+
+ #if defined(USB_CAN_BE_DEVICE)
+ static void USB_DeviceTask(void);
+ #endif
+ #endif
+
+ /* Macros: */
+ #define HOST_TASK_NONBLOCK_WAIT(duration, nextstate) {USB_HostState = HOST_STATE_WaitForDevice; WaitMSRemaining = duration; PostWaitState = nextstate; }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
diff --git a/LUFA/Drivers/USB/LowLevel/DevChapter9.c b/LUFA/Drivers/USB/LowLevel/DevChapter9.c new file mode 100644 index 000000000..9ea3f417c --- /dev/null +++ b/LUFA/Drivers/USB/LowLevel/DevChapter9.c @@ -0,0 +1,313 @@ +/*
+ 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 "USBMode.h"
+#if defined(USB_CAN_BE_DEVICE)
+
+#define INCLUDE_FROM_DEVCHAPTER9_C
+#include "DevChapter9.h"
+
+uint8_t USB_ConfigurationNumber;
+bool USB_RemoteWakeupEnabled;
+bool USB_CurrentlySelfPowered;
+
+void USB_Device_ProcessControlPacket(void)
+{
+ uint8_t bmRequestType = Endpoint_Read_Byte();
+ uint8_t bRequest = Endpoint_Read_Byte();
+ bool RequestHandled = false;
+
+ switch (bRequest)
+ {
+ case REQ_GetStatus:
+ if ((bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE)) ||
+ (bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_ENDPOINT)))
+ {
+ USB_Device_GetStatus(bmRequestType);
+ RequestHandled = true;
+ }
+
+ break;
+#if !defined(NO_CLEARSET_FEATURE_REQUEST)
+ case REQ_ClearFeature:
+ case REQ_SetFeature:
+ if (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_ENDPOINT))
+ {
+ USB_Device_ClearSetFeature(bRequest, bmRequestType);
+ RequestHandled = true;
+ }
+
+ break;
+#endif
+ case REQ_SetAddress:
+ if (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_DEVICE))
+ {
+ USB_Device_SetAddress();
+ RequestHandled = true;
+ }
+
+ break;
+ case REQ_GetDescriptor:
+ if ((bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE)) ||
+ (bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_INTERFACE)))
+ {
+ USB_Device_GetDescriptor();
+ RequestHandled = true;
+ }
+
+ break;
+ case REQ_GetConfiguration:
+ if (bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE))
+ {
+ USB_Device_GetConfiguration();
+ RequestHandled = true;
+ }
+
+ break;
+ case REQ_SetConfiguration:
+ if (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_DEVICE))
+ {
+ USB_Device_SetConfiguration();
+ RequestHandled = true;
+ }
+
+ break;
+ }
+
+ if (!(RequestHandled))
+ RAISE_EVENT(USB_UnhandledControlPacket, bRequest, bmRequestType);
+
+ if (Endpoint_IsSetupReceived())
+ {
+ Endpoint_StallTransaction();
+ Endpoint_ClearSetupReceived();
+ }
+}
+
+static void USB_Device_SetAddress(void)
+{
+ uint8_t wValue_LSB = Endpoint_Read_Byte();
+
+ Endpoint_ClearSetupReceived();
+
+ while (!(Endpoint_IsSetupINReady()));
+
+ Endpoint_ClearSetupIN();
+
+ while (!(Endpoint_IsSetupINReady()));
+
+ UDADDR = ((1 << ADDEN) | (wValue_LSB & 0x7F));
+
+ return;
+}
+
+static void USB_Device_SetConfiguration(void)
+{
+ uint8_t wValue_LSB = Endpoint_Read_Byte();
+ bool AlreadyConfigured = (USB_ConfigurationNumber != 0);
+
+#if defined(USE_SINGLE_DEVICE_CONFIGURATION)
+ if (wValue_LSB > 1)
+#else
+ USB_Descriptor_Device_t* DevDescriptorPtr;
+
+ if ((USB_GetDescriptor((DTYPE_Device << 8), 0, (void*)&DevDescriptorPtr) == NO_DESCRIPTOR) ||
+ #if defined(USE_RAM_DESCRIPTORS)
+ (wValue_LSB > DevDescriptorPtr->NumberOfConfigurations))
+ #elif defined (USE_EEPROM_DESCRIPTORS)
+ (wValue_LSB > eeprom_read_byte(&DevDescriptorPtr->NumberOfConfigurations)))
+ #else
+ (wValue_LSB > pgm_read_byte(&DevDescriptorPtr->NumberOfConfigurations)))
+ #endif
+#endif
+ {
+ return;
+ }
+
+ Endpoint_ClearSetupReceived();
+
+ USB_ConfigurationNumber = wValue_LSB;
+
+ Endpoint_ClearSetupIN();
+
+ if (!(AlreadyConfigured) && USB_ConfigurationNumber)
+ RAISE_EVENT(USB_DeviceEnumerationComplete);
+
+ RAISE_EVENT(USB_ConfigurationChanged);
+}
+
+void USB_Device_GetConfiguration(void)
+{
+ Endpoint_ClearSetupReceived();
+
+ Endpoint_Write_Byte(USB_ConfigurationNumber);
+
+ Endpoint_ClearSetupIN();
+
+ while (!(Endpoint_IsSetupOUTReceived()));
+ Endpoint_ClearSetupOUT();
+}
+
+static void USB_Device_GetDescriptor(void)
+{
+ uint16_t wValue = Endpoint_Read_Word_LE();
+ uint16_t wIndex = Endpoint_Read_Word_LE();
+ uint16_t wLength = Endpoint_Read_Word_LE();
+
+ void* DescriptorPointer;
+ uint16_t DescriptorSize;
+
+ bool SendZLP;
+
+ if ((DescriptorSize = USB_GetDescriptor(wValue, wIndex, &DescriptorPointer)) == NO_DESCRIPTOR)
+ return;
+
+ Endpoint_ClearSetupReceived();
+
+ if (wLength > DescriptorSize)
+ wLength = DescriptorSize;
+
+ while (wLength)
+ {
+ while (!(Endpoint_IsSetupINReady()))
+ {
+ if (Endpoint_IsSetupOUTReceived())
+ {
+ Endpoint_ClearSetupOUT();
+ return;
+ }
+ }
+
+ while (wLength && (Endpoint_BytesInEndpoint() < USB_ControlEndpointSize))
+ {
+ #if defined(USE_RAM_DESCRIPTORS)
+ Endpoint_Write_Byte(*((uint8_t*)DescriptorPointer++));
+ #elif defined (USE_EEPROM_DESCRIPTORS)
+ Endpoint_Write_Byte(eeprom_read_byte(DescriptorPointer++));
+ #else
+ Endpoint_Write_Byte(pgm_read_byte(DescriptorPointer++));
+ #endif
+
+ wLength--;
+ }
+
+ SendZLP = (Endpoint_BytesInEndpoint() == USB_ControlEndpointSize);
+ Endpoint_ClearSetupIN();
+ }
+
+ if (SendZLP)
+ {
+ while (!(Endpoint_IsSetupINReady()));
+ Endpoint_ClearSetupIN();
+ }
+
+ while (!(Endpoint_IsSetupOUTReceived()));
+ Endpoint_ClearSetupOUT();
+}
+
+static void USB_Device_GetStatus(const uint8_t bmRequestType)
+{
+ uint8_t CurrentStatus = 0;
+
+ Endpoint_Discard_Word();
+
+ uint8_t wIndex_LSB = Endpoint_Read_Byte();
+
+ switch (bmRequestType)
+ {
+ case (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE):
+ if (USB_CurrentlySelfPowered)
+ CurrentStatus |= FEATURE_SELFPOWERED_ENABLED;
+
+ if (USB_RemoteWakeupEnabled)
+ CurrentStatus |= FEATURE_REMOTE_WAKEUP_ENABLED;
+
+ break;
+ case (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_ENDPOINT):
+ Endpoint_SelectEndpoint(wIndex_LSB);
+
+ CurrentStatus = Endpoint_IsStalled();
+
+ break;
+ }
+
+ Endpoint_SelectEndpoint(ENDPOINT_CONTROLEP);
+ Endpoint_ClearSetupReceived();
+ Endpoint_Write_Word_LE(CurrentStatus);
+
+ Endpoint_ClearSetupIN();
+
+ while (!(Endpoint_IsSetupOUTReceived()));
+ Endpoint_ClearSetupOUT();
+}
+
+#if !defined(NO_CLEARSET_FEATURE_REQUEST)
+static void USB_Device_ClearSetFeature(const uint8_t bRequest, const uint8_t bmRequestType)
+{
+ uint16_t wValue = Endpoint_Read_Word_LE();
+ uint16_t wIndex = Endpoint_Read_Word_LE();
+
+ switch (bmRequestType & CONTROL_REQTYPE_RECIPIENT)
+ {
+ case REQREC_ENDPOINT:
+ if (wValue == FEATURE_ENDPOINT_HALT)
+ {
+ uint8_t EndpointIndex = (wIndex & ENDPOINT_EPNUM_MASK);
+
+ if (EndpointIndex != ENDPOINT_CONTROLEP)
+ {
+ Endpoint_SelectEndpoint(EndpointIndex);
+
+ if (Endpoint_IsEnabled())
+ {
+ if (bRequest == REQ_ClearFeature)
+ {
+ Endpoint_ClearStall();
+ Endpoint_ResetFIFO(EndpointIndex);
+ Endpoint_ResetDataToggle();
+ }
+ else
+ {
+ Endpoint_StallTransaction();
+ }
+ }
+
+ Endpoint_SelectEndpoint(ENDPOINT_CONTROLEP);
+ Endpoint_ClearSetupReceived();
+ Endpoint_ClearSetupIN();
+ }
+ }
+
+ break;
+ }
+}
+#endif
+
+#endif
diff --git a/LUFA/Drivers/USB/LowLevel/DevChapter9.h b/LUFA/Drivers/USB/LowLevel/DevChapter9.h new file mode 100644 index 000000000..5e1772a53 --- /dev/null +++ b/LUFA/Drivers/USB/LowLevel/DevChapter9.h @@ -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.
+*/
+
+/** \file
+ *
+ * Module for device mode request processing. This module allows for the processing of standard control
+ * requests to the default control endpoint while in device mode.
+ *
+ * \see Chapter 9 of the USB 2.0 specification.
+ */
+
+#ifndef __DEVCHAPTER9_H__
+#define __DEVCHAPTER9_H__
+
+ /* Includes: */
+ #include <avr/io.h>
+ #include <avr/pgmspace.h>
+ #include <avr/eeprom.h>
+
+ #include "../HighLevel/StdDescriptors.h"
+ #include "../HighLevel/Events.h"
+ #include "LowLevel.h"
+ #include "StdRequestType.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Global Variables: */
+ /** Indicates the currently set configuration number of the device. USB devices may have several
+ * different configurations which the host can select between; this indicates the currently selected
+ * value, or 0 if no configuration has been selected.
+ *
+ * If a device has only one single configuration, the token USE_SINGLE_DEVICE_CONFIGURATION may be
+ * defined in the project makefile and passed to the compiler using the -D switch. This optimize for
+ * a single configuration, saving a small amount of space in the resulting compiled binary.
+ *
+ * \note This variable should be treated as read-only in the user application, and never manually
+ * changed in value.
+ */
+ extern uint8_t USB_ConfigurationNumber;
+
+ /** Indicates if the host is currently allowing the device to issue remote wakeup events. If this
+ * flag is cleared, the device should not issue remote wakeup events to the host.
+ *
+ * \note This variable should be treated as read-only in the user application, and never manually
+ * changed in value.
+ */
+ extern bool USB_RemoteWakeupEnabled;
+
+ /** Indicates if the device is currently being powered by its own power supply, rather than being
+ * powered by the host's USB supply. This flag should remain cleared if the device does not
+ * support self powered mode, as indicated in the device descriptors.
+ */
+ extern bool USB_CurrentlySelfPowered;
+
+ /* Throwable Events: */
+ /** This module raises the USB_UnhandledControlPacket event when a request to the default control
+ * endpoint has been received, but the library does not implement an internal handler for it.
+ *
+ * \see Events.h for more information on this event.
+ */
+ RAISES_EVENT(USB_UnhandledControlPacket);
+
+ /** This module raises the USB_ConfigurationChanged event when the host issues a REQ_SetConfiguration
+ * device request, to change the currently selected configuration number.
+ *
+ * \see Events.h for more information on this event.
+ */
+ RAISES_EVENT(USB_ConfigurationChanged);
+
+ /** This module raises the USB_DeviceEnumerationComplete event when the host has completed its
+ * enumeration of the device (i.e. when a REQ_SetConfiguration request changes the current configuration
+ * number from 0 to a non-zero value).
+ *
+ * \see Events.h for more information on this event.
+ */
+ RAISES_EVENT(USB_DeviceEnumerationComplete);
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ #if defined(USE_RAM_DESCRIPTORS) && defined(USE_EEPROM_DESCRIPTORS)
+ #error USE_RAM_DESCRIPTORS and USE_EEPROM_DESCRIPTORS are mutually exclusive.
+ #endif
+
+ /* Function Prototypes: */
+ void USB_Device_ProcessControlPacket(void);
+
+ #if defined(INCLUDE_FROM_DEVCHAPTER9_C)
+ static void USB_Device_SetAddress(void);
+ static void USB_Device_SetConfiguration(void);
+ static void USB_Device_GetConfiguration(void);
+ static void USB_Device_GetDescriptor(void);
+ static void USB_Device_GetStatus(const uint8_t bmRequestType);
+ #if !defined(NO_CLEARSET_FEATURE_REQUEST)
+ static void USB_Device_ClearSetFeature(const uint8_t bRequest, const uint8_t bmRequestType);
+ #endif
+ #endif
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
diff --git a/LUFA/Drivers/USB/LowLevel/Device.h b/LUFA/Drivers/USB/LowLevel/Device.h new file mode 100644 index 000000000..187fccb4a --- /dev/null +++ b/LUFA/Drivers/USB/LowLevel/Device.h @@ -0,0 +1,126 @@ +/*
+ 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 Device mode related macros and enums. This module contains macros and enums which are used when
+ * the USB controller is initialized in device mode.
+ */
+
+#ifndef __USBDEVICE_H__
+#define __USBDEVICE_H__
+
+ /* Includes: */
+ #include <avr/pgmspace.h>
+ #include <avr/eeprom.h>
+
+ #include "../../../Common/Common.h"
+ #include "../HighLevel/StdDescriptors.h"
+ #include "Endpoint.h"
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ #if defined(USB_FULL_CONTROLLER) || defined(USB_MODIFIED_FULL_CONTROLLER) || defined(__DOXYGEN__)
+ /** Mask for the Options parameter of the USB_Init() function. This indicates that the
+ * USB interface should be initialized in low speed (1.5Mb/s) mode.
+ *
+ * \note Low Speed mode is not available on all USB AVR models.
+ *
+ * \note Restrictions apply on the number, size and type of endpoints which can be used
+ * when running in low speed mode -- refer to the USB 2.0 standard.
+ */
+ #define USB_DEVICE_OPT_LOWSPEED (1 << 0)
+ #endif
+
+ /** Mask for the Options parameter of the USB_Init() function. This indicates that the
+ * USB interface should be initialized in full speed (12Mb/s) mode.
+ */
+ #define USB_DEVICE_OPT_FULLSPEED (0 << 0)
+
+ /** Sends a Remote Wakeup request to the host. This signals to the host that the device should
+ * be taken out of suspended mode, and communications should resume.
+ *
+ * Typically, this is implemented so that HID devices (mice, keyboards, etc.) can wake up the
+ * host computer when the host has suspended all USB devices to enter a low power state.
+ *
+ * \note This macro should only be used if the device has indicated to the host that it
+ * supports the Remote Wakeup feature in the device descriptors, and should only be
+ * issued if the host is currently allowing remote wakeup events from the device (i.e.,
+ * the USB_RemoteWakeupEnabled flag is set, see DevChapter9.h documentation).
+ *
+ * \see StdDescriptors.h for more information on the RMWAKEUP feature and device descriptors.
+ */
+ #define USB_Device_SendRemoteWakeup() MACROS{ UDCON |= (1 << RMWKUP); }MACROE
+
+ /** Indicates if a Remote Wakeup request is being sent to the host. This returns true if a
+ * remote wakeup is currently being sent, false otherwise.
+ *
+ * This can be used in conjunction with the USB_Device_IsUSBSuspended() macro to determine if
+ * a sent RMWAKEUP request was accepted or rejected by the host.
+ *
+ * \note This macro should only be used if the device has indicated to the host that it
+ * supports the Remote Wakeup feature in the device descriptors.
+ *
+ * \see StdDescriptors.h for more information on the RMWAKEUP feature and device descriptors.
+ */
+ #define USB_Device_IsRemoteWakeupSent() ((UDCON & (1 << RMWKUP)) ? false : true)
+
+ /** Indicates if the device is currently suspended by the host. While suspended, the device is
+ * to enter a low power state until resumed by the host. While suspended no USB traffic to or
+ * from the device can ocurr (except for Remote Wakeup requests).
+ *
+ * This macro returns true if the USB communications have been suspended by the host, false
+ * otherwise.
+ */
+ #define USB_Device_IsUSBSuspended() ((UDINT & (1 << SUSPI)) ? true : false)
+
+ /* Enums: */
+ /** Enum for the ErrorCode parameter of the USB_DeviceError event.
+ *
+ * \see Events.h for more information on this event.
+ */
+ enum USB_Device_ErrorCodes_t
+ {
+ DEVICE_ERROR_GetDescriptorNotHooked = 0, /**< Indicates that the GetDescriptor() method
+ * has not been hooked by the user application.
+ *
+ * \see StdDescriptors.h for more information on
+ * the GetDescriptor() method.
+ */
+ };
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define USB_Device_SetLowSpeed() MACROS{ UDCON |= (1 << LSM); }MACROE
+ #define USB_Device_SetHighSpeed() MACROS{ UDCON &= ~(1 << LSM); }MACROE
+ #endif
+
+#endif
diff --git a/LUFA/Drivers/USB/LowLevel/Endpoint.c b/LUFA/Drivers/USB/LowLevel/Endpoint.c new file mode 100644 index 000000000..273e1908a --- /dev/null +++ b/LUFA/Drivers/USB/LowLevel/Endpoint.c @@ -0,0 +1,387 @@ +/*
+ 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 "USBMode.h"
+#if defined(USB_CAN_BE_DEVICE)
+
+#define INCLUDE_FROM_ENDPOINT_C
+#include "Endpoint.h"
+
+#if !defined(FIXED_CONTROL_ENDPOINT_SIZE)
+uint8_t USB_ControlEndpointSize = ENDPOINT_CONTROLEP_DEFAULT_SIZE;
+#endif
+
+#if !defined(STATIC_ENDPOINT_CONFIGURATION)
+bool Endpoint_ConfigureEndpoint(const uint8_t Number, const uint8_t Type, const uint8_t Direction,
+ const uint16_t Size, const uint8_t Banks)
+{
+ Endpoint_SelectEndpoint(Number);
+ Endpoint_EnableEndpoint();
+
+ UECFG1X = 0;
+
+ UECFG0X = ((Type << EPTYPE0) | Direction);
+ UECFG1X = ((1 << ALLOC) | Banks | Endpoint_BytesToEPSizeMask(Size));
+
+ return Endpoint_IsConfigured();
+}
+#else
+bool Endpoint_ConfigureEndpointStatic(const uint8_t Number, const uint8_t UECFG0XData, const uint8_t UECFG1XData)
+{
+ Endpoint_SelectEndpoint(Number);
+ Endpoint_EnableEndpoint();
+
+ UECFG1X = 0;
+
+ UECFG0X = UECFG0XData;
+ UECFG1X = UECFG1XData;
+
+ return Endpoint_IsConfigured();
+}
+#endif
+
+void Endpoint_ClearEndpoints(void)
+{
+ UEINT = 0;
+
+ for (uint8_t EPNum = 0; EPNum < ENDPOINT_TOTAL_ENDPOINTS; EPNum++)
+ {
+ Endpoint_SelectEndpoint(EPNum);
+ UEIENX = 0;
+ UEINTX = 0;
+ Endpoint_DeallocateMemory();
+ Endpoint_DisableEndpoint();
+ }
+}
+
+uint8_t Endpoint_WaitUntilReady(void)
+{
+ uint8_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS;
+
+ USB_INT_Clear(USB_INT_SOFI);
+
+ while (!(Endpoint_ReadWriteAllowed()))
+ {
+ if (!(USB_IsConnected))
+ return ENDPOINT_READYWAIT_DeviceDisconnected;
+ else if (Endpoint_IsStalled())
+ return ENDPOINT_READYWAIT_EndpointStalled;
+
+ if (USB_INT_HasOccurred(USB_INT_SOFI))
+ {
+ USB_INT_Clear(USB_INT_SOFI);
+
+ if (!(TimeoutMSRem--))
+ return ENDPOINT_READYWAIT_Timeout;
+ }
+ }
+
+ return ENDPOINT_READYWAIT_NoError;
+}
+
+uint8_t Endpoint_Discard_Stream(uint16_t Length
+#if !defined(NO_STREAM_CALLBACKS)
+ , uint8_t (* const Callback)(void)
+#endif
+ )
+{
+ uint8_t ErrorCode;
+
+ if ((ErrorCode = Endpoint_WaitUntilReady()))
+ return ErrorCode;
+
+ while (Length--)
+ {
+ if (!(Endpoint_ReadWriteAllowed()))
+ {
+ Endpoint_ClearCurrentBank();
+
+ #if !defined(NO_STREAM_CALLBACKS)
+ if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
+ return ENDPOINT_RWSTREAM_ERROR_CallbackAborted;
+ #endif
+
+ if ((ErrorCode = Endpoint_WaitUntilReady()))
+ return ErrorCode;
+ }
+
+ Endpoint_Discard_Byte();
+ }
+
+ return ENDPOINT_RWSTREAM_ERROR_NoError;
+}
+
+uint8_t Endpoint_Write_Stream_LE(const void* Buffer, uint16_t Length
+#if !defined(NO_STREAM_CALLBACKS)
+ , uint8_t (* const Callback)(void)
+#endif
+ )
+{
+ uint8_t* DataStream = (uint8_t*)Buffer;
+ uint8_t ErrorCode;
+
+ if ((ErrorCode = Endpoint_WaitUntilReady()))
+ return ErrorCode;
+
+ while (Length--)
+ {
+ if (!(Endpoint_ReadWriteAllowed()))
+ {
+ Endpoint_ClearCurrentBank();
+
+ #if !defined(NO_STREAM_CALLBACKS)
+ if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
+ return ENDPOINT_RWSTREAM_ERROR_CallbackAborted;
+ #endif
+
+ if ((ErrorCode = Endpoint_WaitUntilReady()))
+ return ErrorCode;
+ }
+
+ Endpoint_Write_Byte(*(DataStream++));
+ }
+
+ return ENDPOINT_RWSTREAM_ERROR_NoError;
+}
+
+uint8_t Endpoint_Write_Stream_BE(const void* Buffer, uint16_t Length
+#if !defined(NO_STREAM_CALLBACKS)
+ , uint8_t (* const Callback)(void)
+#endif
+ )
+{
+ uint8_t* DataStream = (uint8_t*)(Buffer + Length - 1);
+ uint8_t ErrorCode;
+
+ if ((ErrorCode = Endpoint_WaitUntilReady()))
+ return ErrorCode;
+
+ while (Length--)
+ {
+ if (!(Endpoint_ReadWriteAllowed()))
+ {
+ Endpoint_ClearCurrentBank();
+
+ #if !defined(NO_STREAM_CALLBACKS)
+ if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
+ return ENDPOINT_RWSTREAM_ERROR_CallbackAborted;
+ #endif
+
+ if ((ErrorCode = Endpoint_WaitUntilReady()))
+ return ErrorCode;
+ }
+
+ Endpoint_Write_Byte(*(DataStream--));
+ }
+
+ return ENDPOINT_RWSTREAM_ERROR_NoError;
+}
+
+uint8_t Endpoint_Read_Stream_LE(void* Buffer, uint16_t Length
+#if !defined(NO_STREAM_CALLBACKS)
+ , uint8_t (* const Callback)(void)
+#endif
+ )
+{
+ uint8_t* DataStream = (uint8_t*)Buffer;
+ uint8_t ErrorCode;
+
+ if ((ErrorCode = Endpoint_WaitUntilReady()))
+ return ErrorCode;
+
+ while (Length--)
+ {
+ if (!(Endpoint_ReadWriteAllowed()))
+ {
+ Endpoint_ClearCurrentBank();
+
+ #if !defined(NO_STREAM_CALLBACKS)
+ if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
+ return ENDPOINT_RWSTREAM_ERROR_CallbackAborted;
+ #endif
+
+ if ((ErrorCode = Endpoint_WaitUntilReady()))
+ return ErrorCode;
+ }
+
+ *(DataStream++) = Endpoint_Read_Byte();
+ }
+
+ return ENDPOINT_RWSTREAM_ERROR_NoError;
+}
+
+uint8_t Endpoint_Read_Stream_BE(void* Buffer, uint16_t Length
+#if !defined(NO_STREAM_CALLBACKS)
+ , uint8_t (* const Callback)(void)
+#endif
+ )
+{
+ uint8_t* DataStream = (uint8_t*)(Buffer + Length - 1);
+ uint8_t ErrorCode;
+
+ if ((ErrorCode = Endpoint_WaitUntilReady()))
+ return ErrorCode;
+
+ while (Length--)
+ {
+ if (!(Endpoint_ReadWriteAllowed()))
+ {
+ Endpoint_ClearCurrentBank();
+
+ #if !defined(NO_STREAM_CALLBACKS)
+ if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
+ return ENDPOINT_RWSTREAM_ERROR_CallbackAborted;
+ #endif
+
+ if ((ErrorCode = Endpoint_WaitUntilReady()))
+ return ErrorCode;
+ }
+
+ *(DataStream--) = Endpoint_Read_Byte();
+ }
+
+ return ENDPOINT_RWSTREAM_ERROR_NoError;
+}
+
+uint8_t Endpoint_Write_Control_Stream_LE(const void* Buffer, uint16_t Length)
+{
+ uint8_t* DataStream = (uint8_t*)Buffer;
+ bool SendZLP = true;
+
+ while (Length && !(Endpoint_IsSetupOUTReceived()))
+ {
+ while (!(Endpoint_IsSetupINReady()));
+
+ while (Length && (Endpoint_BytesInEndpoint() < USB_ControlEndpointSize))
+ {
+ Endpoint_Write_Byte(*(DataStream++));
+
+ Length--;
+ }
+
+ SendZLP = (Endpoint_BytesInEndpoint() == USB_ControlEndpointSize);
+ Endpoint_ClearSetupIN();
+ }
+
+ if (Endpoint_IsSetupOUTReceived())
+ return ENDPOINT_RWCSTREAM_ERROR_HostAborted;
+
+ if (SendZLP)
+ {
+ while (!(Endpoint_IsSetupINReady()));
+ Endpoint_ClearSetupIN();
+ }
+
+ while (!(Endpoint_IsSetupOUTReceived()));
+
+ return ENDPOINT_RWCSTREAM_ERROR_NoError;
+}
+
+uint8_t Endpoint_Write_Control_Stream_BE(const void* Buffer, uint16_t Length)
+{
+ uint8_t* DataStream = (uint8_t*)(Buffer + Length - 1);
+ bool SendZLP = true;
+
+ while (Length && !(Endpoint_IsSetupOUTReceived()))
+ {
+ while (!(Endpoint_IsSetupINReady()));
+
+ while (Length && (Endpoint_BytesInEndpoint() < USB_ControlEndpointSize))
+ {
+ Endpoint_Write_Byte(*(DataStream--));
+
+ Length--;
+ }
+
+ SendZLP = (Endpoint_BytesInEndpoint() == USB_ControlEndpointSize);
+ Endpoint_ClearSetupIN();
+ }
+
+ if (Endpoint_IsSetupOUTReceived())
+ return ENDPOINT_RWCSTREAM_ERROR_HostAborted;
+
+ if (SendZLP)
+ {
+ while (!(Endpoint_IsSetupINReady()));
+ Endpoint_ClearSetupIN();
+ }
+
+ while (!(Endpoint_IsSetupOUTReceived()));
+
+ return ENDPOINT_RWCSTREAM_ERROR_NoError;
+}
+
+uint8_t Endpoint_Read_Control_Stream_LE(void* Buffer, uint16_t Length)
+{
+ uint8_t* DataStream = (uint8_t*)Buffer;
+
+ while (Length)
+ {
+ while (!(Endpoint_IsSetupOUTReceived()));
+
+ while (Length && Endpoint_BytesInEndpoint())
+ {
+ *(DataStream++) = Endpoint_Read_Byte();
+
+ Length--;
+ }
+
+ Endpoint_ClearSetupOUT();
+ }
+
+ while (!(Endpoint_IsSetupINReady()));
+
+ return ENDPOINT_RWCSTREAM_ERROR_NoError;
+}
+
+uint8_t Endpoint_Read_Control_Stream_BE(void* Buffer, uint16_t Length)
+{
+ uint8_t* DataStream = (uint8_t*)(Buffer + Length - 1);
+
+ while (Length)
+ {
+ while (!(Endpoint_IsSetupOUTReceived()));
+
+ while (Length && Endpoint_BytesInEndpoint())
+ {
+ *(DataStream--) = Endpoint_Read_Byte();
+
+ Length--;
+ }
+
+ Endpoint_ClearSetupOUT();
+ }
+
+ while (!(Endpoint_IsSetupINReady()));
+
+ return ENDPOINT_RWCSTREAM_ERROR_NoError;
+}
+
+#endif
diff --git a/LUFA/Drivers/USB/LowLevel/Endpoint.h b/LUFA/Drivers/USB/LowLevel/Endpoint.h new file mode 100644 index 000000000..5f3170416 --- /dev/null +++ b/LUFA/Drivers/USB/LowLevel/Endpoint.h @@ -0,0 +1,842 @@ +/*
+ 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
+ *
+ * Functions, macros and enums related to endpoint management when in USB Device mode. This
+ * module contains the endpoint management macros, as well as endpoint interrupt and data
+ * send/recieve functions for various datatypes.
+ */
+
+#ifndef __ENDPOINT_H__
+#define __ENDPOINT_H__
+
+ /* Includes: */
+ #include <avr/io.h>
+ #include <stdbool.h>
+
+ #include "../../../Common/Common.h"
+ #include "../HighLevel/USBTask.h"
+
+ #if !defined(NO_STREAM_CALLBACKS) || defined(__DOXYGEN__)
+ #include "StreamCallbacks.h"
+ #endif
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Endpoint data direction mask for Endpoint_ConfigureEndpoint(). This indicates that the endpoint
+ * should be initialized in the OUT direction - i.e. data flows from host to device.
+ */
+ #define ENDPOINT_DIR_OUT 0
+
+ /** Endpoint data direction mask for Endpoint_ConfigureEndpoint(). This indicates that the endpoint
+ * should be initialized in the IN direction - i.e. data flows from device to host.
+ */
+ #define ENDPOINT_DIR_IN (1 << EPDIR)
+
+ /** Mask for the bank mode selection for the Endpoint_ConfigureEndpoint() macro. This indicates
+ * that the endpoint should have one single bank, which requires less USB FIFO memory but results
+ * in slower transfers as only one USB device (the AVR or the host) can access the endpoint's
+ * bank at the one time.
+ */
+ #define ENDPOINT_BANK_SINGLE 0
+
+ /** Mask for the bank mode selection for the Endpoint_ConfigureEndpoint() macro. This indicates
+ * that the endpoint should have two banks, which requires more USB FIFO memory but results
+ * in faster transfers as one USB device (the AVR or the host) can access one bank while the other
+ * accesses the second bank.
+ */
+ #define ENDPOINT_BANK_DOUBLE (1 << EPBK0)
+
+ /** Endpoint address for the default control endpoint, which always resides in address 0. This is
+ * defined for convenience to give more readable code when used with the endpoint macros.
+ */
+ #define ENDPOINT_CONTROLEP 0
+
+ /** Default size of the default control endpoint's bank, until altered by the Endpoint0Size value
+ * in the device descriptor. Not available if the FIXED_CONTROL_ENDPOINT_SIZE token is defined.
+ */
+ #if (!defined(FIXED_CONTROL_ENDPOINT_SIZE) || defined(__DOXYGEN__))
+ #define ENDPOINT_CONTROLEP_DEFAULT_SIZE 8
+ #endif
+
+ /** Endpoint number mask, for masking against endpoint addresses to retrieve the endpoint's
+ * numerical address in the device.
+ */
+ #define ENDPOINT_EPNUM_MASK 0b111
+
+ /** Endpoint bank size mask, for masking against endpoint addresses to retrieve the endpoint's
+ * bank size in the device.
+ */
+ #define ENDPOINT_EPSIZE_MASK 0x7FF
+
+ /** Maximum size in bytes of a given endpoint.
+ *
+ * \param n Endpoint number, a value between 0 and (ENDPOINT_TOTAL_ENDPOINTS - 1)
+ */
+ #define ENDPOINT_MAX_SIZE(n) _ENDPOINT_GET_MAXSIZE(n)
+
+ /** Indicates if the given endpoint supports double banking.
+ *
+ * \param n Endpoint number, a value between 0 and (ENDPOINT_TOTAL_ENDPOINTS - 1)
+ */
+ #define ENDPOINT_DOUBLEBANK_SUPPORTED(n) _ENDPOINT_GET_DOUBLEBANK(n)
+
+ #if defined(USB_FULL_CONTROLLER) || defined(USB_MODIFIED_FULL_CONTROLLER) || defined(__DOXYGEN__)
+ /** Total number of endpoints (including the default control endpoint at address 0) which may
+ * be used in the device. Different USB AVR models support different amounts of endpoints,
+ * this value reflects the maximum number of endpoints for the currently selected AVR model.
+ */
+ #define ENDPOINT_TOTAL_ENDPOINTS 7
+ #else
+ #define ENDPOINT_TOTAL_ENDPOINTS 5
+ #endif
+
+ /** Interrupt definition for the endpoint SETUP interrupt (for CONTROL type endpoints). Should be
+ * used with the USB_INT_* macros located in USBInterrupt.h.
+ *
+ * This interrupt will fire if enabled on a CONTROL type endpoint if a new control packet is
+ * received from the host.
+ */
+ #define ENDPOINT_INT_SETUP UEIENX, (1 << RXSTPE), UEINTX, (1 << RXSTPI)
+
+ /** Interrupt definition for the endpoint IN interrupt (for INTERRUPT type endpoints). Should be
+ * used with the USB_INT_* macros located in USBInterrupt.h.
+ *
+ * This interrupt will fire if enabled on an INTERRUPT type endpoint if a the endpoint interrupt
+ * period has elapsed and the endpoint is ready for a new packet to be written to its FIFO buffer
+ * (if required).
+ */
+ #define ENDPOINT_INT_IN UEIENX, (1 << TXINE) , UEINTX, (1 << TXINI)
+
+ /** Interrupt definition for the endpoint OUT interrupt (for INTERRUPT type endpoints). Should be
+ * used with the USB_INT_* macros located in USBInterrupt.h.
+ *
+ * This interrupt will fire if enabled on an INTERRUPT type endpoint if a the endpoint interrupt
+ * period has elapsed and the endpoint is ready for a packet from the host to be read from its
+ * FIFO buffer (if received).
+ */
+ #define ENDPOINT_INT_OUT UEIENX, (1 << RXOUTE), UEINTX, (1 << RXOUTI)
+
+ #if defined(USB_FULL_CONTROLLER) || defined(USB_MODIFIED_FULL_CONTROLLER) || defined(__DOXYGEN__)
+ /** Indicates the number of bytes currently stored in the current endpoint's selected bank. */
+ #define Endpoint_BytesInEndpoint() UEBCX
+ #else
+ #define Endpoint_BytesInEndpoint() UEBCLX
+ #endif
+
+ /** Returns the endpoint address of the currently selected endpoint. This is typically used to save
+ * the currently selected endpoint number so that it can be restored after another endpoint has
+ * been manipulated.
+ */
+ #define Endpoint_GetCurrentEndpoint() (UENUM & ENDPOINT_EPNUM_MASK)
+
+ /** Selects the given endpoint number. If the address from the device descriptors is used, the
+ * value should be masked with the ENDPOINT_EPNUM_MASK constant to extract only the endpoint
+ * number (and discarding the endpoint direction bit).
+ *
+ * Any endpoint operations which do not require the endpoint number to be indicated will operate on
+ * the currently selected endpoint.
+ */
+ #define Endpoint_SelectEndpoint(epnum) MACROS{ UENUM = epnum; }MACROE
+
+ /** Resets the endpoint bank FIFO. This clears all the endpoint banks and resets the USB controller's
+ * In and Out pointers to the bank's contents.
+ */
+ #define Endpoint_ResetFIFO(epnum) MACROS{ UERST = (1 << epnum); UERST = 0; }MACROE
+
+ /** Enables the currently selected endpoint so that data can be sent and received through it to
+ * and from a host.
+ *
+ * \note Endpoints must first be configured properly rather than just being enabled via the
+ * Endpoint_ConfigureEndpoint() macro, which calls Endpoint_EnableEndpoint() automatically.
+ */
+ #define Endpoint_EnableEndpoint() MACROS{ UECONX |= (1 << EPEN); }MACROE
+
+ /** Disables the currently selected endpoint so that data cannot be sent and received through it
+ * to and from a host.
+ */
+ #define Endpoint_DisableEndpoint() MACROS{ UECONX &= ~(1 << EPEN); }MACROE
+
+ /** Returns true if the currently selected endpoint is enabled, false otherwise. */
+ #define Endpoint_IsEnabled() ((UECONX & (1 << EPEN)) ? true : false)
+
+ /** Returns true if the currently selected endpoint may be read from (if data is waiting in the endpoint
+ * bank and the endpoint is an OUT direction, or if the bank is not yet full if the endpoint is an
+ * IN direction). This function will return false if an error has occured in the endpoint, or if
+ * the endpoint is an OUT direction and no packet has been received, or if the endpoint is an IN
+ * direction and the endpoint bank is full.
+ */
+ #define Endpoint_ReadWriteAllowed() ((UEINTX & (1 << RWAL)) ? true : false)
+
+ /** Returns true if the currently selected endpoint is configured, false otherwise. */
+ #define Endpoint_IsConfigured() ((UESTA0X & (1 << CFGOK)) ? true : false)
+
+ /** Returns a mask indicating which INTERRUPT type endpoints have interrupted - i.e. their
+ * interrupt duration has elapsed. Which endpoints have interrupted can be determined by
+ * masking the return value against (1 << {Endpoint Number}).
+ */
+ #define Endpoint_GetEndpointInterrupts() UEINT
+
+ /** Clears the endpoint interrupt flag. This clears the specified endpoint number's interrupt
+ * mask in the endpoint interrupt flag register.
+ */
+ #define Endpoint_ClearEndpointInterrupt(n) MACROS{ UEINT &= ~(1 << n); }MACROE
+
+ /** Returns true if the specified endpoint number has interrupted (valid only for INTERRUPT type
+ * endpoints), false otherwise.
+ */
+ #define Endpoint_HasEndpointInterrupted(n) ((UEINT & (1 << n)) ? true : false)
+
+ /** Clears the currently selected endpoint bank, and switches to the alternate bank if the currently
+ * selected endpoint is dual-banked. When cleared, this either frees the bank up for the next packet
+ * from the host (if the endpoint is of the OUT direction) or sends the packet contents to the host
+ * (if the endpoint is of the IN direction).
+ */
+ #define Endpoint_ClearCurrentBank() MACROS{ UEINTX &= ~(1 << FIFOCON); }MACROE
+
+ /** Returns true if the current CONTROL type endpoint is ready for an IN packet, false otherwise. */
+ #define Endpoint_IsSetupINReady() ((UEINTX & (1 << TXINI)) ? true : false)
+
+ /** Returns true if the current CONTROL type endpoint is ready for an OUT packet, false otherwise. */
+ #define Endpoint_IsSetupOUTReceived() ((UEINTX & (1 << RXOUTI)) ? true : false)
+
+ /** Returns true if the current CONTROL type endpoint is ready for a SETUP packet, false otherwise. */
+ #define Endpoint_IsSetupReceived() ((UEINTX & (1 << RXSTPI)) ? true : false)
+
+ /** Clears a received SETUP packet on the currently selected CONTROL type endpoint. */
+ #define Endpoint_ClearSetupReceived() MACROS{ UEINTX &= ~(1 << RXSTPI); }MACROE
+
+ /** Sends an IN packet to the host on the currently selected CONTROL type endpoint. */
+ #define Endpoint_ClearSetupIN() MACROS{ UEINTX &= ~(1 << TXINI); }MACROE
+
+ /** Acknowedges an OUT packet to the host on the currently selected CONTROL type endpoint, freeing
+ * up the endpoint for the next packet.
+ */
+ #define Endpoint_ClearSetupOUT() MACROS{ UEINTX &= ~(1 << RXOUTI); }MACROE
+
+ /** Stalls the current endpoint, indicating to the host that a logical problem occured with the
+ * indicated endpoint and that the current transfer sequence should be aborted. This provides a
+ * way for devices to indicate invalid commands to the host so that the current transfer can be
+ * aborted and the host can begin its own recovery seqeuence.
+ *
+ * The currently selected endpoint remains stalled until either the Endpoint_ClearStall() macro
+ * is called, or the host issues a CLEAR FEATURE request to the device for the currently selected
+ * endpoint.
+ */
+ #define Endpoint_StallTransaction() MACROS{ UECONX |= (1 << STALLRQ); }MACROE
+
+ /** Clears the stall on the currently selected endpoint. */
+ #define Endpoint_ClearStall() MACROS{ UECONX |= (1 << STALLRQC); }MACROE
+
+ /** Returns true if the currently selected endpoint is stalled, false othewise. */
+ #define Endpoint_IsStalled() ((UECONX & (1 << STALLRQ)) ? true : false)
+
+ /** Resets the data toggle of the currently selected endpoint. */
+ #define Endpoint_ResetDataToggle() MACROS{ UECONX |= (1 << RSTDT); }MACROE
+
+ /* Enums: */
+ /** Enum for the possible error return codes of the Endpoint_WaitUntilReady function */
+ enum Endpoint_WaitUntilReady_ErrorCodes_t
+ {
+ ENDPOINT_READYWAIT_NoError = 0, /**< Endpoint is ready for next packet, no error. */
+ ENDPOINT_READYWAIT_EndpointStalled = 1, /**< The endpoint was stalled during the stream
+ * transfer by the host or device.
+ */
+ ENDPOINT_READYWAIT_DeviceDisconnected = 2, /**< Device was disconnected from the host while
+ * waiting for the endpoint to become ready.
+ */
+ ENDPOINT_READYWAIT_Timeout = 3, /**< The host failed to accept or send the next packet
+ * within the software timeout period set by the
+ * USB_STREAM_TIMEOUT_MS macro.
+ */
+ };
+
+ /** Enum for the possible error return codes of the Endpoint_*_Stream_* functions. */
+ enum Endpoint_Stream_RW_ErrorCodes_t
+ {
+ ENDPOINT_RWSTREAM_ERROR_NoError = 0, /**< Command completed successfully, no error. */
+ ENDPOINT_RWSTREAM_ERROR_EndpointStalled = 1, /**< The endpoint was stalled during the stream
+ * transfer by the host or device.
+ */
+ ENDPOINT_RWSTREAM_ERROR_DeviceDisconnected = 1, /**< Device was disconnected from the host during
+ * the transfer.
+ */
+ ENDPOINT_RWSTREAM_ERROR_Timeout = 2, /**< The host failed to accept or send the next packet
+ * within the software timeout period set by the
+ * USB_STREAM_TIMEOUT_MS macro.
+ */
+ ENDPOINT_RWSTREAM_ERROR_CallbackAborted = 3, /**< Indicates that the stream's callback function
+ * aborted the transfer early.
+ */
+ };
+
+ /** Enum for the possible error return codes of the Endpoint_*_Control_Stream_* functions. */
+ enum Endpoint_ControlStream_RW_ErrorCodes_t
+ {
+ ENDPOINT_RWCSTREAM_ERROR_NoError = 0, /**< Command completed successfully, no error. */
+ ENDPOINT_RWCSTREAM_ERROR_HostAborted = 1, /**< The aborted the transfer prematurely. */
+ };
+
+ /* Inline Functions: */
+ /** Reads one byte from the currently selected endpoint's bank, for OUT direction endpoints. */
+ static inline uint8_t Endpoint_Read_Byte(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Endpoint_Read_Byte(void)
+ {
+ return UEDATX;
+ }
+
+ /** Writes one byte from the currently selected endpoint's bank, for IN direction endpoints. */
+ static inline void Endpoint_Write_Byte(const uint8_t Byte)
+ {
+ UEDATX = Byte;
+ }
+
+ /** Discards one byte from the currently selected endpoint's bank, for OUT direction endpoints. */
+ static inline void Endpoint_Discard_Byte(void)
+ {
+ uint8_t Dummy;
+
+ Dummy = UEDATX;
+ }
+
+ /** Reads two bytes from the currently selected endpoint's bank in little endian format, for OUT
+ * direction endpoints.
+ */
+ static inline uint16_t Endpoint_Read_Word_LE(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint16_t Endpoint_Read_Word_LE(void)
+ {
+ uint16_t Data;
+
+ Data = UEDATX;
+ Data |= (((uint16_t)UEDATX) << 8);
+
+ return Data;
+ }
+
+ /** Reads two bytes from the currently selected endpoint's bank in big endian format, for OUT
+ * direction endpoints.
+ */
+ static inline uint16_t Endpoint_Read_Word_BE(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint16_t Endpoint_Read_Word_BE(void)
+ {
+ uint16_t Data;
+
+ Data = (((uint16_t)UEDATX) << 8);
+ Data |= UEDATX;
+
+ return Data;
+ }
+
+ /** Writes two bytes to the currently selected endpoint's bank in little endian format, for IN
+ * direction endpoints.
+ */
+ static inline void Endpoint_Write_Word_LE(const uint16_t Word)
+ {
+ UEDATX = (Word & 0xFF);
+ UEDATX = (Word >> 8);
+ }
+
+ /** Writes two bytes to the currently selected endpoint's bank in big endian format, for IN
+ * direction endpoints.
+ */
+ static inline void Endpoint_Write_Word_BE(const uint16_t Word)
+ {
+ UEDATX = (Word >> 8);
+ UEDATX = (Word & 0xFF);
+ }
+
+ /** Discards two bytes from the currently selected endpoint's bank, for OUT direction endpoints. */
+ static inline void Endpoint_Discard_Word(void)
+ {
+ uint8_t Dummy;
+
+ Dummy = UEDATX;
+ Dummy = UEDATX;
+ }
+
+ /** Reads four bytes from the currently selected endpoint's bank in little endian format, for OUT
+ * direction endpoints.
+ */
+ static inline uint32_t Endpoint_Read_DWord_LE(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint32_t Endpoint_Read_DWord_LE(void)
+ {
+ union
+ {
+ uint32_t DWord;
+ uint8_t Bytes[4];
+ } Data;
+
+ Data.Bytes[0] = UEDATX;
+ Data.Bytes[1] = UEDATX;
+ Data.Bytes[2] = UEDATX;
+ Data.Bytes[3] = UEDATX;
+
+ return Data.DWord;
+ }
+
+ /** Reads four bytes from the currently selected endpoint's bank in big endian format, for OUT
+ * direction endpoints.
+ */
+ static inline uint32_t Endpoint_Read_DWord_BE(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint32_t Endpoint_Read_DWord_BE(void)
+ {
+ union
+ {
+ uint32_t DWord;
+ uint8_t Bytes[4];
+ } Data;
+
+ Data.Bytes[3] = UEDATX;
+ Data.Bytes[2] = UEDATX;
+ Data.Bytes[1] = UEDATX;
+ Data.Bytes[0] = UEDATX;
+
+ return Data.DWord;
+ }
+
+ /** Writes four bytes to the currently selected endpoint's bank in little endian format, for IN
+ * direction endpoints.
+ */
+ static inline void Endpoint_Write_DWord_LE(const uint32_t DWord)
+ {
+ Endpoint_Write_Word_LE(DWord);
+ Endpoint_Write_Word_LE(DWord >> 16);
+ }
+
+ /** Writes four bytes to the currently selected endpoint's bank in big endian format, for IN
+ * direction endpoints.
+ */
+ static inline void Endpoint_Write_DWord_BE(const uint32_t DWord)
+ {
+ Endpoint_Write_Word_BE(DWord >> 16);
+ Endpoint_Write_Word_BE(DWord);
+ }
+
+ /** Discards four bytes from the currently selected endpoint's bank, for OUT direction endpoints. */
+ static inline void Endpoint_Discard_DWord(void)
+ {
+ uint8_t Dummy;
+
+ Dummy = UEDATX;
+ Dummy = UEDATX;
+ Dummy = UEDATX;
+ Dummy = UEDATX;
+ }
+
+ /* External Variables: */
+ /** Global indicating the maximum packet size of the default control endpoint located at address
+ * 0 in the device. This value is set to the value indicated in the device descriptor in the user
+ * project once the USB interface is initialized into device mode.
+ *
+ * If space is an issue, it is possible to fix this to a static value by defining the control
+ * endpoint size in the FIXED_CONTROL_ENDPOINT_SIZE token passed to the compiler in the makefile
+ * via the -D switch. When a fixed control endpoint size is used, the size is no longer dynamically
+ * read from the descriptors at runtime and instead fixed to the given value. When used, it is
+ * important that the descriptor control endpoint size value matches the size given as the
+ * FIXED_CONTROL_ENDPOINT_SIZE token - it is recommended that the FIXED_CONTROL_ENDPOINT_SIZE token
+ * be used in the descriptors to ensure this.
+ *
+ * \note This variable should be treated as read-only in the user application, and never manually
+ * changed in value.
+ */
+ #if (!defined(FIXED_CONTROL_ENDPOINT_SIZE) || defined(__DOXYGEN__))
+ extern uint8_t USB_ControlEndpointSize;
+ #else
+ #define USB_ControlEndpointSize FIXED_CONTROL_ENDPOINT_SIZE
+ #endif
+
+ /* Function Prototypes: */
+ /** Configures the specified endpoint number with the given endpoint type, direction, bank size
+ * and banking mode. Endpoints should be allocated in ascending order by their address in the
+ * device (i.e. endpoint 1 should be configured before endpoint 2 and so on).
+ *
+ * The endpoint type may be one of the EP_TYPE_* macros listed in LowLevel.h and the direction
+ * may be either ENDPOINT_DIR_OUT or ENDPOINT_DIR_IN.
+ *
+ * The bank size must indicate the maximum packet size that the endpoint can handle. Different
+ * endpoint numbers can handle different maximum packet sizes - refer to the chosen USB AVR's
+ * datasheet to determine the maximum bank size for each endpoint.
+ *
+ * The banking mode may be either ENDPOINT_BANK_SINGLE or ENDPOINT_BANK_DOUBLE.
+ *
+ * The success of this routine can be determined via the Endpoint_IsConfigured() macro.
+ *
+ * By default, the routine is entirely dynamic, and will accept both constant and variable inputs.
+ * If dynamic configuration is unused, a small space savings can be made by defining the
+ * STATIC_ENDPOINT_CONFIGURATION macro via the -D switch to the compiler, to optimize for constant
+ * input values.
+ *
+ * \note This routine will select the specified endpoint, and the endpoint will remain selected
+ * once the routine completes regardless of if the endpoint configuration succeeds.
+ *
+ * \return Boolean true if the configuration succeeded, false otherwise
+ */
+ bool Endpoint_ConfigureEndpoint(const uint8_t Number, const uint8_t Type, const uint8_t Direction,
+ const uint16_t Size, const uint8_t Banks);
+
+ /** Spinloops until the currently selected non-control endpoint is ready for the next packet of data
+ * to be read or written to it.
+ *
+ * \note This routine should not be called on CONTROL type endpoints.
+ *
+ * \return A value from the Endpoint_WaitUntilReady_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_WaitUntilReady(void);
+
+ /** Reads and discards the given number of bytes from the endpoint from the given buffer,
+ * discarding fully read packets from the host as needed. The last packet is not automatically
+ * discarded once the remaining bytes has been read; the user is responsible for manually
+ * discarding the last packet from the host via the Endpoint_ClearCurrentBank() macro. Between
+ * each USB packet, the given stream callback function is executed repeatedly until the next
+ * packet is ready, allowing for early aborts of stream transfers.
+ *
+ * The callback routine should be created using the STREAM_CALLBACK() macro. If the token
+ * NO_STREAM_CALLBACKS is passed via the -D option to the compiler, stream callbacks are disabled
+ * and this function has the Callback parameter ommitted.
+ *
+ * \note This routine should not be used on CONTROL type endpoints.
+ *
+ * \param Length Number of bytes to send via the currently selected endpoint.
+ * \param Callback Name of a callback routine to call between sucessive USB packet transfers, NULL if no callback
+ *
+ * \return A value from the Endpoint_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Discard_Stream(uint16_t Length
+ #if !defined(NO_STREAM_CALLBACKS) || defined(__DOXYGEN__)
+ , uint8_t (* const Callback)(void)
+ #endif
+ );
+
+ /** Writes the given number of bytes to the endpoint from the given buffer in little endian,
+ * sending full packets to the host as needed. The last packet filled is not automatically sent;
+ * the user is responsible for manually sending the last written packet to the host via the
+ * Endpoint_ClearCurrentBank() macro. Between each USB packet, the given stream callback function
+ * is executed repeatedly until the endpoint is ready to accept the next packet, allowing for early
+ * aborts of stream transfers.
+ *
+ * The callback routine should be created using the STREAM_CALLBACK() macro. If the token
+ * NO_STREAM_CALLBACKS is passed via the -D option to the compiler, stream callbacks are disabled
+ * and this function has the Callback parameter ommitted.
+ *
+ * \note This routine should not be used on CONTROL type endpoints.
+ *
+ * \param Buffer Pointer to the source data buffer to read from.
+ * \param Length Number of bytes to read for the currently selected endpoint into the buffer.
+ * \param Callback Name of a callback routine to call between sucessive USB packet transfers, NULL if no callback
+ *
+ * \return A value from the Endpoint_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Write_Stream_LE(const void* Buffer, uint16_t Length
+ #if !defined(NO_STREAM_CALLBACKS) || defined(__DOXYGEN__)
+ , uint8_t (* const Callback)(void)
+ #endif
+ ) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Writes the given number of bytes to the endpoint from the given buffer in big endian,
+ * sending full packets to the host as needed. The last packet filled is not automatically sent;
+ * the user is responsible for manually sending the last written packet to the host via the
+ * Endpoint_ClearCurrentBank() macro. Between each USB packet, the given stream callback function
+ * is executed repeatedly until the endpoint is ready to accept the next packet, allowing for early
+ * aborts of stream transfers.
+ *
+ * The callback routine should be created using the STREAM_CALLBACK() macro. If the token
+ * NO_STREAM_CALLBACKS is passed via the -D option to the compiler, stream callbacks are disabled
+ * and this function has the Callback parameter ommitted.
+ *
+ * \note This routine should not be used on CONTROL type endpoints.
+ *
+ * \param Buffer Pointer to the source data buffer to read from.
+ * \param Length Number of bytes to read for the currently selected endpoint into the buffer.
+ * \param Callback Name of a callback routine to call between sucessive USB packet transfers, NULL if no callback
+ *
+ * \return A value from the Endpoint_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Write_Stream_BE(const void* Buffer, uint16_t Length
+ #if !defined(NO_STREAM_CALLBACKS) || defined(__DOXYGEN__)
+ , uint8_t (* const Callback)(void)
+ #endif
+ ) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Reads the given number of bytes from the endpoint from the given buffer in little endian,
+ * discarding fully read packets from the host as needed. The last packet is not automatically
+ * discarded once the remaining bytes has been read; the user is responsible for manually
+ * discarding the last packet from the host via the Endpoint_ClearCurrentBank() macro. Between
+ * each USB packet, the given stream callback function is executed repeatedly until the endpoint
+ * is ready to accept the next packet, allowing for early aborts of stream transfers.
+ *
+ * The callback routine should be created using the STREAM_CALLBACK() macro. If the token
+ * NO_STREAM_CALLBACKS is passed via the -D option to the compiler, stream callbacks are disabled
+ * and this function has the Callback parameter ommitted.
+ *
+ * \note This routine should not be used on CONTROL type endpoints.
+ *
+ * \param Buffer Pointer to the destination data buffer to write to.
+ * \param Length Number of bytes to send via the currently selected endpoint.
+ * \param Callback Name of a callback routine to call between sucessive USB packet transfers, NULL if no callback
+ *
+ * \return A value from the Endpoint_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Read_Stream_LE(void* Buffer, uint16_t Length
+ #if !defined(NO_STREAM_CALLBACKS) || defined(__DOXYGEN__)
+ , uint8_t (* const Callback)(void)
+ #endif
+ ) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Reads the given number of bytes from the endpoint from the given buffer in big endian,
+ * discarding fully read packets from the host as needed. The last packet is not automatically
+ * discarded once the remaining bytes has been read; the user is responsible for manually
+ * discarding the last packet from the host via the Endpoint_ClearCurrentBank() macro. Between
+ * each USB packet, the given stream callback function is executed repeatedly until the endpoint
+ * is ready to accept the next packet, allowing for early aborts of stream transfers.
+ *
+ * The callback routine should be created using the STREAM_CALLBACK() macro. If the token
+ * NO_STREAM_CALLBACKS is passed via the -D option to the compiler, stream callbacks are disabled
+ * and this function has the Callback parameter ommitted.
+ *
+ * \note This routine should not be used on CONTROL type endpoints.
+ *
+ * \param Buffer Pointer to the destination data buffer to write to.
+ * \param Length Number of bytes to send via the currently selected endpoint.
+ * \param Callback Name of a callback routine to call between sucessive USB packet transfers, NULL if no callback
+ *
+ * \return A value from the Endpoint_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Read_Stream_BE(void* Buffer, uint16_t Length
+ #if !defined(NO_STREAM_CALLBACKS) || defined(__DOXYGEN__)
+ , uint8_t (* const Callback)(void)
+ #endif
+ ) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Writes the given number of bytes to the CONTROL type endpoint from the given buffer in little endian,
+ * sending full packets to the host as needed. The host OUT acknowedgement is not automatically cleared
+ * in both failure and success states; the user is responsible for manually clearing the setup OUT to
+ * finalize the transfer via the Endpoint_ClearSetupOUT() macro.
+ *
+ * \note This routine should only be used on CONTROL type endpoints.
+ *
+ * \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained
+ * together; i.e. the entire stream data must be read or written at the one time.
+ *
+ * \param Buffer Pointer to the source data buffer to read from.
+ * \param Length Number of bytes to read for the currently selected endpoint into the buffer.
+ *
+ * \return A value from the Endpoint_ControlStream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Write_Control_Stream_LE(const void* Buffer, uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Writes the given number of bytes to the CONTROL type endpoint from the given buffer in big endian,
+ * sending full packets to the host as needed. The host OUT acknowedgement is not automatically cleared
+ * in both failure and success states; the user is responsible for manually clearing the setup OUT to
+ * finalize the transfer via the Endpoint_ClearSetupOUT() macro.
+ *
+ * \note This routine should only be used on CONTROL type endpoints.
+ *
+ * \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained
+ * together; i.e. the entire stream data must be read or written at the one time.
+ *
+ * \param Buffer Pointer to the source data buffer to read from.
+ * \param Length Number of bytes to read for the currently selected endpoint into the buffer.
+ *
+ * \return A value from the Endpoint_ControlStream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Write_Control_Stream_BE(const void* Buffer, uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Reads the given number of bytes from the CONTROL endpoint from the given buffer in little endian,
+ * discarding fully read packets from the host as needed. The device IN acknowedgement is not
+ * automatically sent after success or failure states; the user is responsible for manually sending the
+ * setup IN to finalize the transfer via the Endpoint_ClearSetupIN() macro.
+ *
+ * \note This routine should only be used on CONTROL type endpoints.
+ *
+ * \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained
+ * together; i.e. the entire stream data must be read or written at the one time.
+ *
+ * \param Buffer Pointer to the destination data buffer to write to.
+ * \param Length Number of bytes to send via the currently selected endpoint.
+ *
+ * \return A value from the Endpoint_ControlStream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Read_Control_Stream_LE(void* Buffer, uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Reads the given number of bytes from the CONTROL endpoint from the given buffer in big endian,
+ * discarding fully read packets from the host as needed. The device IN acknowedgement is not
+ * automatically sent after success or failure states; the user is responsible for manually sending the
+ * setup IN to finalize the transfer via the Endpoint_ClearSetupIN() macro.
+ *
+ * \note This routine should only be used on CONTROL type endpoints.
+ *
+ * \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained
+ * together; i.e. the entire stream data must be read or written at the one time.
+ *
+ * \param Buffer Pointer to the destination data buffer to write to.
+ * \param Length Number of bytes to send via the currently selected endpoint.
+ *
+ * \return A value from the Endpoint_ControlStream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Read_Control_Stream_BE(void* Buffer, uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
+
+ /* Function Aliases: */
+ /** Alias for Endpoint_Discard_Byte().
+ */
+ #define Endpoint_Ignore_Byte() Endpoint_Discard_Byte()
+
+ /** Alias for Endpoint_Discard_Word().
+ */
+ #define Endpoint_Ignore_Word() Endpoint_Discard_Word()
+
+ /** Alias for Endpoint_Discard_DWord().
+ */
+ #define Endpoint_Ignore_DWord() Endpoint_Discard_DWord()
+
+ /** Alias for Endpoint_Read_Word_LE(). By default USB transfers use little endian format, thus
+ * the command with no endianness specifier indicates little endian mode.
+ */
+ #define Endpoint_Read_Word() Endpoint_Read_Word_LE()
+
+ /** Alias for Endpoint_Write_Word_LE(). By default USB transfers use little endian format, thus
+ * the command with no endianness specifier indicates little endian mode.
+ */
+ #define Endpoint_Write_Word(Word) Endpoint_Write_Word_LE(Word)
+
+ /** Alias for Endpoint_Read_DWord_LE(). By default USB transfers use little endian format, thus
+ * the command with no endianness specifier indicates little endian mode.
+ */
+ #define Endpoint_Read_DWord() Endpoint_Read_DWord_LE()
+
+ /** Alias for Endpoint_Write_DWord_LE(). By default USB transfers use little endian format, thus
+ * the command with no endianness specifier indicates little endian mode.
+ */
+ #define Endpoint_Write_DWord(DWord) Endpoint_Write_DWord_LE(DWord)
+
+ /** Alias for Endpoint_Read_Stream_LE(). By default USB transfers use little endian format, thus
+ * the command with no endianness specifier indicates little endian mode.
+ */
+ #if !defined(NO_STREAM_CALLBACKS)
+ #define Endpoint_Read_Stream(Buffer, Length, Callback) Endpoint_Read_Stream_LE(Buffer, Length, Callback)
+ #else
+ #define Endpoint_Read_Stream(Buffer, Length) Endpoint_Read_Stream_LE(Buffer, Length)
+ #endif
+
+ /** Alias for Endpoint_Write_Stream_LE(). By default USB transfers use little endian format, thus
+ * the command with no endianness specifier indicates little endian mode.
+ */
+ #if !defined(NO_STREAM_CALLBACKS)
+ #define Endpoint_Write_Stream(Buffer, Length, Callback) Endpoint_Write_Stream_LE(Buffer, Length, Callback)
+ #else
+ #define Endpoint_Write_Stream(Buffer, Length) Endpoint_Write_Stream_LE(Buffer, Length)
+ #endif
+
+ /** Alias for Endpoint_Read_Control_Stream_LE(). By default USB transfers use little endian format, thus
+ * the command with no endianness specifier indicates little endian mode.
+ */
+ #define Endpoint_Read_Control_Stream(Data, Length) Endpoint_Read_Control_Stream_LE(Data, Length)
+
+ /** Alias for Endpoint_Write_Control_Stream_LE(). By default USB transfers use little endian format, thus
+ * the command with no endianness specifier indicates little endian mode.
+ */
+ #define Endpoint_Write_Control_Stream(Data, Length) Endpoint_Write_Control_Stream_LE(Data, Length)
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define Endpoint_AllocateMemory() MACROS{ UECFG1X |= (1 << ALLOC); }MACROE
+ #define Endpoint_DeallocateMemory() MACROS{ UECFG1X &= ~(1 << ALLOC); }MACROE
+
+ #define _ENDPOINT_GET_MAXSIZE(n) _ENDPOINT_GET_MAXSIZE2(ENDPOINT_DETAILS_EP ## n)
+ #define _ENDPOINT_GET_MAXSIZE2(details) _ENDPOINT_GET_MAXSIZE3(details)
+ #define _ENDPOINT_GET_MAXSIZE3(maxsize, db) maxsize
+
+ #define _ENDPOINT_GET_DOUBLEBANK(n) _ENDPOINT_GET_DOUBLEBANK2(ENDPOINT_DETAILS_EP ## n)
+ #define _ENDPOINT_GET_DOUBLEBANK2(details) _ENDPOINT_GET_DOUBLEBANK3(details)
+ #define _ENDPOINT_GET_DOUBLEBANK3(maxsize, db) db
+
+ #if defined(USB_FULL_CONTROLLER) || defined(USB_MODIFIED_FULL_CONTROLLER)
+ #define ENDPOINT_DETAILS_EP0 64, true
+ #define ENDPOINT_DETAILS_EP1 256, true
+ #define ENDPOINT_DETAILS_EP2 64, true
+ #define ENDPOINT_DETAILS_EP3 64, true
+ #define ENDPOINT_DETAILS_EP4 64, true
+ #define ENDPOINT_DETAILS_EP5 64, true
+ #define ENDPOINT_DETAILS_EP6 64, true
+ #else
+ #define ENDPOINT_DETAILS_EP0 64, true
+ #define ENDPOINT_DETAILS_EP1 64, false
+ #define ENDPOINT_DETAILS_EP2 64, false
+ #define ENDPOINT_DETAILS_EP3 64, true
+ #define ENDPOINT_DETAILS_EP4 64, true
+ #endif
+
+ #if defined(STATIC_ENDPOINT_CONFIGURATION)
+ #define Endpoint_ConfigureEndpoint(Number, Type, Direction, Size, Banks) \
+ Endpoint_ConfigureEndpointStatic(Number, \
+ ((Type << EPTYPE0) | Direction), \
+ ((1 << ALLOC) | Banks | Endpoint_BytesToEPSizeMask(Size)));
+ #endif
+
+ /* Function Prototypes: */
+ void Endpoint_ClearEndpoints(void);
+ bool Endpoint_ConfigureEndpointStatic(const uint8_t Number, const uint8_t UECFG0XData, const uint8_t UECFG1XData);
+
+ /* Inline Functions: */
+ static inline uint8_t Endpoint_BytesToEPSizeMask(const uint16_t Bytes) ATTR_WARN_UNUSED_RESULT ATTR_CONST ATTR_ALWAYSINLINE;
+ static inline uint8_t Endpoint_BytesToEPSizeMask(const uint16_t Bytes)
+ {
+ if (Bytes <= 8)
+ return (0 << EPSIZE0);
+ else if (Bytes <= 16)
+ return (1 << EPSIZE0);
+ else if (Bytes <= 32)
+ return (2 << EPSIZE0);
+ #if defined(USB_LIMITED_CONTROLLER)
+ else
+ return (3 << EPSIZE0);
+ #else
+ else if (Bytes <= 64)
+ return (3 << EPSIZE0);
+ else if (Bytes <= 128)
+ return (4 << EPSIZE0);
+ else
+ return (5 << EPSIZE0);
+ #endif
+ };
+
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
diff --git a/LUFA/Drivers/USB/LowLevel/Host.c b/LUFA/Drivers/USB/LowLevel/Host.c new file mode 100644 index 000000000..7acbffe71 --- /dev/null +++ b/LUFA/Drivers/USB/LowLevel/Host.c @@ -0,0 +1,115 @@ +/*
+ 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 "USBMode.h"
+#if defined(USB_CAN_BE_HOST)
+
+#include "Host.h"
+
+uint8_t USB_Host_WaitMS(uint8_t MS)
+{
+ bool BusSuspended = USB_Host_IsBusSuspended();
+ uint8_t ErrorCode = HOST_WAITERROR_Successful;
+
+ USB_INT_Clear(USB_INT_HSOFI);
+ USB_Host_ResumeBus();
+
+ while (MS)
+ {
+ if (USB_INT_HasOccurred(USB_INT_HSOFI))
+ {
+ USB_INT_Clear(USB_INT_HSOFI);
+ MS--;
+ }
+
+ if ((USB_IsConnected == false) || (USB_CurrentMode == USB_MODE_DEVICE))
+ {
+ ErrorCode = HOST_WAITERROR_DeviceDisconnect;
+
+ break;
+ }
+
+ if (Pipe_IsError() == true)
+ {
+ Pipe_ClearError();
+ ErrorCode = HOST_WAITERROR_PipeError;
+
+ break;
+ }
+
+ if (Pipe_IsStalled() == true)
+ {
+ Pipe_ClearStall();
+ ErrorCode = HOST_WAITERROR_SetupStalled;
+
+ break;
+ }
+ }
+
+ if (BusSuspended)
+ USB_Host_SuspendBus();
+
+ return ErrorCode;
+}
+
+void USB_Host_ResetDevice(void)
+{
+ bool BusSuspended = USB_Host_IsBusSuspended();
+
+ USB_INT_Disable(USB_INT_DDISCI);
+
+ USB_Host_ResetBus();
+ while (!(USB_Host_IsResetBusDone()));
+
+ USB_INT_Clear(USB_INT_HSOFI);
+ USB_Host_ResumeBus();
+
+ for (uint8_t MSRem = 10; MSRem != 0; MSRem--)
+ {
+ /* Workaround for powerless-pullup devices. After a USB bus reset,
+ all disconnection interrupts are supressed while a USB frame is
+ looked for - if it is found within 10ms, the device is still
+ present. */
+
+ if (USB_INT_HasOccurred(USB_INT_HSOFI))
+ {
+ USB_INT_Clear(USB_INT_DDISCI);
+ break;
+ }
+
+ _delay_ms(1);
+ }
+
+ if (BusSuspended)
+ USB_Host_SuspendBus();
+
+ USB_INT_Enable(USB_INT_DDISCI);
+}
+#endif
diff --git a/LUFA/Drivers/USB/LowLevel/Host.h b/LUFA/Drivers/USB/LowLevel/Host.h new file mode 100644 index 000000000..5cc215454 --- /dev/null +++ b/LUFA/Drivers/USB/LowLevel/Host.h @@ -0,0 +1,245 @@ +/*
+ 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 Host mode related macros and enums. This module contains macros and enums which are used when
+ * the USB controller is initialized in host mode.
+ */
+
+#ifndef __USBHOST_H__
+#define __USBHOST_H__
+
+ /* Includes: */
+ #include <avr/io.h>
+ #include <stdbool.h>
+ #include <util/delay.h>
+
+ #include "../../../Common/Common.h"
+ #include "../HighLevel/USBInterrupt.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates the fixed USB device address which any attached device is enumerated to when in
+ * host mode. As only one USB device may be attached to the AVR in host mode at any one time
+ * and that the address used is not important (other than the fact that it is non-zero), a
+ * fixed value is specified by the library.
+ */
+ #define USB_HOST_DEVICEADDRESS 1
+
+ #if !defined(USB_HOST_TIMEOUT_MS) || defined(__DOXYGEN__)
+ /** Constant for the maximum software timeout period of sent USB control transactions to an attached
+ * device. If a device fails to respond to a sent control request within this period, the
+ * library will return a timeout error code.
+ *
+ * This value may be overridden in the user project makefile as the value of the
+ * USB_HOST_TIMEOUT_MS token, and passed to the compiler using the -D switch.
+ */
+ #define USB_HOST_TIMEOUT_MS 1000
+ #endif
+
+ #if !defined(HOST_DEVICE_SETTLE_DELAY_MS) || defined(__DOXYGEN__)
+ /** Constant for the delay in milliseconds after a device is connected before the library
+ * will start the enumeration process. Some devices require a delay of up to 5 seconds
+ * after connection before the enumeration process can start or incorrect operation will
+ * occur.
+ *
+ * This value may be overridden in the user project makefile as the value of the
+ * HOST_DEVICE_SETTLE_DELAY_MS token, and passed to the compiler using the -D switch.
+ */
+ #define HOST_DEVICE_SETTLE_DELAY_MS 1500
+ #endif
+
+ /** Resets the USB bus, including the endpoints in any attached device and pipes on the AVR host.
+ * USB bus resets leave the default control pipe configured (if already configured).
+ *
+ * If the USB bus has been suspended prior to issuing a bus reset, the attached device will be
+ * woken up automatically and the bus resumed after the reset has been correctly issued.
+ */
+ #define USB_Host_ResetBus() MACROS{ UHCON |= (1 << RESET); }MACROE
+
+ /** Determines if a previously issued bus reset (via the USB_Host_ResetBus() macro) has
+ * completed. This macro returns true if no bus reset is currently being sent, false
+ * otherwise.
+ */
+ #define USB_Host_IsResetBusDone() ((UHCON & (1 << RESET)) ? false : true)
+
+ /** Resumes USB communications with an attached and enumerated device, by resuming the transmission
+ * of the 1MS Start Of Frame messages to the device. When resumed, USB communications between the
+ * host and attached device may occur.
+ */
+ #define USB_Host_ResumeBus() MACROS{ UHCON |= (1 << SOFEN); }MACROE
+
+ /** Suspends the USB bus, preventing any communications from occuring between the host and attached
+ * device until the bus has been resumed. This stops the transmission of the 1MS Start Of Frame
+ * messages to the device.
+ */
+ #define USB_Host_SuspendBus() MACROS{ UHCON &= ~(1 << SOFEN); }MACROE
+
+ /** Returns true if the USB bus has been suspended via the use of the USB_Host_SuspendBus() macro,
+ * false otherwise. While suspended, no USB communications can occur until the bus is resumed,
+ * except for the Remote Wakeup event from the device if supported.
+ */
+ #define USB_Host_IsBusSuspended() ((UHCON & (1 << SOFEN)) ? false : true)
+
+ /** Returns true if the attached device is currently enumerated in Full Speed mode (12Mb/s), or
+ * false if the attached device is enumerated in Low Speed mode (1.5Mb/s).
+ */
+ #define USB_Host_IsDeviceFullSpeed() ((USBSTA & (1 << SPEED)) ? true : false)
+
+ /** Returns true if the attached device is currently issuing a Remote Wakeup request, requesting
+ * that the host resume the USB bus and wake up the device, false otherwise.
+ */
+ #define USB_Host_IsRemoteWakeupSent() ((UHINT & (1 << RXRSMI)) ? true : false)
+
+ /** Clears the flag indicating that a Remote Wakeup request has been issued by an attached
+ * device.
+ */
+ #define USB_Host_ClearRemoteWakeupSent() MACROS{ UHINT &= ~(1 << RXRSMI); }MACROE
+
+ /** Accepts a Remote Wakeup request from an attached device. This must be issued in response to
+ * a device's Remote Wakeup request within 2ms for the request to be accepted and the bus to
+ * be resumed.
+ */
+ #define USB_Host_ResumeFromWakeupRequest() MACROS{ UHCON |= (1 << RESUME); }MACROE
+
+ /** Returns true if no resume from Remote Wakeup request is currently being sent to an attached
+ * device, false otherwise.
+ */
+ #define USB_Host_IsResumeFromWakeupRequestSent() ((UHCON & (1 << RESUME)) ? false : true)
+
+ /* Enums: */
+ /** Enum for the various states of the USB Host state machine. Only some states are
+ * implemented in the LUFA library - other states are left to the user to implement.
+ *
+ * For information on each state, refer to the USB 2.0 specification. Some states have
+ *
+ * \see USBTask.h for information on the global variable USB_HostState, which stores the
+ * current host state machine state.
+ */
+ enum USB_Host_States_t
+ {
+ HOST_STATE_WaitForDevice = 0, /**< Internally implemented by the library. */
+ HOST_STATE_Unattached = 1, /**< Internally implemented by the library. */
+ HOST_STATE_Attached = 2, /**< Internally implemented by the library. */
+ HOST_STATE_Attached_WaitForDeviceSettle = 3, /**< Internally implemented by the library. */
+ HOST_STATE_Attached_WaitForConnect = 4, /**< Internally implemented by the library. */
+ HOST_STATE_Attached_DoReset = 5, /**< Internally implemented by the library. */
+ HOST_STATE_Powered = 6, /**< Internally implemented by the library. */
+ HOST_STATE_Default = 7, /**< Internally implemented by the library. */
+ HOST_STATE_Default_PostReset = 8, /**< Internally implemented by the library. */
+ HOST_STATE_Default_PostAddressSet = 9, /**< Internally implemented by the library. */
+ HOST_STATE_Addressed = 10, /**< May be implemented by the user project. */
+ HOST_STATE_Configured = 11, /**< May be implemented by the user project. */
+ HOST_STATE_Ready = 12, /**< May be implemented by the user project. */
+ HOST_STATE_Suspended = 13, /**< May be implemented by the user project. */
+ };
+
+ /** Enum for the error codes for the USB_HostError event.
+ *
+ * \see Events.h for more information on this event.
+ */
+ enum USB_Host_ErrorCodes_t
+ {
+ HOST_ERROR_VBusVoltageDip = 0, /**< VBUS voltage dipped to an unacceptable level. This
+ * error may be the result of an attached device drawing
+ * too much current from the VBUS line, or due to the
+ * AVR's power source being unable to supply sufficient
+ * current.
+ */
+ };
+
+ /** Enum for the error codes for the USB_DeviceEnumerationFailed event.
+ *
+ * \see Events.h for more information on this event.
+ */
+ enum USB_Host_EnumerationErrorCodes_t
+ {
+ HOST_ENUMERROR_NoError = 0, /**< No error occurred. Used internally, this is not a valid
+ * ErrorCode parameter value for the USB_DeviceEnumerationFailed
+ * event.
+ */
+ HOST_ENUMERROR_WaitStage = 1, /**< One of the delays between enumeration steps failed
+ * to complete successfuly, due to a timeout or other
+ * error.
+ */
+ HOST_ENUMERROR_NoDeviceDetected = 2, /**< No device was detected, despite the USB data lines
+ * indicating the attachment of a device.
+ */
+ HOST_ENUMERROR_ControlError = 3, /**< One of the enumeration control requests failed to
+ * complete successfuly.
+ */
+ HOST_ENUMERROR_PipeConfigError = 4, /**< The default control pipe (address 0) failed to
+ * configure correctly.
+ */
+ };
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define USB_Host_HostMode_On() MACROS{ USBCON |= (1 << HOST); }MACROE
+ #define USB_Host_HostMode_Off() MACROS{ USBCON &= ~(1 << HOST); }MACROE
+
+ #define USB_Host_VBUS_Auto_Enable() MACROS{ OTGCON &= ~(1 << VBUSHWC); UHWCON |= (1 << UVCONE); }MACROE
+ #define USB_Host_VBUS_Manual_Enable() MACROS{ OTGCON |= (1 << VBUSHWC); UHWCON &= ~(1 << UVCONE); DDRE |= (1 << 7); }MACROE
+
+ #define USB_Host_VBUS_Auto_On() MACROS{ OTGCON |= (1 << VBUSREQ); }MACROE
+ #define USB_Host_VBUS_Manual_On() MACROS{ PORTE |= (1 << 7); }MACROE
+
+ #define USB_Host_VBUS_Auto_Off() MACROS{ OTGCON |= (1 << VBUSRQC); }MACROE
+ #define USB_Host_VBUS_Manual_Off() MACROS{ PORTE &= ~(1 << 7); }MACROE
+
+ #define USB_Host_SetDeviceAddress(addr) MACROS{ UHADDR = (addr & 0b01111111); }MACROE
+
+ /* Enums: */
+ enum USB_Host_WaitMSErrorCodes_t
+ {
+ HOST_WAITERROR_Successful = 0,
+ HOST_WAITERROR_DeviceDisconnect = 1,
+ HOST_WAITERROR_PipeError = 2,
+ HOST_WAITERROR_SetupStalled = 3,
+ };
+
+ /* Function Prototypes: */
+ uint8_t USB_Host_WaitMS(uint8_t MS);
+ void USB_Host_ResetDevice(void);
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
diff --git a/LUFA/Drivers/USB/LowLevel/HostChapter9.c b/LUFA/Drivers/USB/LowLevel/HostChapter9.c new file mode 100644 index 000000000..fe168b724 --- /dev/null +++ b/LUFA/Drivers/USB/LowLevel/HostChapter9.c @@ -0,0 +1,178 @@ +/*
+ 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 "USBMode.h"
+#if defined(USB_CAN_BE_HOST)
+
+#define INCLUDE_FROM_HOSTCHAPTER9_C
+#include "HostChapter9.h"
+
+USB_Host_Request_Header_t USB_HostRequest;
+
+uint8_t USB_Host_SendControlRequest(void* BufferPtr)
+{
+ uint8_t* HeaderStream = (uint8_t*)&USB_HostRequest;
+ uint8_t* DataStream = (uint8_t*)BufferPtr;
+ bool BusSuspended = USB_Host_IsBusSuspended();
+ uint8_t ReturnStatus = HOST_SENDCONTROL_Successful;
+ uint16_t DataLen = USB_HostRequest.wLength;
+
+ USB_Host_ResumeBus();
+
+ if ((ReturnStatus = USB_Host_WaitMS(1)) != HOST_WAITERROR_Successful)
+ return ReturnStatus;
+
+ Pipe_SelectPipe(PIPE_CONTROLPIPE);
+ Pipe_SetToken(PIPE_TOKEN_SETUP);
+ Pipe_ClearErrorFlags();
+ Pipe_ClearSetupSent();
+
+ Pipe_Unfreeze();
+
+ for (uint8_t HeaderByte = 0; HeaderByte < sizeof(USB_Host_Request_Header_t); HeaderByte++)
+ Pipe_Write_Byte(*(HeaderStream++));
+
+ Pipe_ClearSetupOUT();
+
+ if ((ReturnStatus = USB_Host_Wait_For_Setup_IOS(USB_HOST_WAITFOR_SetupSent)))
+ goto End_Of_Control_Send;
+
+ Pipe_ClearSetupSent();
+ Pipe_Freeze();
+
+ if ((ReturnStatus = USB_Host_WaitMS(1)) != HOST_WAITERROR_Successful)
+ goto End_Of_Control_Send;
+
+ if ((USB_HostRequest.bmRequestType & CONTROL_REQTYPE_DIRECTION) == REQDIR_DEVICETOHOST)
+ {
+ Pipe_SetToken(PIPE_TOKEN_IN);
+
+ if (DataStream != NULL)
+ {
+ while (DataLen)
+ {
+ Pipe_Unfreeze();
+
+ if ((ReturnStatus = USB_Host_Wait_For_Setup_IOS(USB_HOST_WAITFOR_InReceived)))
+ goto End_Of_Control_Send;
+
+ if (!(Pipe_BytesInPipe()))
+ DataLen = 0;
+
+ while (Pipe_BytesInPipe() && DataLen)
+ {
+ *(DataStream++) = Pipe_Read_Byte();
+ DataLen--;
+ }
+
+ Pipe_Freeze();
+ Pipe_ClearSetupIN();
+ }
+ }
+
+ Pipe_SetToken(PIPE_TOKEN_OUT);
+ Pipe_Unfreeze();
+
+ if ((ReturnStatus = USB_Host_Wait_For_Setup_IOS(USB_HOST_WAITFOR_OutReady)))
+ goto End_Of_Control_Send;
+
+ Pipe_ClearSetupOUT();
+
+ if ((ReturnStatus = USB_Host_Wait_For_Setup_IOS(USB_HOST_WAITFOR_OutReady)))
+ goto End_Of_Control_Send;
+ }
+ else
+ {
+ if (DataStream != NULL)
+ {
+ Pipe_SetToken(PIPE_TOKEN_OUT);
+ Pipe_Unfreeze();
+
+ while (DataLen)
+ {
+ if ((ReturnStatus = USB_Host_Wait_For_Setup_IOS(USB_HOST_WAITFOR_OutReady)))
+ goto End_Of_Control_Send;
+
+ while (DataLen && (Pipe_BytesInPipe() < USB_ControlPipeSize))
+ {
+ Pipe_Write_Byte(*(DataStream++));
+ DataLen--;
+ }
+
+ Pipe_ClearSetupOUT();
+ }
+
+ if ((ReturnStatus = USB_Host_Wait_For_Setup_IOS(USB_HOST_WAITFOR_OutReady)))
+ goto End_Of_Control_Send;
+
+ Pipe_Freeze();
+ }
+
+ Pipe_SetToken(PIPE_TOKEN_IN);
+ Pipe_Unfreeze();
+
+ if ((ReturnStatus = USB_Host_Wait_For_Setup_IOS(USB_HOST_WAITFOR_InReceived)))
+ goto End_Of_Control_Send;
+
+ Pipe_ClearSetupIN();
+ }
+
+End_Of_Control_Send:
+ Pipe_Freeze();
+
+ if (BusSuspended)
+ USB_Host_SuspendBus();
+
+ Pipe_ResetPipe(PIPE_CONTROLPIPE);
+
+ return ReturnStatus;
+}
+
+static uint8_t USB_Host_Wait_For_Setup_IOS(const uint8_t WaitType)
+{
+ uint16_t TimeoutCounter = USB_HOST_TIMEOUT_MS;
+
+ while (!(((WaitType == USB_HOST_WAITFOR_SetupSent) && Pipe_IsSetupSent()) ||
+ ((WaitType == USB_HOST_WAITFOR_InReceived) && Pipe_IsSetupINReceived()) ||
+ ((WaitType == USB_HOST_WAITFOR_OutReady) && Pipe_IsSetupOUTReady())))
+ {
+ uint8_t ErrorCode;
+
+ if ((ErrorCode = USB_Host_WaitMS(1)) != HOST_WAITERROR_Successful)
+ return ErrorCode;
+
+ if (!(TimeoutCounter--))
+ return HOST_SENDCONTROL_SoftwareTimeOut;
+ }
+
+ return HOST_SENDCONTROL_Successful;
+}
+
+#endif
diff --git a/LUFA/Drivers/USB/LowLevel/HostChapter9.h b/LUFA/Drivers/USB/LowLevel/HostChapter9.h new file mode 100644 index 000000000..1ca4343a9 --- /dev/null +++ b/LUFA/Drivers/USB/LowLevel/HostChapter9.h @@ -0,0 +1,127 @@ +/*
+ 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
+ *
+ * Module for host mode request processing. This module allows for the transmission of standard, class and
+ * vendor control requests to the default control endpoint of an attached device while in host mode.
+ *
+ * \see Chapter 9 of the USB 2.0 specification.
+ */
+
+#ifndef __HOSTCHAPTER9_H__
+#define __HOSTCHAPTER9_H__
+
+ /* Includes: */
+ #include <avr/io.h>
+ #include <stdbool.h>
+
+ #include "LowLevel.h"
+ #include "StdRequestType.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Type Defines: */
+ /** Type define for a standard USB control request.
+ *
+ * \see StdRequestType.h for information on the request type and data.
+ * \see The USB 2.0 specification for more information on standard control requests.
+ */
+ typedef struct
+ {
+ uint8_t bmRequestType; /**< Type of the request. */
+ uint8_t bRequest; /**< Request command code. */
+ uint16_t wValue; /**< wValue parameter of the request. */
+ uint16_t wIndex; /**< wIndex parameter of the request. */
+ uint16_t wLength; /**< Length of the data to transfer in bytes. */
+ } USB_Host_Request_Header_t;
+
+ /* Enums: */
+ /** Enum for the USB_Host_SendControlRequest() return code, indicating the reason for the error
+ * if the transfer of the request is unsuccessful.
+ */
+ enum USB_Host_SendControlErrorCodes_t
+ {
+ HOST_SENDCONTROL_Successful = 0, /**< No error occurred in the request transfer. */
+ HOST_SENDCONTROL_DeviceDisconnect = 1, /**< The attached device was disconnected during the
+ * request transfer.
+ */
+ HOST_SENDCONTROL_PipeError = 2, /**< An error occured in the pipe while sending the request. */
+ HOST_SENDCONTROL_SetupStalled = 3, /**< The attached device stalled the request, usually
+ * indicating that the request is unsupported on the device.
+ */
+ HOST_SENDCONTROL_SoftwareTimeOut = 4, /**< The request or data transfer timed out. */
+ };
+
+ /* Global Variables: */
+ /** Global for the request to send via the USB_Host_SendControlRequest() function. This
+ * global should be filled with the correct control request data before sending the request to
+ * the attached device while in host mode.
+ */
+ extern USB_Host_Request_Header_t USB_HostRequest;
+
+ /* Function Prototypes: */
+ /** Sends the request stored in the USB_HostRequest global structure to the attached device,
+ * and transfers the data stored in the buffer to the device, or from the device to the buffer
+ * as requested.
+ *
+ * \param BufferPtr Pointer to the start of the data buffer if the request has a data stage, or
+ * NULL if the request transfers no data to or from the device.
+ *
+ * \return A value from the USB_Host_SendControlErrorCodes_t enum to indicate the result.
+ */
+ uint8_t USB_Host_SendControlRequest(void* BufferPtr);
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Enums: */
+ enum USB_WaitForTypes_t
+ {
+ USB_HOST_WAITFOR_SetupSent,
+ USB_HOST_WAITFOR_InReceived,
+ USB_HOST_WAITFOR_OutReady,
+ };
+
+ /* Function Prototypes: */
+ #if defined(INCLUDE_FROM_HOSTCHAPTER9_C)
+ static uint8_t USB_Host_Wait_For_Setup_IOS(const uint8_t WaitType);
+ #endif
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
diff --git a/LUFA/Drivers/USB/LowLevel/LowLevel.c b/LUFA/Drivers/USB/LowLevel/LowLevel.c new file mode 100644 index 000000000..61acf6def --- /dev/null +++ b/LUFA/Drivers/USB/LowLevel/LowLevel.c @@ -0,0 +1,260 @@ +/*
+ 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 "USBMode.h"
+
+#include "LowLevel.h"
+
+#if (!defined(USB_HOST_ONLY) && !defined(USB_DEVICE_ONLY))
+volatile uint8_t USB_CurrentMode = USB_MODE_NONE;
+#endif
+
+#if !defined(USE_STATIC_OPTIONS)
+volatile uint8_t USB_Options;
+#endif
+
+void USB_Init(
+ #if defined(USB_CAN_BE_BOTH)
+ const uint8_t Mode
+ #endif
+
+ #if (defined(USB_CAN_BE_BOTH) && !defined(USE_STATIC_OPTIONS))
+ ,
+ #elif (!defined(USB_CAN_BE_BOTH) && defined(USE_STATIC_OPTIONS))
+ void
+ #endif
+
+ #if !defined(USE_STATIC_OPTIONS)
+ const uint8_t Options
+ #endif
+ )
+{
+ USB_ShutDown();
+
+ #if defined(USB_CAN_BE_BOTH)
+ USB_CurrentMode = Mode;
+ #endif
+
+ #if !defined(USE_STATIC_OPTIONS)
+ USB_Options = Options;
+ #endif
+
+ #if defined(USB_CAN_BE_HOST)
+ USB_ControlPipeSize = PIPE_CONTROLPIPE_DEFAULT_SIZE;
+ #endif
+
+ #if defined(USB_DEVICE_ONLY) && defined(USB_FULL_CONTROLLER)
+ UHWCON |= (1 << UIMOD);
+ #elif defined(USB_HOST_ONLY)
+ UHWCON &= ~(1 << UIMOD);
+ #elif defined(USB_CAN_BE_BOTH)
+ if (Mode == USB_MODE_UID)
+ {
+ UHWCON |= (1 << UIDE);
+
+ USB_INT_Clear(USB_INT_IDTI);
+ USB_INT_Enable(USB_INT_IDTI);
+
+ USB_CurrentMode = USB_GetUSBModeFromUID();
+ }
+ else if (Mode == USB_MODE_DEVICE)
+ {
+ UHWCON |= (1 << UIMOD);
+ }
+ else if (Mode == USB_MODE_HOST)
+ {
+ UHWCON &= ~(1 << UIMOD);
+ }
+ else
+ {
+ RAISE_EVENT(USB_PowerOnFail, POWERON_ERROR_NoUSBModeSpecified);
+ return;
+ }
+ #endif
+
+ USB_ResetInterface();
+
+ #if defined(USB_FULL_CONTROLLER) || defined(USB_MODIFIED_FULL_CONTROLLER)
+ USB_OTGPAD_On();
+ #endif
+
+ USB_IsInitialized = true;
+
+ sei();
+}
+
+void USB_ShutDown(void)
+{
+ if (USB_IsConnected)
+ RAISE_EVENT(USB_Disconnect);
+
+ USB_Detach();
+
+ USB_INT_DisableAllInterrupts();
+ USB_INT_ClearAllInterrupts();
+
+ USB_IsConnected = false;
+ USB_IsInitialized = false;
+
+ #if defined(USB_CAN_BE_HOST)
+ USB_HostState = HOST_STATE_Unattached;
+ #endif
+
+ #if defined(USB_CAN_BE_DEVICE)
+ USB_ConfigurationNumber = 0;
+ #endif
+
+ #if defined(CAN_BE_BOTH)
+ USB_CurrentMode = USB_MODE_NONE;
+ #endif
+
+ USB_Interface_Disable();
+ USB_PLL_Off();
+
+ #if defined(USB_FULL_CONTROLLER) || defined(USB_MODIFIED_FULL_CONTROLLER)
+ USB_OTGPAD_Off();
+ #endif
+
+ #if defined(USB_CAN_BE_BOTH)
+ UHWCON &= ~(1 << UIDE);
+ #endif
+}
+
+void USB_ResetInterface(void)
+{
+ USB_INT_DisableAllInterrupts();
+ USB_INT_ClearAllInterrupts();
+
+ USB_IsConnected = false;
+
+ #if defined(USB_CAN_BE_HOST)
+ USB_HostState = HOST_STATE_Unattached;
+ #endif
+
+ #if defined(USB_CAN_BE_DEVICE)
+ USB_ConfigurationNumber = 0;
+ USB_IsSuspended = false;
+ USB_RemoteWakeupEnabled = false;
+ USB_CurrentlySelfPowered = false;
+ #endif
+
+ if (!(USB_Options & USB_OPT_MANUAL_PLL))
+ {
+ #if defined(USB_MODIFIED_FULL_CONTROLLER)
+ PLLFRQ = ((1 << PLLUSB) | (1 << PDIV3) | (1 << PDIV1));
+ #endif
+
+ USB_PLL_On();
+ while (!(USB_PLL_IsReady()));
+ }
+
+ USB_Interface_Reset();
+
+ #if defined(USB_CAN_BE_BOTH)
+ if (UHWCON & (1 << UIDE))
+ {
+ USB_INT_Clear(USB_INT_IDTI);
+ USB_INT_Enable(USB_INT_IDTI);
+ USB_CurrentMode = USB_GetUSBModeFromUID();
+ }
+ #endif
+
+ if (!(USB_Options & USB_OPT_REG_DISABLED))
+ USB_REG_On();
+
+ USB_CLK_Unfreeze();
+
+ #if (defined(USB_CAN_BE_DEVICE) && (defined(USB_FULL_CONTROLLER) || defined(USB_MODIFIED_FULL_CONTROLLER)))
+ if (USB_CurrentMode == USB_MODE_DEVICE)
+ {
+ if (USB_Options & USB_DEVICE_OPT_LOWSPEED)
+ USB_Device_SetLowSpeed();
+ else
+ USB_Device_SetHighSpeed();
+
+ USB_INT_Enable(USB_INT_VBUS);
+ }
+ #endif
+
+ #if (defined(USB_CAN_BE_DEVICE) && !defined(FIXED_CONTROL_ENDPOINT_SIZE))
+ if (USB_CurrentMode == USB_MODE_DEVICE)
+ {
+ USB_Descriptor_Device_t* DeviceDescriptorPtr;
+
+ if (USB_GetDescriptor((DTYPE_Device << 8), 0, (void*)&DeviceDescriptorPtr) != NO_DESCRIPTOR)
+ {
+ #if defined(USE_RAM_DESCRIPTORS)
+ USB_ControlEndpointSize = DeviceDescriptorPtr->Endpoint0Size;
+ #elif defined(USE_EEPROM_DESCRIPTORS)
+ USB_ControlEndpointSize = eeprom_read_byte(&DeviceDescriptorPtr->Endpoint0Size);
+ #else
+ USB_ControlEndpointSize = pgm_read_byte(&DeviceDescriptorPtr->Endpoint0Size);
+ #endif
+ }
+ }
+ #endif
+
+ USB_Attach();
+
+ #if defined(USB_DEVICE_ONLY)
+ USB_INT_Enable(USB_INT_SUSPEND);
+ USB_INT_Enable(USB_INT_EORSTI);
+ #elif defined(USB_HOST_ONLY)
+ USB_Host_HostMode_On();
+
+ USB_Host_VBUS_Auto_Off();
+ USB_OTGPAD_Off();
+
+ USB_Host_VBUS_Manual_Enable();
+ USB_Host_VBUS_Manual_On();
+
+ USB_INT_Enable(USB_INT_SRPI);
+ USB_INT_Enable(USB_INT_BCERRI);
+ #else
+ if (USB_CurrentMode == USB_MODE_DEVICE)
+ {
+ USB_INT_Enable(USB_INT_SUSPEND);
+ USB_INT_Enable(USB_INT_EORSTI);
+ }
+ else if (USB_CurrentMode == USB_MODE_HOST)
+ {
+ USB_Host_HostMode_On();
+
+ USB_Host_VBUS_Auto_Off();
+ USB_OTGPAD_Off();
+
+ USB_Host_VBUS_Manual_Enable();
+ USB_Host_VBUS_Manual_On();
+
+ USB_INT_Enable(USB_INT_SRPI);
+ USB_INT_Enable(USB_INT_BCERRI);
+ }
+ #endif
+}
diff --git a/LUFA/Drivers/USB/LowLevel/LowLevel.h b/LUFA/Drivers/USB/LowLevel/LowLevel.h new file mode 100644 index 000000000..faafbd7bf --- /dev/null +++ b/LUFA/Drivers/USB/LowLevel/LowLevel.h @@ -0,0 +1,371 @@ +/*
+ 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
+ *
+ * Main low level USB driver. This module manages the low level initialization and shut down of the USB AVR's
+ * USB interface in either device or (if supported) host mode.
+ */
+
+#ifndef __USBLOWLEVEL_H__
+#define __USBLOWLEVEL_H__
+
+ /* Includes: */
+ #include <avr/io.h>
+ #include <avr/interrupt.h>
+ #include <stdbool.h>
+
+ #include "USBMode.h"
+ #include "../../../Common/Common.h"
+ #include "../HighLevel/Events.h"
+ #include "../HighLevel/USBTask.h"
+ #include "../HighLevel/USBInterrupt.h"
+
+ #if defined(USB_CAN_BE_HOST) || defined(__DOXYGEN__)
+ #include "Host.h"
+ #include "Pipe.h"
+ #include "OTG.h"
+ #endif
+
+ #if defined(USB_CAN_BE_DEVICE) || defined(__DOXYGEN__)
+ #include "Device.h"
+ #include "Endpoint.h"
+ #include "DevChapter9.h"
+ #endif
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks and Defines: */
+ #if (F_CPU == 8000000)
+ #if (defined(__AVR_AT90USB82__) || defined(__AVR_AT90USB162__))
+ #define USB_PLL_PSC 0
+ #elif (defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || \
+ defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) || \
+ defined(__AVR_ATmega32U6__))
+ #define USB_PLL_PSC ((1 << PLLP1) | (1 << PLLP0))
+ #elif (defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__))
+ #define USB_PLL_PSC 0
+ #endif
+ #elif (F_CPU == 16000000)
+ #if (defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_ATmega32U6__))
+ #define USB_PLL_PSC ((1 << PLLP2) | (1 << PLLP1))
+ #elif (defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__))
+ #define USB_PLL_PSC ((1 << PLLP2) | (1 << PLLP0))
+ #elif (defined(__AVR_AT90USB82__) || defined(__AVR_AT90USB162__))
+ #define USB_PLL_PSC (1 << PLLP0)
+ #elif (defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__))
+ #define USB_PLL_PSC (1 << PINDIV)
+ #endif
+ #endif
+
+ #if !defined(USB_PLL_PSC)
+ #error No PLL prescale value available for chosen F_CPU value and AVR model.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Mode mask for the USB_CurrentMode global. This indicates that the USB interface is currently not
+ * initialized into any mode.
+ */
+ #define USB_MODE_NONE 0
+
+ /** Mode mask for the USB_CurrentMode global and the USB_Init() function. This indicates that the
+ * USB interface is or should be initialized in the USB device mode.
+ */
+ #define USB_MODE_DEVICE 1
+
+ /** Mode mask for the USB_CurrentMode global and the USB_Init() function. This indicates that the
+ * USB interface is or should be initialized in the USB host mode.
+ *
+ * \note Not all USB AVRs support host mode.
+ */
+ #define USB_MODE_HOST 2
+
+ /** Mode mask for the the USB_Init() function. This indicates that the USB interface should be
+ * initialized into whatever mode the UID pin of the USB AVR indicates, and that the device
+ * should swap over its mode when the level of the UID pin changes during operation.
+ *
+ * \note Not all USB AVRs support host mode, and thus UID mode.
+ */
+ #define USB_MODE_UID 3
+
+ /** Regulator disable option mask for USB_Init(). This indicates that the internal 3.3V USB data pad
+ * regulator should be enabled to regulate the data pin voltages to within the USB standard.
+ *
+ * \note See USB AVR data sheet for more information on the internal pad regulator.
+ */
+ #define USB_OPT_REG_DISABLED (1 << 1)
+
+ /** Regulator enable option mask for USB_Init(). This indicates that the internal 3.3V USB data pad
+ * regulator should be disabled and the AVR's VCC level used for the data pads.
+ *
+ * \note See USB AVR data sheet for more information on the internal pad regulator.
+ */
+ #define USB_OPT_REG_ENABLED (0 << 1)
+
+ /** Manual PLL control option mask for USB_Init(). This indicates to the library that the user application
+ * will take full responsibility for controlling the AVR's PLL (used to generate the high frequency clock
+ * that the USB controller requires) and ensuring that it is locked at the correct frequency for USB operations.
+ */
+ #define USB_OPT_MANUAL_PLL (1 << 2)
+
+ /** Automatic PLL control option mask for USB_Init(). This indicates to the library that the library should
+ * take full responsibility for controlling the AVR's PLL (used to generate the high frequency clock
+ * that the USB controller requires) and ensuring that it is locked at the correct frequency for USB operations.
+ */
+ #define USB_OPT_AUTO_PLL (0 << 2)
+
+ /** Mask for a CONTROL type endpoint or pipe.
+ *
+ * \note See Endpoint.h and Pipe.h headers for endpoint/pipe functions.
+ */
+ #define EP_TYPE_CONTROL 0b00
+
+ /** Mask for an ISOCHRONOUS type endpoint or pipe.
+ *
+ * \note See Endpoint.h and Pipe.h headers for endpoint/pipe functions.
+ */
+ #define EP_TYPE_ISOCHRONOUS 0b01
+
+ /** Mask for a BULK type endpoint or pipe.
+ *
+ * \note See Endpoint.h and Pipe.h headers for endpoint/pipe functions.
+ */
+ #define EP_TYPE_BULK 0b10
+
+ /** Mask for an INTERRUPT type endpoint or pipe.
+ *
+ * \note See Endpoint.h and Pipe.h headers for endpoint/pipe functions.
+ */
+ #define EP_TYPE_INTERRUPT 0b11
+
+ /** Mask for determining the type of an endpoint or pipe. This should then be compared with the
+ * EP_TYPE_* macros elsewhere in this module to determine the exact type of the endpoint or pipe.
+ *
+ * \note See Endpoint.h and Pipe.h headers for endpoint/pipe functions.
+ */
+ #define EP_TYPE_MASK 0b11
+
+ /** Returns boolean true if the VBUS line is currently high (i.e. the USB host is supplying power),
+ * otherwise returns false.
+ */
+ #define USB_VBUS_GetStatus() ((USBSTA & (1 << VBUS)) ? true : false)
+
+ /** Detaches the device from the USB bus. This has the effect of removing the device from any
+ * host if, ceasing USB communications. If no host is present, this prevents any host from
+ * enumerating the device once attached until USB_Attach() is called.
+ */
+ #define USB_Detach() MACROS{ UDCON |= (1 << DETACH); }MACROE
+
+ /** Attaches the device to the USB bus. This announces the device's presence to any attached
+ * USB host, starting the enumeration process. If no host is present, attaching the device
+ * will allow for enumeration once a host is connected to the device.
+ *
+ * This is inexplicably also required for proper operation while in host mode, to enable the
+ * attachment of a device to the host. This is despite the bit being located in the device-mode
+ * register and despite the datasheet making no mention of its requirement in host mode.
+ */
+ #define USB_Attach() MACROS{ UDCON &= ~(1 << DETACH); }MACROE
+
+ #if !defined(USB_STREAM_TIMEOUT_MS) || defined(__DOXYGEN__)
+ /** Constant for the maximum software timeout period of the USB data stream transfer functions
+ * (both control and standard) when in either device or host mode. If the next packet of a stream
+ * is not received or acknowedged within this time period, the stream function will fail.
+ *
+ * This value may be overridden in the user project makefile as the value of the
+ * USB_STREAM_TIMEOUT_MS token, and passed to the compiler using the -D switch.
+ */
+ #define USB_STREAM_TIMEOUT_MS 100
+ #endif
+
+ /* Function Prototypes: */
+ /** Main function to initialize and start the USB interface. Once active, the USB interface will
+ * allow for device connection to a host when in device mode, or for device enumeration while in
+ * host mode.
+ *
+ * As the USB library relies on USB interrupts for some of its functionality, this routine will
+ * enable global interrupts.
+ *
+ * Calling this function when the USB interface is already initialized will cause a complete USB
+ * interface reset and re-enumeration.
+ *
+ * \param Mode This is a mask indicating what mode the USB interface is to be initialized to.
+ * Valid mode masks are USB_MODE_DEVICE, USB_MODE_HOST or USB_MODE_UID.
+ *
+ * \param Options Mask indicating the options which should be used when initializing the USB
+ * interface to control the USB interface's behaviour. This should be comprised of
+ * a USB_OPT_REG_* mask to control the regulator, a USB_OPT_*_PLL mask to control the
+ * PLL, and a USB_DEVICE_OPT_* mask (when the device mode is enabled) to set the device
+ * mode speed.
+ *
+ * \note To reduce the FLASH requirements of the library if only device or host mode is required,
+ * this can be statically set via defining the token USB_DEVICE_ONLY for device mode or
+ * USB_HOST_ONLY for host mode in the use project makefile, passing the token to the compiler
+ * via the -D switch. If the mode is statically set, this parameter does not exist in the
+ * function prototype.
+ *
+ * \note To reduce the FLASH requirements of the library if only fixed settings are are required,
+ * the options may be set statically in the same manner as the mode (see the Mode parameter of
+ * this function). To statically set the USB options, pass in the USE_STATIC_OPTIONS token,
+ * defined to the appropriate options masks. When the options are statically set, this
+ * parameter does not exist in the function prototype.
+ *
+ * \note The mode parameter does not exist on devices where only one mode is possible, such as USB
+ * AVR models which only implement the USB device mode in hardware.
+ *
+ * \see Device.h for the USB_DEVICE_OPT_* masks.
+ */
+ void USB_Init(
+ #if defined(USB_CAN_BE_BOTH) || defined(__DOXYGEN__)
+ const uint8_t Mode
+ #endif
+
+ #if (defined(USB_CAN_BE_BOTH) && !defined(USE_STATIC_OPTIONS)) || defined(__DOXYGEN__)
+ ,
+ #elif (!defined(USB_CAN_BE_BOTH) && defined(USE_STATIC_OPTIONS))
+ void
+ #endif
+
+ #if !defined(USE_STATIC_OPTIONS) || defined(__DOXYGEN__)
+ const uint8_t Options
+ #endif
+ );
+
+ /** Shuts down the USB interface. This turns off the USB interface after deallocating all USB FIFO
+ * memory, endpoints and pipes. When turned off, no USB functionality can be used until the interface
+ * is restarted with the USB_Init() function.
+ */
+ void USB_ShutDown(void);
+
+ /** Resets the interface, when already initialized. This will re-enumerate the device if already connected
+ * to a host, or re-enumerate an already attached device when in host mode.
+ */
+ void USB_ResetInterface(void);
+
+ /* Enums: */
+ /** Enum for error codes relating to the powering on of the USB interface. These error codes are
+ * used in the ErrorCode parameter value of the USB_PowerOnFail event.
+ */
+ enum USB_PowerOnErrorCodes_t
+ {
+ POWERON_ERROR_NoUSBModeSpecified = 0, /**< Indicates that USB_Init() was called with an
+ * invalid or missing Mode parameter.
+ */
+ };
+
+ /* Global Variables: */
+ #if (!defined(USB_HOST_ONLY) && !defined(USB_DEVICE_ONLY)) || defined(__DOXYGEN__)
+ /** Indicates the mode that the USB interface is currently initialized to. This value will be
+ * one of the USB_MODE_* masks defined elsewhere in this module.
+ *
+ * \note This variable should be treated as read-only in the user application, and never manually
+ * changed in value.
+ */
+ extern volatile uint8_t USB_CurrentMode;
+ #endif
+
+ #if !defined(USE_STATIC_OPTIONS) || defined(__DOXYGEN__)
+ extern volatile uint8_t USB_Options;
+ /** Indicates the current USB options that the USB interface was initialized with when USB_Init()
+ * was called. This value will be one of the USB_MODE_* masks defined elsewhere in this module.
+ *
+ * \note This variable should be treated as read-only in the user application, and never manually
+ * changed in value.
+ */
+ #endif
+
+ /* Throwable Events: */
+ /** This module raises the USB_Disconnect event if the USB interface is reset (such as during a mode
+ * change while in UID mode) while the USB interface is connected to a device when in host mode, or
+ * a host while in device mode.
+ *
+ * \see Events.h for more information on this event.
+ */
+ RAISES_EVENT(USB_Disconnect);
+
+ #if defined(USB_CAN_BE_BOTH) || defined(__DOXYGEN__)
+ /** This module raises the Power On Failure event when an error occurs while initializing the USB
+ * interface.
+ *
+ * \see Events.h for more information on this event.
+ */
+ RAISES_EVENT(USB_PowerOnFail);
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define USB_PLL_On() MACROS{ PLLCSR = USB_PLL_PSC; PLLCSR |= (1 << PLLE); }MACROE
+ #define USB_PLL_Off() MACROS{ PLLCSR = 0; }MACROE
+ #define USB_PLL_IsReady() ((PLLCSR & (1 << PLOCK)) ? true : false)
+
+ #if defined(USB_FULL_CONTROLLER) || defined(USB_MODIFIED_FULL_CONTROLLER)
+ #define USB_REG_On() MACROS{ UHWCON |= (1 << UVREGE); }MACROE
+ #define USB_REG_Off() MACROS{ UHWCON &= ~(1 << UVREGE); }MACROE
+ #else
+ #define USB_REG_On() MACROS{ REGCR &= ~(1 << REGDIS); }MACROE
+ #define USB_REG_Off() MACROS{ REGCR |= (1 << REGDIS); }MACROE
+ #endif
+
+ #define USB_OTGPAD_On() MACROS{ USBCON |= (1 << OTGPADE); }MACROE
+ #define USB_OTGPAD_Off() MACROS{ USBCON &= ~(1 << OTGPADE); }MACROE
+
+ #define USB_CLK_Freeze() MACROS{ USBCON |= (1 << FRZCLK); }MACROE
+ #define USB_CLK_Unfreeze() MACROS{ USBCON &= ~(1 << FRZCLK); }MACROE
+
+ #define USB_Interface_Enable() MACROS{ USBCON |= (1 << USBE); }MACROE
+ #define USB_Interface_Disable() MACROS{ USBCON &= ~(1 << USBE); }MACROE
+ #define USB_Interface_Reset() MACROS{ uint8_t Temp = USBCON; USBCON = (Temp & ~(1 << USBE)); \
+ USBCON = (Temp | (1 << USBE)); }MACROE
+
+ /* Inline Functions: */
+ static inline uint8_t USB_GetUSBModeFromUID(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t USB_GetUSBModeFromUID(void)
+ {
+ #if (defined(__AVR_AT90USB1287__) || defined(__AVR_AT90USB647__))
+ if (USBSTA & (1 << ID))
+ return USB_MODE_DEVICE;
+ else
+ return USB_MODE_HOST;
+ #else
+ return USB_MODE_DEVICE;
+ #endif
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
diff --git a/LUFA/Drivers/USB/LowLevel/OTG.h b/LUFA/Drivers/USB/LowLevel/OTG.h new file mode 100644 index 000000000..e1a92f1eb --- /dev/null +++ b/LUFA/Drivers/USB/LowLevel/OTG.h @@ -0,0 +1,102 @@ +/*
+ 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
+ *
+ * Macros for embedded USB hosts with dual role On The Go capabilities, for managing role exchange. OTG
+ * is a way for two USB dual role devices to talk to one another directly without fixed device/host roles.
+ *
+ * \note These macros are only for AVRs which support the OTG protocol, and do not exist for device-only AVRs.
+ */
+
+#ifndef __USBOTG_H__
+#define __USBOTG_H__
+
+ /* Includes: */
+ #include <avr/io.h>
+ #include <stdbool.h>
+
+ #include "../../../Common/Common.h"
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Initiate a Host Negotiation Protocol request. This indicates to the other connected device
+ * that the device wishes to change device/host roles.
+ */
+ #define USB_OTG_DEV_Request_HNP() MACROS{ OTGCON |= (1 << HNPREQ); }MACROE
+
+ /** Cancel a Host Negotiation Protocol request. This stops a pending HNP request to the other
+ * connected device.
+ */
+ #define USB_OTG_DEV_Cancel_HNP_Request() MACROS{ OTGCON &= ~(1 << HNPREQ); }MACROE
+
+ /** Returns boolean false if not currently sending a HNP to the other connected device, or true
+ * if a HNP is currently being issued.
+ */
+ #define USB_OTG_DEV_IsSendingHNP() ((OTGCON & (1 << HNPREQ)) ? true : false)
+
+ /** Accepts a HNP from a connected device, indicating that both devices should exchange
+ * device/host roles.
+ */
+ #define USB_OTG_HOST_Accept_HNP() USB_OTG_DEV_Request_HNP()
+
+ /** Rejects a HNP from a connected device, indicating that both devices should remain in their
+ * current device/host roles.
+ */
+ #define USB_OTG_HOST_Reject_HNP() USB_OTG_DEV_Cancel_HNP_Request()
+
+ /** Returns boolean false if the connected device is not currently sending a HNP request, or true
+ * if a HNP is currently being issued by the connected device.
+ */
+ #define USB_OTG_HOST_IsHNPReceived() ((OTGCON & (1 << HNPREQ)) ? true : false)
+
+ /** Initiates a Session Request Protocol request. Most OTG devices turn off VBUS when the USB
+ * interface is not in use, to conserve power. Sending a SRP to a USB OTG device running in
+ * host mode indicates that VBUS should be applied and a session started.
+ *
+ * There are two different methods of sending a SRP - either pulses on the VBUS line, or by
+ * pulsing the Data + line via the internal pullup resistor. The SRP mode is given as the
+ * "type" parameter, and can be either USB_OTG_SRP_VBUS or USB_OTG_STP_DATA.
+ */
+ #define USB_OTG_DEV_Initiate_SRP(type) MACROS{ OTGCON = ((OTGCON & ~(1 << SRPSEL)) | (type | (1 << SRPREQ))); }MACROE
+
+ /** Mask for the VBUS pulsing method of SRP, supported by some OTG devices.
+ *
+ * \see USB_OTG_DEV_Initiate_SRP()
+ */
+ #define USB_OTG_SRP_VBUS (1 << SRPSEL)
+
+ /** Mask for the Data + pulsing method of SRP, supported by some OTG devices.
+ *
+ * \see USB_OTG_DEV_Initiate_SRP()
+ */
+ #define USB_OTG_STP_DATA 0
+
+#endif
diff --git a/LUFA/Drivers/USB/LowLevel/Pipe.c b/LUFA/Drivers/USB/LowLevel/Pipe.c new file mode 100644 index 000000000..743bb91f2 --- /dev/null +++ b/LUFA/Drivers/USB/LowLevel/Pipe.c @@ -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.
+*/
+#include "USBMode.h"
+#if defined(USB_CAN_BE_HOST)
+
+#define INCLUDE_FROM_PIPE_C
+#include "Pipe.h"
+
+uint8_t USB_ControlPipeSize = PIPE_CONTROLPIPE_DEFAULT_SIZE;
+
+bool Pipe_ConfigurePipe(const uint8_t Number, const uint8_t Type, const uint8_t Token, const uint8_t EndpointNumber,
+ const uint16_t Size, const uint8_t Banks)
+{
+ Pipe_SelectPipe(Number);
+ Pipe_EnablePipe();
+
+ UPCFG1X = 0;
+
+ UPCFG0X = ((Type << EPTYPE0) | Token | (EndpointNumber << PEPNUM0));
+ UPCFG1X = ((1 << ALLOC) | Banks | Pipe_BytesToEPSizeMask(Size));
+
+ return Pipe_IsConfigured();
+}
+
+void Pipe_ClearPipes(void)
+{
+ UPINT = 0;
+
+ for (uint8_t PNum = 0; PNum < PIPE_TOTAL_PIPES; PNum++)
+ {
+ Pipe_ResetPipe(PNum);
+ Pipe_SelectPipe(PNum);
+ UPIENX = 0;
+ UPINTX = 0;
+ Pipe_ClearError();
+ Pipe_ClearErrorFlags();
+ Pipe_DeallocateMemory();
+ Pipe_DisablePipe();
+ }
+}
+
+uint8_t Pipe_WaitUntilReady(void)
+{
+ uint8_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS;
+
+ USB_INT_Clear(USB_INT_HSOFI);
+
+ while (!(Pipe_ReadWriteAllowed()))
+ {
+ if (Pipe_IsStalled())
+ return PIPE_READYWAIT_PipeStalled;
+ else if (!(USB_IsConnected))
+ return PIPE_READYWAIT_DeviceDisconnected;
+
+ if (USB_INT_HasOccurred(USB_INT_HSOFI))
+ {
+ USB_INT_Clear(USB_INT_HSOFI);
+
+ if (!(TimeoutMSRem--))
+ return PIPE_READYWAIT_Timeout;
+ }
+ }
+
+ return PIPE_READYWAIT_NoError;
+}
+
+uint8_t Pipe_Write_Stream_LE(const void* Data, uint16_t Length
+#if !defined(NO_STREAM_CALLBACKS)
+ , uint8_t (* const Callback)(void)
+#endif
+ )
+{
+ uint8_t* DataStream = (uint8_t*)Data;
+ uint8_t ErrorCode;
+
+ if ((ErrorCode = Pipe_WaitUntilReady()))
+ return ErrorCode;
+
+ while (Length--)
+ {
+ if (!(Pipe_ReadWriteAllowed()))
+ {
+ Pipe_ClearCurrentBank();
+
+ #if !defined(NO_STREAM_CALLBACKS)
+ if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
+ return PIPE_RWSTREAM_ERROR_CallbackAborted;
+ #endif
+
+ if ((ErrorCode = Pipe_WaitUntilReady()))
+ return ErrorCode;
+ }
+
+ Pipe_Write_Byte(*(DataStream++));
+ }
+
+ return PIPE_RWSTREAM_ERROR_NoError;
+}
+
+uint8_t Pipe_Write_Stream_BE(const void* Data, uint16_t Length
+#if !defined(NO_STREAM_CALLBACKS)
+ , uint8_t (* const Callback)(void)
+#endif
+ )
+{
+ uint8_t* DataStream = (uint8_t*)(Data + Length - 1);
+ uint8_t ErrorCode;
+
+ if ((ErrorCode = Pipe_WaitUntilReady()))
+ return ErrorCode;
+
+ while (Length--)
+ {
+ if (!(Pipe_ReadWriteAllowed()))
+ {
+ Pipe_ClearCurrentBank();
+
+ #if !defined(NO_STREAM_CALLBACKS)
+ if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
+ return PIPE_RWSTREAM_ERROR_CallbackAborted;
+ #endif
+
+ if ((ErrorCode = Pipe_WaitUntilReady()))
+ return ErrorCode;
+ }
+
+ Pipe_Write_Byte(*(DataStream--));
+ }
+
+ return PIPE_RWSTREAM_ERROR_NoError;
+}
+
+uint8_t Pipe_Discard_Stream(uint16_t Length
+#if !defined(NO_STREAM_CALLBACKS)
+ , uint8_t (* const Callback)(void)
+#endif
+ )
+{
+ uint8_t ErrorCode;
+
+ if ((ErrorCode = Pipe_WaitUntilReady()))
+ return ErrorCode;
+
+ while (Length--)
+ {
+ if (!(Pipe_ReadWriteAllowed()))
+ {
+ Pipe_ClearCurrentBank();
+
+ #if !defined(NO_STREAM_CALLBACKS)
+ if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
+ return PIPE_RWSTREAM_ERROR_CallbackAborted;
+ #endif
+
+ if ((ErrorCode = Pipe_WaitUntilReady()))
+ return ErrorCode;
+ }
+
+ Pipe_Discard_Byte();
+ }
+
+ return PIPE_RWSTREAM_ERROR_NoError;
+}
+
+uint8_t Pipe_Read_Stream_LE(void* Buffer, uint16_t Length
+ #if !defined(NO_STREAM_CALLBACKS)
+ , uint8_t (* const Callback)(void)
+#endif
+ )
+{
+ uint8_t* DataStream = (uint8_t*)Buffer;
+ uint8_t ErrorCode;
+
+ if ((ErrorCode = Pipe_WaitUntilReady()))
+ return ErrorCode;
+
+ while (Length--)
+ {
+ if (!(Pipe_ReadWriteAllowed()))
+ {
+ Pipe_ClearCurrentBank();
+
+ #if !defined(NO_STREAM_CALLBACKS)
+ if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
+ return PIPE_RWSTREAM_ERROR_CallbackAborted;
+ #endif
+
+ if ((ErrorCode = Pipe_WaitUntilReady()))
+ return ErrorCode;
+ }
+
+ *(DataStream++) = Pipe_Read_Byte();
+ }
+
+ return PIPE_RWSTREAM_ERROR_NoError;
+}
+
+uint8_t Pipe_Read_Stream_BE(void* Buffer, uint16_t Length
+ #if !defined(NO_STREAM_CALLBACKS)
+ , uint8_t (* const Callback)(void)
+#endif
+ )
+{
+ uint8_t* DataStream = (uint8_t*)(Buffer + Length - 1);
+ uint8_t ErrorCode;
+
+ if ((ErrorCode = Pipe_WaitUntilReady()))
+ return ErrorCode;
+
+ while (Length--)
+ {
+ if (!(Pipe_ReadWriteAllowed()))
+ {
+ Pipe_ClearCurrentBank();
+
+ #if !defined(NO_STREAM_CALLBACKS)
+ if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
+ return PIPE_RWSTREAM_ERROR_CallbackAborted;
+ #endif
+
+ if ((ErrorCode = Pipe_WaitUntilReady()))
+ return ErrorCode;
+ }
+
+ *(DataStream--) = Pipe_Read_Byte();
+ }
+
+ return PIPE_RWSTREAM_ERROR_NoError;
+}
+
+#endif
diff --git a/LUFA/Drivers/USB/LowLevel/Pipe.h b/LUFA/Drivers/USB/LowLevel/Pipe.h new file mode 100644 index 000000000..a1f28ccc2 --- /dev/null +++ b/LUFA/Drivers/USB/LowLevel/Pipe.h @@ -0,0 +1,788 @@ +/*
+ 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
+ *
+ * Functions, macros and enums related to pipe management when in USB Host mode. This
+ * module contains the pipe management macros, as well as pipe interrupt and data
+ * send/recieve functions for various datatypes.
+ */
+
+#ifndef __PIPE_H__
+#define __PIPE_H__
+
+ /* Includes: */
+ #include <avr/io.h>
+ #include <stdbool.h>
+
+ #include "../../../Common/Common.h"
+ #include "../HighLevel/USBTask.h"
+
+ #if !defined(NO_STREAM_CALLBACKS) || defined(__DOXYGEN__)
+ #include "StreamCallbacks.h"
+ #endif
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Mask for Pipe_GetErrorFlags(), indicating that a CRC error occurred in the pipe on the received data. */
+ #define PIPE_ERRORFLAG_CRC16 (1 << 4)
+
+ /** Mask for Pipe_GetErrorFlags(), indicating that a hardware timeout error occurred in the pipe. */
+ #define PIPE_ERRORFLAG_TIMEOUT (1 << 3)
+
+ /** Mask for Pipe_GetErrorFlags(), indicating that a hardware PID error occurred in the pipe. */
+ #define PIPE_ERRORFLAG_PID (1 << 2)
+
+ /** Mask for Pipe_GetErrorFlags(), indicating that a hardware data PID error occurred in the pipe. */
+ #define PIPE_ERRORFLAG_DATAPID (1 << 1)
+
+ /** Mask for Pipe_GetErrorFlags(), indicating that a hardware data toggle error occurred in the pipe. */
+ #define PIPE_ERRORFLAG_DATATGL (1 << 0)
+
+ /** Token mask for Pipe_ConfigurePipe(). This sets the pipe as a SETUP token (for CONTROL type pipes),
+ * which will trigger a control request on the attached device when data is written to the pipe.
+ */
+ #define PIPE_TOKEN_SETUP (0b00 << PTOKEN0)
+
+ /** Token mask for Pipe_ConfigurePipe(). This sets the pipe as a IN token (for non-CONTROL type pipes),
+ * indicating that the pipe data will flow from device to host.
+ */
+ #define PIPE_TOKEN_IN (0b01 << PTOKEN0)
+
+ /** Token mask for Pipe_ConfigurePipe(). This sets the pipe as a IN token (for non-CONTROL type pipes),
+ * indicating that the pipe data will flow from host to device.
+ */
+ #define PIPE_TOKEN_OUT (0b10 << PTOKEN0)
+
+ /** Mask for the bank mode selection for the Pipe_ConfigurePipe() macro. This indicates that the pipe
+ * should have one single bank, which requires less USB FIFO memory but results in slower transfers as
+ * only one USB device (the AVR or the attached device) can access the pipe's bank at the one time.
+ */
+ #define PIPE_BANK_SINGLE 0
+
+ /** Mask for the bank mode selection for the Pipe_ConfigurePipe() macro. This indicates that the pipe
+ * should have two banks, which requires more USB FIFO memory but results in faster transfers as one
+ * USB device (the AVR or the attached device) can access one bank while the other accesses the second
+ * bank.
+ */
+ #define PIPE_BANK_DOUBLE (1 << EPBK0)
+
+ /** Pipe address for the default control pipe, which always resides in address 0. This is
+ * defined for convenience to give more readable code when used with the pipe macros.
+ */
+ #define PIPE_CONTROLPIPE 0
+
+ /** Default size of the default control pipe's bank, until altered by the Endpoint0Size value
+ * in the device descriptor of the attached device.
+ */
+ #define PIPE_CONTROLPIPE_DEFAULT_SIZE 8
+
+ /** Pipe number mask, for masking against pipe addresses to retrieve the pipe's numerical address
+ * in the device.
+ */
+ #define PIPE_PIPENUM_MASK 0x07
+
+ /** Total number of pipes (including the default control pipe at address 0) which may be used in
+ * the device. Different USB AVR models support different amounts of pipes, this value reflects
+ * the maximum number of pipes for the currently selected AVR model.
+ */
+ #define PIPE_TOTAL_PIPES 7
+
+ /** Size in bytes of the largest pipe bank size possible in the device. Not all banks on each AVR
+ * model supports the largest bank size possible on the device; different pipe numbers support
+ * different maximum bank sizes. This value reflects the largest possible bank of any pipe on the
+ * currently selected USB AVR model.
+ */
+ #define PIPE_MAX_SIZE 256
+
+ /** Endpoint number mask, for masking against endpoint addresses to retrieve the endpoint's
+ * numerical address in the attached device.
+ */
+ #define PIPE_EPNUM_MASK 0x07
+
+ /** Endpoint bank size mask, for masking against endpoint addresses to retrieve the endpoint's
+ * bank size in the attached device.
+ */
+ #define PIPE_EPSIZE_MASK 0x7FF
+
+ /** Interrupt definition for the pipe IN interrupt (for INTERRUPT type pipes). Should be used with
+ * the USB_INT_* macros located in USBInterrupt.h.
+ *
+ * This interrupt will fire if enabled on an INTERRUPT type pipe if the pipe interrupt period has
+ * elapsed and the pipe is ready for the next packet from the attached device to be read out from its
+ * FIFO buffer (if received).
+ *
+ * This interrupt must be enabled on *each* pipe which requires it (after the pipe is selected), and
+ * will fire the common pipe interrupt vector.
+ *
+ * \see ENDPOINT_PIPE_vect for more information on the common pipe and endpoint interrupt vector.
+ */
+ #define PIPE_INT_IN UPIENX, (1 << RXINE) , UPINTX, (1 << RXINI)
+
+ /** Interrupt definition for the pipe OUT interrupt (for INTERRUPT type pipes). Should be used with
+ * the USB_INT_* macros located in USBInterrupt.h.
+ *
+ * This interrupt will fire if enabled on an INTERRUPT type endpoint if a the pipe interrupt period
+ * has elapsed and the pipe is ready for a packet to be written to the pipe's FIFO buffer and sent
+ * to the attached device (if required).
+ *
+ * This interrupt must be enabled on *each* pipe which requires it (after the pipe is selected), and
+ * will fire the common pipe interrupt vector.
+ *
+ * \see ENDPOINT_PIPE_vect for more information on the common pipe and endpoint interrupt vector. */
+ #define PIPE_INT_OUT UPIENX, (1 << TXOUTE), UPINTX, (1 << TXOUTI)
+
+ /** Interrupt definition for the pipe SETUP bank ready interrupt (for CONTROL type pipes). Should be
+ * used with the USB_INT_* macros located in USBInterrupt.h.
+ *
+ * This interrupt will fire if enabled on an CONTROL type pipe when the pipe is ready for a new
+ * control request.
+ *
+ * This interrupt must be enabled on *each* pipe which requires it (after the pipe is selected), and
+ * will fire the common pipe interrupt vector.
+ *
+ * \see ENDPOINT_PIPE_vect for more information on the common pipe and endpoint interrupt vector.
+ */
+ #define PIPE_INT_SETUP UPIENX, (1 << TXSTPE) , UPINTX, (1 << TXSTPI)
+
+ /** Interrupt definition for the pipe error interrupt. Should be used with the USB_INT_* macros
+ * located in USBInterrupt.h.
+ *
+ * This interrupt will fire if enabled on a particular pipe if an error occurs on that pipe, such
+ * as a CRC mismatch error.
+ *
+ * This interrupt must be enabled on *each* pipe which requires it (after the pipe is selected), and
+ * will fire the common pipe interrupt vector.
+ *
+ * \see ENDPOINT_PIPE_vect for more information on the common pipe and endpoint interrupt vector.
+ *
+ * \see Pipe_GetErrorFlags() for more information on the pipe errors.
+ */
+ #define PIPE_INT_ERROR UPIENX, (1 << PERRE), UPINTX, (1 << PERRI)
+
+ /** Interrupt definition for the pipe NAK received interrupt. Should be used with the USB_INT_* macros
+ * located in USBInterrupt.h.
+ *
+ * This interrupt will fire if enabled on a particular pipe if an attached device returns a NAK in
+ * response to a sent packet.
+ *
+ * This interrupt must be enabled on *each* pipe which requires it (after the pipe is selected), and
+ * will fire the common pipe interrupt vector.
+ *
+ * \see ENDPOINT_PIPE_vect for more information on the common pipe and endpoint interrupt vector.
+ *
+ * \see Pipe_IsNAKReceived() for more information on pipe NAKs.
+ */
+ #define PIPE_INT_NAK UPIENX, (1 << NAKEDE), UPINTX, (1 << NAKEDI)
+
+ /** Interrupt definition for the pipe STALL received interrupt. Should be used with the USB_INT_* macros
+ * located in USBInterrupt.h.
+ *
+ * This interrupt will fire if enabled on a particular pipe if an attached device returns a STALL on the
+ * currently selected pipe. This will also fire if the pipe is an isochronous pipe and a CRC error occurs.
+ *
+ * This interrupt must be enabled on *each* pipe which requires it (after the pipe is selected), and
+ * will fire the common pipe interrupt vector.
+ *
+ * \see ENDPOINT_PIPE_vect for more information on the common pipe and endpoint interrupt vector.
+ */
+ #define PIPE_INT_STALL UPIENX, (1 << RXSTALLE), UPINTX, (1 << RXSTALLI)
+
+ /** Indicates the number of bytes currently stored in the current pipe's selected bank. */
+ #define Pipe_BytesInPipe() UPBCX
+
+ /** Resets the desired pipe, including the pipe banks and flags. */
+ #define Pipe_ResetPipe(pipenum) MACROS{ UPRST = (1 << pipenum); UPRST = 0; }MACROE
+
+ /** Selects the given pipe number. Any pipe operations which do not require the pipe number to be
+ * indicated will operate on the currently selected pipe.
+ */
+ #define Pipe_SelectPipe(pipenum) MACROS{ UPNUM = pipenum; }MACROE
+
+ /** Returns the pipe address of the currently selected pipe. This is typically used to save the
+ * currently selected pipe number so that it can be restored after another pipe has been manipulated.
+ */
+ #define Pipe_GetCurrentPipe() (UPNUM & PIPE_PIPENUM_MASK)
+
+ /** Enables the currently selected pipe so that data can be sent and received through it to and from
+ * an attached device.
+ *
+ * \note Pipes must first be configured properly rather than just being enabled via the
+ * Pipe_ConfigurePipe() macro, which calls Pipe_EnablePipe() automatically.
+ */
+ #define Pipe_EnablePipe() MACROS{ UPCONX |= (1 << PEN); }MACROE
+
+ /** Disables the currently selected pipe so that data cannot be sent and received through it to and
+ * from an attached device.
+ */
+ #define Pipe_DisablePipe() MACROS{ UPCONX &= ~(1 << PEN); }MACROE
+
+ /** Returns true if the currently selected pipe is enabled, false otherwise. */
+ #define Pipe_IsEnabled() ((UPCONX & (1 << PEN)) ? true : false)
+
+ /** Sets the token for the currently selected endpoint to one of the tokens specified by the PIPE_TOKEN_*
+ * masks. This should only be used on CONTROL type endpoints, to allow for bidirectional transfer of
+ * data during control requests.
+ */
+ #define Pipe_SetToken(token) MACROS{ UPCFG0X = ((UPCFG0X & ~PIPE_TOKEN_MASK) | token); }MACROE
+
+ /** Configures the currently selected pipe to allow for an unlimited number of IN requests. */
+ #define Pipe_SetInfiniteINRequests() MACROS{ UPCONX |= (1 << INMODE); }MACROE
+
+ /** Configures the currently selected pipe to only allow the specified number of IN requests to be
+ * accepted by the pipe before it is automatically frozen.
+ */
+ #define Pipe_SetFiniteINRequests(n) MACROS{ UPCONX &= ~(1 << INMODE); UPINRQX = n; }MACROE
+
+ /** Returns true if the currently selected pipe is configured, false otherwise. */
+ #define Pipe_IsConfigured() ((UPSTAX & (1 << CFGOK)) ? true : false)
+
+ /** Sets the period between interrupts for an INTERRUPT type pipe to a specified number of milliseconds. */
+ #define Pipe_SetInterruptPeriod(ms) MACROS{ UPCFG2X = ms; }MACROE
+
+ /** Returns a mask indicating which pipe's interrupt periods have elapsed, indicating that the pipe should
+ * be serviced.
+ */
+ #define Pipe_GetPipeInterrupts() UPINT
+
+ /** Clears the interrupt flag for the specified pipe number. */
+ #define Pipe_ClearPipeInterrupt(n) MACROS{ UPINT &= ~(1 << n); }MACROE
+
+ /** Returns true if the specified pipe's interrupt period has elapsed, false otherwise. */
+ #define Pipe_HasPipeInterrupted(n) ((UPINT & (1 << n)) ? true : false)
+
+ /** Clears the pipe bank, and switches to the alternate bank if the currently selected pipe is
+ * dual-banked. When cleared, this either frees the bank up for the next packet from the host
+ * (if the endpoint is of the OUT direction) or sends the packet contents to the host (if the
+ * pipe is of the IN direction).
+ */
+ #define Pipe_ClearCurrentBank() MACROS{ UPINTX &= ~(1 << FIFOCON); }MACROE
+
+ /** Unfreezes the pipe, allowing it to communicate with an attached device. */
+ #define Pipe_Unfreeze() MACROS{ UPCONX &= ~(1 << PFREEZE); }MACROE
+
+ /** Freezes the pipe, preventing it from communicating with an attached device. */
+ #define Pipe_Freeze() MACROS{ UPCONX |= (1 << PFREEZE); }MACROE
+
+ /** Clears the master pipe error flag. */
+ #define Pipe_ClearError() MACROS{ UPINTX &= ~(1 << PERRI); }MACROE
+
+ /** Returns true if the master pipe error flag is set for the currently selected pipe, indicating that
+ * some sort of hardware error has occurred on the pipe.
+ *
+ * \see Pipe_GetErrorFlags() macro for information on retreiving the exact error flag.
+ */
+ #define Pipe_IsError() ((UPINTX & (1 << PERRI)) ? true : false)
+
+ /** Clears all the currently selected pipe's hardware error flags, but does not clear the master error
+ * flag for the pipe. */
+ #define Pipe_ClearErrorFlags() MACROS{ UPERRX = 0; }MACROE
+
+ /** Returns a mask of the hardware error flags which have occured on the currently selected pipe. This
+ * value can then be masked against the PIPE_ERRORFLAG_* masks to determine what error has occurred.
+ */
+ #define Pipe_GetErrorFlags() UPERRX
+
+ /** Returns true if the currently selected pipe may be read from (if data is waiting in the pipe
+ * bank and the pipe is an IN direction, or if the bank is not yet full if the pipe is an OUT
+ * direction). This function will return false if an error has occured in the pipe, or if the pipe
+ * is an IN direction and no packet has been received, or if the pipe is an OUT direction and the
+ * pipe bank is full.
+ */
+ #define Pipe_ReadWriteAllowed() ((UPINTX & (1 << RWAL)) ? true : false)
+
+ /** Clears the flag indicating that a SETUP request has been sent to the attached device from the
+ * currently selected CONTROL type pipe.
+ */
+ #define Pipe_ClearSetupSent() MACROS{ UPINTX &= ~(1 << TXSTPI); }MACROE
+
+ /** Returns true if no SETUP request is currently being sent to the attached device, false otherwise. */
+ #define Pipe_IsSetupSent() ((UPINTX & (1 << TXSTPI)) ? true : false)
+
+ /** Returns true if the currently selected pipe has been stalled by the attached device, false otherwise. */
+ #define Pipe_IsStalled() ((UPINTX & (1 << RXSTALLI)) ? true : false)
+
+ /** Clears the stall condition on the currently selected pipe. */
+ #define Pipe_ClearStall() MACROS{ UPINTX &= ~(1 << RXSTALLI); }MACROE
+
+ /** Returns true if an IN request has been received on the currently selected CONTROL type pipe, false
+ * otherwise.
+ */
+ #define Pipe_IsSetupINReceived() ((UPINTX & (1 << RXINI)) ? true : false)
+
+ /** Returns true if the currently selected CONTROL type pipe is ready to send an OUT request, false
+ * otherwise.
+ */
+ #define Pipe_IsSetupOUTReady() ((UPINTX & (1 << TXOUTI)) ? true : false)
+
+ /** Acknowedges the reception of a setup IN request from the attached device on the currently selected
+ * CONTROL type endpoint, allowing for the transmission of a setup OUT packet, or the reception of
+ * another setup IN packet.
+ */
+ #define Pipe_ClearSetupIN() MACROS{ UPINTX &= ~(1 << RXINI); UPINTX &= ~(1 << FIFOCON); }MACROE
+
+ /** Sends the currently selected CONTROL type pipe's contents to the device as a setup OUT packet. */
+ #define Pipe_ClearSetupOUT() MACROS{ UPINTX &= ~(1 << TXOUTI); UPINTX &= ~(1 << FIFOCON); }MACROE
+
+ /** Returns true if the device sent a NAK (Negative Acknowedge) in response to the last sent packet on
+ * the currently selected pipe. This ocurrs when the host sends a packet to the device, but the device
+ * is not currently ready to handle the packet (i.e. its endpoint banks are full). Once a NAK has been
+ * received, it must be cleard using Pipe_ClearNAKReceived() before the previous (or any other) packet
+ * can be re-sent.
+ */
+ #define Pipe_IsNAKReceived() ((UPINTX & (1 << NAKEDI)) ? true : false)
+
+ /** Clears the NAK condition on the currently selected pipe.
+ *
+ * \see Pipe_IsNAKReceived() for more details.
+ */
+ #define Pipe_ClearNAKReceived() MACROS{ UPINTX &= ~(1 << NAKEDI); }MACROE
+
+ /* Enums: */
+ /** Enum for the possible error return codes of the Pipe_WaitUntilReady function */
+ enum Pipe_WaitUntilReady_ErrorCodes_t
+ {
+ PIPE_READYWAIT_NoError = 0, /**< Pipe ready for next packet, no error */
+ PIPE_READYWAIT_PipeStalled = 1, /**< The device stalled the pipe while waiting. */
+ PIPE_READYWAIT_DeviceDisconnected = 2, /**< Device was disconnected from the host while waiting. */
+ PIPE_READYWAIT_Timeout = 3, /**< The device failed to accept or send the next packet
+ * within the software timeout period set by the
+ * USB_STREAM_TIMEOUT_MS macro.
+ */
+ };
+
+ /** Enum for the possible error return codes of the Pipe_*_Stream_* functions. */
+ enum Pipe_Stream_RW_ErrorCodes_t
+ {
+ PIPE_RWSTREAM_ERROR_NoError = 0, /**< Command completed successfully, no error. */
+ PIPE_RWSTREAM_ERROR_PipeStalled = 1, /**< The device stalled the pipe during the transfer. */
+ PIPE_RWSTREAM_ERROR_DeviceDisconnected = 2, /**< Device was disconnected from the host during
+ * the transfer.
+ */
+ PIPE_RWSTREAM_ERROR_Timeout = 3, /**< The device failed to accept or send the next packet
+ * within the software timeout period set by the
+ * USB_STREAM_TIMEOUT_MS macro.
+ */
+ PIPE_RWSTREAM_ERROR_CallbackAborted = 4, /**< Indicates that the stream's callback function aborted
+ * the transfer early.
+ */
+ };
+
+ /* Inline Functions: */
+ /** Reads one byte from the currently selected pipe's bank, for OUT direction pipes. */
+ static inline uint8_t Pipe_Read_Byte(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Pipe_Read_Byte(void)
+ {
+ return UPDATX;
+ }
+
+ /** Writes one byte from the currently selected pipe's bank, for IN direction pipes. */
+ static inline void Pipe_Write_Byte(const uint8_t Byte)
+ {
+ UPDATX = Byte;
+ }
+
+ /** Discards one byte from the currently selected pipe's bank, for OUT direction pipes. */
+ static inline void Pipe_Discard_Byte(void)
+ {
+ uint8_t Dummy;
+
+ Dummy = UPDATX;
+ }
+
+ /** Reads two bytes from the currently selected pipe's bank in little endian format, for OUT
+ * direction pipes.
+ */
+ static inline uint16_t Pipe_Read_Word_LE(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint16_t Pipe_Read_Word_LE(void)
+ {
+ uint16_t Data;
+
+ Data = UPDATX;
+ Data |= (((uint16_t)UPDATX) << 8);
+
+ return Data;
+ }
+
+ /** Reads two bytes from the currently selected pipe's bank in big endian format, for OUT
+ * direction pipes.
+ */
+ static inline uint16_t Pipe_Read_Word_BE(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint16_t Pipe_Read_Word_BE(void)
+ {
+ uint16_t Data;
+
+ Data = (((uint16_t)UPDATX) << 8);
+ Data |= UPDATX;
+
+ return Data;
+ }
+
+ /** Writes two bytes to the currently selected pipe's bank in little endian format, for IN
+ * direction pipes.
+ */
+ static inline void Pipe_Write_Word_LE(const uint16_t Word)
+ {
+ UPDATX = (Word & 0xFF);
+ UPDATX = (Word >> 8);
+ }
+
+ /** Writes two bytes to the currently selected pipe's bank in big endian format, for IN
+ * direction pipes.
+ */
+ static inline void Pipe_Write_Word_BE(const uint16_t Word)
+ {
+ UPDATX = (Word >> 8);
+ UPDATX = (Word & 0xFF);
+ }
+
+ /** Discards two bytes from the currently selected pipe's bank, for OUT direction pipes. */
+ static inline void Pipe_Ignore_Word(void)
+ {
+ uint8_t Dummy;
+
+ Dummy = UPDATX;
+ Dummy = UPDATX;
+ }
+
+ /** Reads four bytes from the currently selected pipe's bank in little endian format, for OUT
+ * direction pipes.
+ */
+ static inline uint32_t Pipe_Read_DWord_LE(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint32_t Pipe_Read_DWord_LE(void)
+ {
+ union
+ {
+ uint32_t DWord;
+ uint8_t Bytes[4];
+ } Data;
+
+ Data.Bytes[0] = UPDATX;
+ Data.Bytes[1] = UPDATX;
+ Data.Bytes[2] = UPDATX;
+ Data.Bytes[3] = UPDATX;
+
+ return Data.DWord;
+ }
+
+ /** Reads four bytes from the currently selected pipe's bank in big endian format, for OUT
+ * direction pipes.
+ */
+ static inline uint32_t Pipe_Read_DWord_BE(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint32_t Pipe_Read_DWord_BE(void)
+ {
+ union
+ {
+ uint32_t DWord;
+ uint8_t Bytes[4];
+ } Data;
+
+ Data.Bytes[3] = UPDATX;
+ Data.Bytes[2] = UPDATX;
+ Data.Bytes[1] = UPDATX;
+ Data.Bytes[0] = UPDATX;
+
+ return Data.DWord;
+ }
+
+ /** Writes four bytes to the currently selected pipe's bank in little endian format, for IN
+ * direction pipes.
+ */
+ static inline void Pipe_Write_DWord_LE(const uint32_t DWord)
+ {
+ Pipe_Write_Word_LE(DWord);
+ Pipe_Write_Word_LE(DWord >> 16);
+ }
+
+ /** Writes four bytes to the currently selected pipe's bank in big endian format, for IN
+ * direction pipes.
+ */
+ static inline void Pipe_Write_DWord_BE(const uint32_t DWord)
+ {
+ Pipe_Write_Word_BE(DWord >> 16);
+ Pipe_Write_Word_BE(DWord);
+ }
+
+ /** Discards four bytes from the currently selected pipe's bank, for OUT direction pipes. */
+ static inline void Pipe_Ignore_DWord(void)
+ {
+ uint8_t Dummy;
+
+ Dummy = UPDATX;
+ Dummy = UPDATX;
+ Dummy = UPDATX;
+ Dummy = UPDATX;
+ }
+
+ /* External Variables: */
+ /** Global indicating the maximum packet size of the default control pipe located at address
+ * 0 in the device. This value is set to the value indicated in the attached device's device
+ * descriptor once the USB interface is initialized into host mode and a device is attached
+ * to the USB bus.
+ *
+ * \note This variable should be treated as read-only in the user application, and never manually
+ * changed in value.
+ */
+ extern uint8_t USB_ControlPipeSize;
+
+ /* Function Prototypes: */
+ /** Configures the specified pipe number with the given pipe type, token, target endpoint number in the
+ * attached device, bank size and banking mode. Pipes should be allocated in ascending order by their
+ * address in the device (i.e. pipe 1 should be configured before pipe 2 and so on).
+ *
+ * The pipe type may be one of the EP_TYPE_* macros listed in LowLevel.h, the token may be one of the
+ * PIPE_TOKEN_* masks.
+ *
+ * The bank size must indicate the maximum packet size that the pipe can handle. Different pipe
+ * numbers can handle different maximum packet sizes - refer to the chosen USB AVR's datasheet to
+ * determine the maximum bank size for each pipe.
+ *
+ * The banking mode may be either PIPE_BANK_SINGLE or PIPE_BANK_DOUBLE.
+ *
+ * A newly configured pipe is frozen by default, and must be unfrozen before use via the Pipe_Unfreeze() macro.
+ *
+ * \note This routine will select the specified pipe, and the pipe will remain selected once the
+ * routine completes regardless of if the pipe configuration succeeds.
+ *
+ * \return Boolean true if the configuration is successful, false otherwise
+ */
+ bool Pipe_ConfigurePipe(const uint8_t Number, const uint8_t Type, const uint8_t Token, const uint8_t EndpointNumber,
+ const uint16_t Size, const uint8_t Banks);
+
+ /** Spinloops until the currently selected non-control pipe is ready for the next packed of data
+ * to be read or written to it.
+ *
+ * \note This routine should not be called on CONTROL type pipes.
+ *
+ * \return A value from the Pipe_WaitUntilReady_ErrorCodes_t enum.
+ */
+ uint8_t Pipe_WaitUntilReady(void);
+
+ /** Writes the given number of bytes to the pipe from the given buffer in little endian,
+ * sending full packets to the device as needed. The last packet filled is not automatically sent;
+ * the user is responsible for manually sending the last written packet to the host via the
+ * Pipe_ClearCurrentBank() macro. Between each USB packet, the given stream callback function is
+ * executed repeatedly until the next packet is ready, allowing for early aborts of stream transfers.
+ *
+ * The callback routine should be created using the STREAM_CALLBACK() macro. If the token
+ * NO_STREAM_CALLBACKS is passed via the -D option to the compiler, stream callbacks are disabled
+ * and this function has the Callback parameter ommitted.
+ *
+ * \param Buffer Pointer to the source data buffer to read from.
+ * \param Length Number of bytes to read for the currently selected pipe into the buffer.
+ * \param Callback Name of a callback routine to call between sucessive USB packet transfers, NULL if no callback
+ *
+ * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Pipe_Write_Stream_LE(const void* Buffer, uint16_t Length
+ #if !defined(NO_STREAM_CALLBACKS) || defined(__DOXYGEN__)
+ , uint8_t (* const Callback)(void)
+ #endif
+ ) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Writes the given number of bytes to the pipe from the given buffer in big endian,
+ * sending full packets to the device as needed. The last packet filled is not automatically sent;
+ * the user is responsible for manually sending the last written packet to the host via the
+ * Pipe_ClearCurrentBank() macro. Between each USB packet, the given stream callback function is
+ * executed repeatedly until the next packet is ready, allowing for early aborts of stream transfers.
+ *
+ * The callback routine should be created using the STREAM_CALLBACK() macro. If the token
+ * NO_STREAM_CALLBACKS is passed via the -D option to the compiler, stream callbacks are disabled
+ * and this function has the Callback parameter ommitted.
+ *
+ * \param Buffer Pointer to the source data buffer to read from.
+ * \param Length Number of bytes to read for the currently selected pipe into the buffer.
+ * \param Callback Name of a callback routine to call between sucessive USB packet transfers, NULL if no callback
+ *
+ * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Pipe_Write_Stream_BE(const void* Buffer, uint16_t Length
+ #if !defined(NO_STREAM_CALLBACKS) || defined(__DOXYGEN__)
+ , uint8_t (* const Callback)(void)
+ #endif
+ ) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Reads and discards the given number of bytes from the pipe, discarding fully read packets from the host
+ * as needed. The last packet is not automatically discarded once the remaining bytes has been read; the
+ * user is responsible for manually discarding the last packet from the host via the Pipe_ClearCurrentBank() macro.
+ * Between each USB packet, the given stream callback function is executed repeatedly until the next packet is ready,
+ * allowing for early aborts of stream transfers.
+ *
+ * The callback routine should be created using the STREAM_CALLBACK() macro. If the token
+ * NO_STREAM_CALLBACKS is passed via the -D option to the compiler, stream callbacks are disabled
+ * and this function has the Callback parameter ommitted.
+ *
+ * \param Length Number of bytes to send via the currently selected pipe.
+ * \param Callback Name of a callback routine to call between sucessive USB packet transfers, NULL if no callback
+ *
+ * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Pipe_Discard_Stream(uint16_t Length
+ #if !defined(NO_STREAM_CALLBACKS) || defined(__DOXYGEN__)
+ , uint8_t (* const Callback)(void)
+ #endif
+ );
+
+ /** Reads the given number of bytes from the pipe into the given buffer in little endian,
+ * sending full packets to the device as needed. The last packet filled is not automatically sent;
+ * the user is responsible for manually sending the last written packet to the host via the
+ * Pipe_ClearCurrentBank() macro. Between each USB packet, the given stream callback function is
+ * executed repeatedly until the next packet is ready, allowing for early aborts of stream transfers.
+ *
+ * The callback routine should be created using the STREAM_CALLBACK() macro. If the token
+ * NO_STREAM_CALLBACKS is passed via the -D option to the compiler, stream callbacks are disabled
+ * and this function has the Callback parameter ommitted.
+ *
+ * \param Buffer Pointer to the source data buffer to write to.
+ * \param Length Number of bytes to read for the currently selected pipe to read from.
+ * \param Callback Name of a callback routine to call between sucessive USB packet transfers, NULL if no callback
+ *
+ * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Pipe_Read_Stream_LE(void* Buffer, uint16_t Length
+ #if !defined(NO_STREAM_CALLBACKS) || defined(__DOXYGEN__)
+ , uint8_t (* const Callback)(void)
+ #endif
+ ) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Reads the given number of bytes from the pipe into the given buffer in big endian,
+ * sending full packets to the device as needed. The last packet filled is not automatically sent;
+ * the user is responsible for manually sending the last written packet to the host via the
+ * Pipe_ClearCurrentBank() macro. Between each USB packet, the given stream callback function is
+ * executed repeatedly until the next packet is ready, allowing for early aborts of stream transfers.
+ *
+ * The callback routine should be created using the STREAM_CALLBACK() macro. If the token
+ * NO_STREAM_CALLBACKS is passed via the -D option to the compiler, stream callbacks are disabled
+ * and this function has the Callback parameter ommitted.
+ *
+ * \param Buffer Pointer to the source data buffer to write to.
+ * \param Length Number of bytes to read for the currently selected pipe to read from.
+ * \param Callback Name of a callback routine to call between sucessive USB packet transfers, NULL if no callback
+ *
+ * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Pipe_Read_Stream_BE(void* Buffer, uint16_t Length
+ #if !defined(NO_STREAM_CALLBACKS) || defined(__DOXYGEN__)
+ , uint8_t (* const Callback)(void)
+ #endif
+ ) ATTR_NON_NULL_PTR_ARG(1);
+
+ /* Function Aliases: */
+ /** Alias for Pipe_Discard_Byte().
+ */
+ #define Pipe_Ignore_Byte() Pipe_Discard_Byte()
+
+ /** Alias for Pipe_Discard_Word().
+ */
+ #define Pipe_Ignore_Word() Pipe_Discard_Word()
+
+ /** Alias for Pipe_Discard_DWord().
+ */
+ #define Pipe_Ignore_DWord() Pipe_Discard_DWord()
+
+ /** Alias for Pipe_Read_Word_LE(). By default USB transfers use little endian format, thus
+ * the command with no endianness specifier indicates little endian mode.
+ */
+ #define Pipe_Read_Word() Pipe_Read_Word_LE()
+
+ /** Alias for Pipe_Write_Word_LE(). By default USB transfers use little endian format, thus
+ * the command with no endianness specifier indicates little endian mode.
+ */
+ #define Pipe_Write_Word(Word) Pipe_Write_Word_LE(Word)
+
+ /** Alias for Pipe_Read_DWord_LE(). By default USB transfers use little endian format, thus
+ * the command with no endianness specifier indicates little endian mode.
+ */
+ #define Pipe_Read_DWord() Pipe_Read_DWord_LE()
+
+ /** Alias for Pipe_Write_DWord_LE(). By default USB transfers use little endian format, thus
+ * the command with no endianness specifier indicates little endian mode.
+ */
+ #define Pipe_Write_DWord(DWord) Pipe_Write_DWord_LE(DWord)
+
+ /** Alias for Pipe_Read_Stream_LE(). By default USB transfers use little endian format, thus
+ * the command with no endianness specifier indicates little endian mode.
+ */
+ #if !defined(NO_STREAM_CALLBACKS)
+ #define Pipe_Read_Stream(Buffer, Length, Callback) Pipe_Read_Stream_LE(Buffer, Length, Callback)
+ #else
+ #define Pipe_Read_Stream(Buffer, Length) Pipe_Read_Stream_LE(Buffer, Length)
+ #endif
+
+ /** Alias for Pipe_Write_Stream_LE(). By default USB transfers use little endian format, thus
+ * the command with no endianness specifier indicates little endian mode.
+ */
+ #if !defined(NO_STREAM_CALLBACKS)
+ #define Pipe_Write_Stream(Buffer, Length, Callback) Pipe_Read_Stream_LE(Buffer, Length, Callback)
+ #else
+ #define Pipe_Write_Stream(Buffer, Length) Pipe_Read_Stream_LE(Buffer, Length)
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define PIPE_TOKEN_MASK (0x03 << PTOKEN0)
+
+ #define Pipe_AllocateMemory() MACROS{ UPCFG1X |= (1 << ALLOC); }MACROE
+ #define Pipe_DeallocateMemory() MACROS{ UPCFG1X &= ~(1 << ALLOC); }MACROE
+
+ /* Function Prototypes: */
+ void Pipe_ClearPipes(void);
+
+ /* Inline Functions: */
+ static inline uint8_t Pipe_BytesToEPSizeMask(uint16_t Bytes) ATTR_WARN_UNUSED_RESULT ATTR_CONST ATTR_ALWAYSINLINE;
+ static inline uint8_t Pipe_BytesToEPSizeMask(uint16_t Bytes)
+ {
+ if (Bytes <= 8)
+ return (0 << EPSIZE0);
+ else if (Bytes <= 16)
+ return (1 << EPSIZE0);
+ else if (Bytes <= 32)
+ return (2 << EPSIZE0);
+ else if (Bytes <= 64)
+ return (3 << EPSIZE0);
+ else if (Bytes <= (8 << 4))
+ return (4 << EPSIZE0);
+ else
+ return (5 << EPSIZE0);
+ };
+
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
diff --git a/LUFA/Drivers/USB/LowLevel/StdRequestType.h b/LUFA/Drivers/USB/LowLevel/StdRequestType.h new file mode 100644 index 000000000..02d4fdc58 --- /dev/null +++ b/LUFA/Drivers/USB/LowLevel/StdRequestType.h @@ -0,0 +1,191 @@ +/*
+ 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
+ *
+ * Contains definitions for the various control request parameters, so that the request details (such as data
+ * direction, request recipient, etc.) can be extracted via masking.
+ */
+
+#ifndef __STDREQTYPE_H__
+#define __STDREQTYPE_H__
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Mask for the request type parameter, to indicate the direction of the request data (Host to Device
+ * or Device to Host). The result of this mask should then be compared to the request direction masks.
+ *
+ * \see REQDIR_* macros for masks indicating the request data direction.
+ */
+ #define CONTROL_REQTYPE_DIRECTION 0b10000000
+
+ /** Mask for the request type parameter, to indicate the type of request (Device, Class or Vendor
+ * Specific). The result of this mask should then be compared to the request type masks.
+ *
+ * \see REQTYPE_* macros for masks indicating the request type.
+ */
+ #define CONTROL_REQTYPE_TYPE 0b01100000
+
+ /** Mask for the request type parameter, to indicate the recipient of the request (Standard, Class
+ * or Vendor Specific). The result of this mask should then be compared to the request recipient
+ * masks.
+ *
+ * \see REQREC_* macros for masks indicating the request recipient.
+ */
+ #define CONTROL_REQTYPE_RECIPIENT 0b00011111
+
+ /** Request data direction mask, indicating that the request data will flow from host to device.
+ *
+ * \see CONTROL_REQTYPE_DIRECTION macro.
+ */
+ #define REQDIR_HOSTTODEVICE (0 << 7)
+
+ /** Request data direction mask, indicating that the request data will flow from device to host.
+ *
+ * \see CONTROL_REQTYPE_DIRECTION macro.
+ */
+ #define REQDIR_DEVICETOHOST (1 << 7)
+
+ /** Request type mask, indicating that the request is a standard request.
+ *
+ * \see CONTROL_REQTYPE_TYPE macro.
+ */
+ #define REQTYPE_STANDARD (0 << 5)
+
+ /** Request type mask, indicating that the request is a class-specific request.
+ *
+ * \see CONTROL_REQTYPE_TYPE macro.
+ */
+ #define REQTYPE_CLASS (1 << 5)
+
+ /** Request type mask, indicating that the request is a vendor specific request.
+ *
+ * \see CONTROL_REQTYPE_TYPE macro.
+ */
+ #define REQTYPE_VENDOR (2 << 5)
+
+ /** Request recipient mask, indicating that the request is to be issued to the device as a whole.
+ *
+ * \see CONTROL_REQTYPE_RECIPIENT macro.
+ */
+ #define REQREC_DEVICE (0 << 0)
+
+ /** Request recipient mask, indicating that the request is to be issued to an interface in the
+ * currently selected configuration.
+ *
+ * \see CONTROL_REQTYPE_RECIPIENT macro.
+ */
+ #define REQREC_INTERFACE (1 << 0)
+
+ /** Request recipient mask, indicating that the request is to be issued to an endpoint in the
+ * currently selected configuration.
+ *
+ * \see CONTROL_REQTYPE_RECIPIENT macro.
+ */
+ #define REQREC_ENDPOINT (2 << 0)
+
+ /** Request recipient mask, indicating that the request is to be issued to an unspecified element
+ * in the currently selected configuration.
+ *
+ * \see CONTROL_REQTYPE_RECIPIENT macro.
+ */
+ #define REQREC_OTHER (3 << 0)
+
+ /** Feature indicator for Clear Feature or Set Feature commands. When used in a Clear Feature
+ * request this indicates that an endpoint (whose address is given elsewhere in the request
+ * should have its stall condition cleared. If used in a similar manner inside a Set Feature
+ * request, this stalls an endpoint.
+ */
+ #define FEATURE_ENDPOINT_HALT 0x00
+
+ /** Feature indicator for Clear Feature or Set Feature commands. When used in a Clear Feature
+ * request this indicates that the remote wakeup enabled device should not issue remote
+ * wakeup requests until further notice. If used in a similar manner inside a Set Feature
+ * request, this re-enabled the remote wakeup feature on the device.
+ */
+ #define FEATURE_REMOTE_WAKEUP 0x01
+
+ /* Enums: */
+ /** Enumeration for the various standard request commands. These commands are applicable when the
+ * request type is REQTYPE_STANDARD (with the exception of REQ_GetDescriptor, which is always
+ * handled regardless of the request type value).
+ *
+ * \see Chapter 9 of the USB 2.0 Specification.
+ */
+ enum USB_Control_Request_t
+ {
+ REQ_GetStatus = 0, /**< Implemented in the library for device, endpoint and interface
+ * recipients. Passed to the user application for other recipients
+ * via the USB_UnhandledControlPacket() event when received in
+ * device mode. */
+ REQ_ClearFeature = 1, /**< Implemented in the library for device, endpoint and interface
+ * recipients. Passed to the user application for other recipients
+ * via the USB_UnhandledControlPacket() event when received in
+ * device mode. */
+ REQ_SetFeature = 3, /**< Implemented in the library for device, endpoint and interface
+ * recipients. Passed to the user application for other recipients
+ * via the USB_UnhandledControlPacket() event when received in
+ * device mode. */
+ REQ_SetAddress = 5, /**< Implemented in the library for the device recipient. Passed
+ * to the user application for other recipients via the
+ * USB_UnhandledControlPacket() event when received in
+ * device mode. */
+ REQ_GetDescriptor = 6, /**< Implemented in the library for all recipients and all request
+ * types. */
+ REQ_SetDescriptor = 7, /**< Not implemented in the library, passed to the user application
+ * via the USB_UnhandledControlPacket() event when received in
+ * device mode. */
+ REQ_GetConfiguration = 8, /**< Implemented in the library for the device recipient. Passed
+ * to the user application for other recipients via the
+ * USB_UnhandledControlPacket() event when received in
+ * device mode. */
+ REQ_SetConfiguration = 9, /**< Implemented in the library for the device recipient. Passed
+ * to the user application for other recipients via the
+ * USB_UnhandledControlPacket() event when received in
+ * device mode. */
+ REQ_GetInterface = 10, /**< Not implemented in the library, passed to the user application
+ * via the USB_UnhandledControlPacket() event when received in
+ * device mode. */
+ REQ_SetInterface = 11, /**< Not implemented in the library, passed to the user application
+ * via the USB_UnhandledControlPacket() event when received in
+ * device mode. */
+ REQ_SynchFrame = 12, /**< Not implemented in the library, passed to the user application
+ * via the USB_UnhandledControlPacket() event when received in
+ * device mode. */
+ };
+
+/* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define FEATURE_SELFPOWERED_ENABLED (1 << 0)
+ #define FEATURE_REMOTE_WAKEUP_ENABLED (1 << 1)
+ #endif
+
+#endif
diff --git a/LUFA/Drivers/USB/LowLevel/StreamCallbacks.h b/LUFA/Drivers/USB/LowLevel/StreamCallbacks.h new file mode 100644 index 000000000..60e408e9c --- /dev/null +++ b/LUFA/Drivers/USB/LowLevel/StreamCallbacks.h @@ -0,0 +1,87 @@ +/*
+ 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
+ *
+ * Macros and enums for the stream callback routines in Endpoint.h and Pipe.c. This module contains the
+ * code required to easily set up stream callback functions which can be used to force early abort of a
+ * stream read/write process.
+ */
+
+#ifndef __STREAMCALLBACK_H__
+#define __STREAMCALLBACK_H__
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Creates a prototype for or begins a stream callback routine. Stream callback routines are small
+ * routines which are executed during stream read or writes (if the callback-enabled versions of
+ * these functions are used) which allow the user application to abort the transfer when certain
+ * arbitrary conditions are met.
+ *
+ * Stream callback functions should return a value from the StreamCallback_Return_ErrorCodes_t
+ * enum.
+ *
+ * Usage Example (Device Endpoint, but applicable for Host pipes also):
+ * \code
+ * STREAM_CALLBACK(GlobalNotSet); // Callback Prototype
+ *
+ * STREAM_CALLBACK(GlobalNotSet)
+ * {
+ * if (MyGlobal == false)
+ * return ENDPOINT_STREAMCALLBACK_Continue;
+ * else
+ * return ENDPOINT_STREAMCALLBACK_Abort;
+ * }
+ *
+ * //...
+ * // Inside some routine:
+ * if (Endpoint_Write_CStream_LE(DataBuffer, sizeof(DataBuffer), GlobalNotSet) ==
+ * ENDPOINT_RWSTREAM_ERROR_CallbackAborted)
+ * {
+ * // Do something when the callback aborted the transfer early
+ * }
+ * \endcode
+ */
+ #define STREAM_CALLBACK(name) uint8_t name (void)
+
+ /** Used with the Endpoint and Pipe stream functions as the callback function parameter, indicating that the stream
+ * call has no callback function to be called between USB packets.
+ */
+ #define NO_STREAM_CALLBACK NULL
+
+ /* Enums: */
+ /** Enum for the possible error return codes of a stream callback function */
+ enum StreamCallback_Return_ErrorCodes_t
+ {
+ STREAMCALLBACK_Continue = 0, /**< Continue sending or receiving the stream. */
+ STREAMCALLBACK_Abort = 1, /**< Abort the stream send or reciving process. */
+ };
+
+#endif
diff --git a/LUFA/Drivers/USB/LowLevel/USBMode.h b/LUFA/Drivers/USB/LowLevel/USBMode.h new file mode 100644 index 000000000..f0fbf68df --- /dev/null +++ b/LUFA/Drivers/USB/LowLevel/USBMode.h @@ -0,0 +1,77 @@ +/*
+ 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.
+*/
+
+#ifndef __USBMODE_H__
+#define __USBMODE_H__
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #if ((defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB646__) || \
+ defined(__AVR_AT90USB162__) || defined(__AVR_AT90USB82__) || \
+ defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) || \
+ defined(__AVR_ATmega32U6__)) && !defined(USB_DEVICE_ONLY))
+ #define USB_DEVICE_ONLY
+ #endif
+
+ #if (defined(__AVR_AT90USB162__) || defined(__AVR_AT90USB82__))
+ #define USB_LIMITED_CONTROLLER
+ #elif (defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__))
+ #define USB_MODIFIED_FULL_CONTROLLER
+ #else
+ #define USB_FULL_CONTROLLER
+ #endif
+
+ #if (!defined(USB_DEVICE_ONLY) && !defined(USB_HOST_ONLY))
+ #define USB_CAN_BE_BOTH
+ #define USB_CAN_BE_HOST
+ #define USB_CAN_BE_DEVICE
+ #elif defined(USB_HOST_ONLY)
+ #define USB_CAN_BE_HOST
+ #define USB_CurrentMode USB_MODE_HOST
+ #elif defined(USB_DEVICE_ONLY)
+ #define USB_CAN_BE_DEVICE
+ #define USB_CurrentMode USB_MODE_DEVICE
+ #endif
+
+ #if (defined(USB_HOST_ONLY) && defined(USB_DEVICE_ONLY))
+ #error USB_HOST_ONLY and USB_DEVICE_ONLY are mutually exclusive.
+ #endif
+
+ #if (defined(USB_RAM_DESCRIPTORS) && defined(USE_EEPROM_DESCRIPTORS))
+ #error USB_RAM_DESCRIPTORS and USE_EEPROM_DESCRIPTORS are mutually exclusive.
+ #endif
+
+ #if defined(USE_STATIC_OPTIONS)
+ #define USB_Options USE_STATIC_OPTIONS
+ #endif
+ #endif
+
+#endif
diff --git a/LUFA/Drivers/USB/USB.h b/LUFA/Drivers/USB/USB.h new file mode 100644 index 000000000..e90d397ce --- /dev/null +++ b/LUFA/Drivers/USB/USB.h @@ -0,0 +1,83 @@ +/*
+ 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
+ *
+ * Master include file for the library USB functionality. This file should be included in all user projects making
+ * use of the USB portions of the library, instead of including any headers in the USB/LowLevel or USB/HighLevel
+ * directories.
+ *
+ * Class specific utility files in USB/Class/ must still be included manually, as they are not normally part of
+ * the USB library unless desired by the library user.
+ */
+
+#ifndef __USB_H__
+#define __USB_H__
+
+ /* Preprocessor Checks: */
+ #if (!(defined(__AVR_AT90USB1287__) || defined(__AVR_AT90USB647__)) && defined(USB_HOST_ONLY))
+ #error USB_HOST_ONLY is not available for the currently selected USB AVR model.
+ #endif
+
+ #if (!(defined(__AVR_AT90USB1287__) || defined(__AVR_AT90USB647__) || \
+ defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB646__) || \
+ defined(__AVR_AT90USB162__) || defined(__AVR_AT90USB82__) || \
+ defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) || \
+ defined(__AVR_ATmega32U6__)))
+ #error The currently selected AVR model is not supported under the USB component of the LUFA library.
+ #endif
+
+ /* Includes: */
+ #include "LowLevel/USBMode.h"
+
+ #if defined(USB_CAN_BE_HOST) || defined(__DOXYGEN__)
+ #include "LowLevel/Host.h"
+ #include "LowLevel/HostChapter9.h"
+ #include "LowLevel/Pipe.h"
+ #endif
+
+ #if defined(USB_CAN_BE_DEVICE) || defined(__DOXYGEN__)
+ #include "LowLevel/Device.h"
+ #include "LowLevel/DevChapter9.h"
+ #include "LowLevel/Endpoint.h"
+ #endif
+
+ #if defined(USB_CAN_BE_BOTH) || defined(__DOXYGEN__)
+ #include "LowLevel/OTG.h"
+ #endif
+
+ #include "LowLevel/LowLevel.h"
+ #include "HighLevel/USBTask.h"
+ #include "HighLevel/USBInterrupt.h"
+ #include "HighLevel/Events.h"
+ #include "HighLevel/StdDescriptors.h"
+
+#endif
+
|