Moved all source to the trunk directory.

This commit is contained in:
Dean Camera 2009-02-23 07:08:22 +00:00
parent 9991321321
commit 6a10d6b465
88 changed files with 15575 additions and 0 deletions

View file

@ -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;
}

View file

@ -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

View file

@ -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;
}
}

View file

@ -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

View file

@ -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

View file

@ -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)
{
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

83
LUFA/Drivers/USB/USB.h Normal file
View file

@ -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