summaryrefslogtreecommitdiff
path: root/LUFA/Drivers/USB/LowLevel
diff options
context:
space:
mode:
Diffstat (limited to 'LUFA/Drivers/USB/LowLevel')
-rw-r--r--LUFA/Drivers/USB/LowLevel/Device.c53
-rw-r--r--LUFA/Drivers/USB/LowLevel/Device.h247
-rw-r--r--LUFA/Drivers/USB/LowLevel/Endpoint.c141
-rw-r--r--LUFA/Drivers/USB/LowLevel/Endpoint.h892
-rw-r--r--LUFA/Drivers/USB/LowLevel/Host.c355
-rw-r--r--LUFA/Drivers/USB/LowLevel/Host.h527
-rw-r--r--LUFA/Drivers/USB/LowLevel/OTG.h155
-rw-r--r--LUFA/Drivers/USB/LowLevel/Pipe.c140
-rw-r--r--LUFA/Drivers/USB/LowLevel/Pipe.h941
-rw-r--r--LUFA/Drivers/USB/LowLevel/USBController.c232
-rw-r--r--LUFA/Drivers/USB/LowLevel/USBController.h471
-rw-r--r--LUFA/Drivers/USB/LowLevel/USBInterrupt.c269
-rw-r--r--LUFA/Drivers/USB/LowLevel/USBInterrupt.h106
13 files changed, 4529 insertions, 0 deletions
diff --git a/LUFA/Drivers/USB/LowLevel/Device.c b/LUFA/Drivers/USB/LowLevel/Device.c
new file mode 100644
index 0000000..917fc19
--- /dev/null
+++ b/LUFA/Drivers/USB/LowLevel/Device.c
@@ -0,0 +1,53 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2010.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, 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.
+*/
+
+#define __INCLUDE_FROM_USB_DRIVER
+#include "../HighLevel/USBMode.h"
+
+#if defined(USB_CAN_BE_DEVICE)
+
+#include "Device.h"
+
+void USB_Device_SendRemoteWakeup(void)
+{
+ if (!(USB_Options & USB_OPT_MANUAL_PLL))
+ {
+ USB_PLL_On();
+ while (!(USB_PLL_IsReady()));
+ }
+
+ USB_CLK_Unfreeze();
+
+ UDCON |= (1 << RMWKUP);
+ while (!(UDCON & (1 << RMWKUP)));
+}
+
+#endif
+
diff --git a/LUFA/Drivers/USB/LowLevel/Device.h b/LUFA/Drivers/USB/LowLevel/Device.h
new file mode 100644
index 0000000..631c883
--- /dev/null
+++ b/LUFA/Drivers/USB/LowLevel/Device.h
@@ -0,0 +1,247 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2010.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, 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
+ * \brief USB device mode definitions.
+ *
+ * This file contains structures, function prototypes and macros related to USB device mode.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB driver
+ * dispatch header located in LUFA/Drivers/USB/USB.h.
+ */
+
+/** \ingroup Group_USB
+ * @defgroup Group_Device Device Management
+ *
+ * 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/io.h>
+ #include <avr/pgmspace.h>
+ #include <avr/eeprom.h>
+
+ #include "../../../Common/Common.h"
+ #include "../HighLevel/StdDescriptors.h"
+ #include "USBInterrupt.h"
+ #include "Endpoint.h"
+
+ /* Preprocessor Checks: */
+ #if (defined(USE_RAM_DESCRIPTORS) && defined(USE_EEPROM_DESCRIPTORS))
+ #error USE_RAM_DESCRIPTORS and USE_EEPROM_DESCRIPTORS are mutually exclusive.
+ #endif
+
+ #if !defined(__INCLUDE_FROM_USB_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** \name USB Device Mode Option Masks */
+ //@{
+ #if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR) || defined(__DOXYGEN__)
+ /** Mask for the Options parameter of the \ref 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.
+ * \n
+ *
+ * \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 specification.
+ */
+ #define USB_DEVICE_OPT_LOWSPEED (1 << 0)
+ #endif
+
+ /** Mask for the Options parameter of the \ref 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)
+ //@}
+
+ /* Function Prototypes: */
+ /** 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 \ref USB_RemoteWakeupEnabled flag is set). When the NO_DEVICE_REMOTE_WAKEUP compile
+ * time option is used, this macro is unavailable.
+ * \n\n
+ *
+ * \note The USB clock must be running for this function to operate. If the stack is initialized with
+ * the \ref USB_OPT_MANUAL_PLL option enabled, the user must ensure that the PLL is running
+ * before attempting to call this function.
+ *
+ * \see \ref Group_Descriptors for more information on the RMWAKEUP feature and device descriptors.
+ */
+ void USB_Device_SendRemoteWakeup(void);
+
+ /* Type Defines: */
+ enum USB_Device_States_t
+ {
+ DEVICE_STATE_Unattached = 0, /**< Internally implemented by the library. This state indicates
+ * that the device is not currently connected to a host.
+ */
+ DEVICE_STATE_Powered = 1, /**< Internally implemented by the library. This state indicates
+ * that the device is connected to a host, but enumeration has not
+ * yet begun.
+ */
+ DEVICE_STATE_Default = 2, /**< Internally implemented by the library. This state indicates
+ * that the device's USB bus has been reset by the host and it is
+ * now waiting for the host to begin the enumeration process.
+ */
+ DEVICE_STATE_Addressed = 3, /**< Internally implemented by the library. This state indicates
+ * that the device has been addressed by the USB Host, but is not
+ * yet configured.
+ */
+ DEVICE_STATE_Configured = 4, /**< May be implemented by the user project. This state indicates
+ * that the device has been enumerated by the host and is ready
+ * for USB communications to begin.
+ */
+ DEVICE_STATE_Suspended = 5, /**< May be implemented by the user project. This state indicates
+ * that the USB bus has been suspended by the host, and the device
+ * should power down to a minimal power level until the bus is
+ * resumed.
+ */
+ };
+
+ /* Inline Functions: */
+ /** Returns the current USB frame number, when in device mode. Every millisecond the USB bus is active (i.e. enumerated to a host)
+ * the frame number is incremented by one.
+ */
+ static inline uint16_t USB_Device_GetFrameNumber(void)
+ {
+ return UDFNUM;
+ }
+
+ #if !defined(NO_SOF_EVENTS)
+ /** Enables the device mode Start Of Frame events. When enabled, this causes the
+ * \ref EVENT_USB_Device_StartOfFrame() event to fire once per millisecond, synchronized to the USB bus,
+ * at the start of each USB frame when enumerated in device mode.
+ *
+ * \note Not available when the NO_SOF_EVENTS compile time token is defined.
+ */
+ static inline void USB_Device_EnableSOFEvents(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Device_EnableSOFEvents(void)
+ {
+ USB_INT_Enable(USB_INT_SOFI);
+ }
+
+ /** Disables the device mode Start Of Frame events. When disabled, this stops the firing of the
+ * \ref EVENT_USB_Device_StartOfFrame() event when enumerated in device mode.
+ *
+ * \note Not available when the NO_SOF_EVENTS compile time token is defined.
+ */
+ static inline void USB_Device_DisableSOFEvents(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Device_DisableSOFEvents(void)
+ {
+ USB_INT_Disable(USB_INT_SOFI);
+ }
+ #endif
+
+ /* 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 so that the library can call it to retrieve descriptor data.
+ *
+ * \param[in] 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[in] 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[out] DescriptorAddress Pointer to the descriptor in memory. This should be set by the routine to
+ * the address of the descriptor.
+ * \param[out] MemoryAddressSpace A value from the \ref USB_DescriptorMemorySpaces_t enum to indicate the memory
+ * space in which the descriptor is stored. This parameter does not exist when one
+ * of the USE_*_DESCRIPTORS compile time options is used.
+ *
+ * \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_RAM_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 \ref NO_DESCRIPTOR otherwise.
+ */
+ uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
+ const uint8_t wIndex,
+ const void** const DescriptorAddress
+ #if !defined(USE_FLASH_DESCRIPTORS) && !defined(USE_EEPROM_DESCRIPTORS) && !defined(USE_RAM_DESCRIPTORS)
+ , uint8_t* MemoryAddressSpace
+ #endif
+ ) ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Inline Functions: */
+ #if (defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR))
+ static inline void USB_Device_SetLowSpeed(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Device_SetLowSpeed(void)
+ {
+ UDCON |= (1 << LSM);
+ }
+
+ static inline void USB_Device_SetFullSpeed(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Device_SetFullSpeed(void)
+ {
+ UDCON &= ~(1 << LSM);
+ }
+ #endif
+
+ static inline void USB_Device_SetDeviceAddress(const uint8_t Address) ATTR_ALWAYS_INLINE;
+ static inline void USB_Device_SetDeviceAddress(const uint8_t Address)
+ {
+ UDADDR = ((UDADDR & (1 << ADDEN)) | (Address & 0x7F));
+ UDADDR |= (1 << ADDEN);
+ }
+
+ static inline bool USB_Device_IsAddressSet(void) ATTR_ALWAYS_INLINE;
+ static inline bool USB_Device_IsAddressSet(void)
+ {
+ return (UDADDR & (1 << ADDEN));
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/LUFA/Drivers/USB/LowLevel/Endpoint.c b/LUFA/Drivers/USB/LowLevel/Endpoint.c
new file mode 100644
index 0000000..6fb842b
--- /dev/null
+++ b/LUFA/Drivers/USB/LowLevel/Endpoint.c
@@ -0,0 +1,141 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2010.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, 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.
+*/
+
+#define __INCLUDE_FROM_USB_DRIVER
+#include "../HighLevel/USBMode.h"
+
+#if defined(USB_CAN_BE_DEVICE)
+
+#include "Endpoint.h"
+
+#if !defined(FIXED_CONTROL_ENDPOINT_SIZE)
+uint8_t USB_ControlEndpointSize = ENDPOINT_CONTROLEP_DEFAULT_SIZE;
+#endif
+
+bool Endpoint_ConfigureEndpoint_Prv(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();
+}
+
+void Endpoint_ClearEndpoints(void)
+{
+ UEINT = 0;
+
+ for (uint8_t EPNum = 0; EPNum < ENDPOINT_TOTAL_ENDPOINTS; EPNum++)
+ {
+ Endpoint_SelectEndpoint(EPNum);
+ UEIENX = 0;
+ UEINTX = 0;
+ UECFG1X = 0;
+ Endpoint_DisableEndpoint();
+ }
+}
+
+void Endpoint_ClearStatusStage(void)
+{
+ if (USB_ControlRequest.bmRequestType & REQDIR_DEVICETOHOST)
+ {
+ while (!(Endpoint_IsOUTReceived()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return;
+ }
+
+ Endpoint_ClearOUT();
+ }
+ else
+ {
+ while (!(Endpoint_IsINReady()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return;
+ }
+
+ Endpoint_ClearIN();
+ }
+}
+
+#if !defined(CONTROL_ONLY_DEVICE)
+uint8_t Endpoint_WaitUntilReady(void)
+{
+ #if (USB_STREAM_TIMEOUT_MS < 0xFF)
+ uint8_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS;
+ #else
+ uint16_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS;
+ #endif
+
+ uint16_t PreviousFrameNumber = USB_Device_GetFrameNumber();
+
+ for (;;)
+ {
+ if (Endpoint_GetEndpointDirection() == ENDPOINT_DIR_IN)
+ {
+ if (Endpoint_IsINReady())
+ return ENDPOINT_READYWAIT_NoError;
+ }
+ else
+ {
+ if (Endpoint_IsOUTReceived())
+ return ENDPOINT_READYWAIT_NoError;
+ }
+
+ uint8_t USB_DeviceState_LCL = USB_DeviceState;
+
+ if (USB_DeviceState_LCL == DEVICE_STATE_Unattached)
+ return ENDPOINT_READYWAIT_DeviceDisconnected;
+ else if (USB_DeviceState_LCL == DEVICE_STATE_Suspended)
+ return ENDPOINT_READYWAIT_BusSuspended;
+ else if (Endpoint_IsStalled())
+ return ENDPOINT_READYWAIT_EndpointStalled;
+
+ uint16_t CurrentFrameNumber = USB_Device_GetFrameNumber();
+
+ if (CurrentFrameNumber != PreviousFrameNumber)
+ {
+ PreviousFrameNumber = CurrentFrameNumber;
+
+ if (!(TimeoutMSRem--))
+ return ENDPOINT_READYWAIT_Timeout;
+ }
+ }
+}
+#endif
+
+#endif
+
diff --git a/LUFA/Drivers/USB/LowLevel/Endpoint.h b/LUFA/Drivers/USB/LowLevel/Endpoint.h
new file mode 100644
index 0000000..88856d8
--- /dev/null
+++ b/LUFA/Drivers/USB/LowLevel/Endpoint.h
@@ -0,0 +1,892 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2010.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, 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
+ * \brief USB device endpoint management definitions.
+ *
+ * This file contains structures, function prototypes and macros related to the management of the device's
+ * data endpoints when the library is initialized in USB device mode.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB driver
+ * dispatch header located in LUFA/Drivers/USB/USB.h.
+ */
+
+/** \ingroup Group_EndpointManagement
+ * @defgroup Group_EndpointRW Endpoint Data Reading and Writing
+ *
+ * Functions, macros, variables, enums and types related to data reading and writing from and to endpoints.
+ */
+
+/** \ingroup Group_EndpointRW
+ * @defgroup Group_EndpointPrimitiveRW Read/Write of Primitive Data Types
+ *
+ * Functions, macros, variables, enums and types related to data reading and writing of primitive data types
+ * from and to endpoints.
+ */
+
+/** \ingroup Group_EndpointManagement
+ * @defgroup Group_EndpointPacketManagement Endpoint Packet Management
+ *
+ * Functions, macros, variables, enums and types related to packet management of endpoints.
+ */
+
+/** \ingroup Group_USB
+ * @defgroup Group_EndpointManagement Endpoint Management
+ *
+ * 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/receive functions for various data types.
+ *
+ * @{
+ */
+
+#ifndef __ENDPOINT_H__
+#define __ENDPOINT_H__
+
+ /* Includes: */
+ #include <avr/io.h>
+ #include <stdbool.h>
+
+ #include "../../../Common/Common.h"
+ #include "../HighLevel/USBTask.h"
+ #include "USBInterrupt.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_USB_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define _ENDPOINT_GET_MAXSIZE(EPIndex) _ENDPOINT_GET_MAXSIZE2(ENDPOINT_DETAILS_EP ## EPIndex)
+ #define _ENDPOINT_GET_MAXSIZE2(EPDetails) _ENDPOINT_GET_MAXSIZE3(EPDetails)
+ #define _ENDPOINT_GET_MAXSIZE3(MaxSize, Banks) (MaxSize)
+
+ #define _ENDPOINT_GET_BANKS(EPIndex) _ENDPOINT_GET_BANKS2(ENDPOINT_DETAILS_EP ## EPIndex)
+ #define _ENDPOINT_GET_BANKS2(EPDetails) _ENDPOINT_GET_BANKS3(EPDetails)
+ #define _ENDPOINT_GET_BANKS3(MaxSize, Banks) (Banks)
+
+ #if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR)
+ #define ENDPOINT_DETAILS_MAXEP 7
+
+ #define ENDPOINT_DETAILS_EP0 64, 2
+ #define ENDPOINT_DETAILS_EP1 256, 2
+ #define ENDPOINT_DETAILS_EP2 64, 2
+ #define ENDPOINT_DETAILS_EP3 64, 2
+ #define ENDPOINT_DETAILS_EP4 64, 2
+ #define ENDPOINT_DETAILS_EP5 64, 2
+ #define ENDPOINT_DETAILS_EP6 64, 2
+ #else
+ #define ENDPOINT_DETAILS_MAXEP 5
+
+ #define ENDPOINT_DETAILS_EP0 64, 2
+ #define ENDPOINT_DETAILS_EP1 64, 1
+ #define ENDPOINT_DETAILS_EP2 64, 1
+ #define ENDPOINT_DETAILS_EP3 64, 2
+ #define ENDPOINT_DETAILS_EP4 64, 2
+ #endif
+
+ /* Inline Functions: */
+ static inline uint8_t Endpoint_BytesToEPSizeMask(const uint16_t Bytes) ATTR_WARN_UNUSED_RESULT ATTR_CONST
+ ATTR_ALWAYS_INLINE;
+ static inline uint8_t Endpoint_BytesToEPSizeMask(const uint16_t Bytes)
+ {
+ uint8_t MaskVal = 0;
+ uint16_t CheckBytes = 8;
+
+ while (CheckBytes < Bytes)
+ {
+ MaskVal++;
+ CheckBytes <<= 1;
+ }
+
+ return (MaskVal << EPSIZE0);
+ }
+
+ /* Function Prototypes: */
+ void Endpoint_ClearEndpoints(void);
+ bool Endpoint_ConfigureEndpoint_Prv(const uint8_t Number,
+ const uint8_t UECFG0XData,
+ const uint8_t UECFG1XData);
+
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** \name Endpoint Direction Masks */
+ //@{
+ /** Endpoint data direction mask for \ref 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 << EPDIR)
+
+ /** Endpoint data direction mask for \ref 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)
+ //@}
+
+ /** \name Endpoint Bank Mode Masks */
+ //@{
+ /** Mask for the bank mode selection for the \ref 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 << EPBK0)
+
+ /** Mask for the bank mode selection for the \ref 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
+
+ #if (!defined(FIXED_CONTROL_ENDPOINT_SIZE) || defined(__DOXYGEN__))
+ /** Default size of the default control endpoint's bank, until altered by the control endpoint bank size
+ * value in the device descriptor. Not available if the FIXED_CONTROL_ENDPOINT_SIZE token is defined.
+ */
+ #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 0x07
+
+ /** Endpoint direction mask, for masking against endpoint addresses to retrieve the endpoint's
+ * direction for comparing with the ENDPOINT_DESCRIPTOR_DIR_* masks.
+ */
+ #define ENDPOINT_EPDIR_MASK 0x80
+
+ /** Endpoint bank size mask, for masking against endpoint addresses to retrieve the endpoint's
+ * bank size in the device.
+ */
+ #define ENDPOINT_EPSIZE_MASK 0x7F
+
+ /** Maximum size in bytes of a given endpoint.
+ *
+ * \param[in] EPIndex Endpoint number, a value between 0 and (ENDPOINT_TOTAL_ENDPOINTS - 1)
+ */
+ #define ENDPOINT_MAX_SIZE(EPIndex) _ENDPOINT_GET_MAXSIZE(EPIndex)
+
+ /** Indicates the total number of banks supported by the given endpoint.
+ *
+ * \param[in] EPIndex Endpoint number, a value between 0 and (ENDPOINT_TOTAL_ENDPOINTS - 1)
+ */
+ #define ENDPOINT_BANKS_SUPPORTED(EPIndex) _ENDPOINT_GET_BANKS(EPIndex)
+
+ #if !defined(CONTROL_ONLY_DEVICE) || 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 ENDPOINT_DETAILS_MAXEP
+ #else
+ #define ENDPOINT_TOTAL_ENDPOINTS 1
+ #endif
+
+ /* Enums: */
+ /** Enum for the possible error return codes of the \ref Endpoint_WaitUntilReady() function.
+ *
+ * \ingroup Group_EndpointRW
+ */
+ 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_BusSuspended = 3, /**< The USB bus has been suspended by the host and
+ * no USB endpoint traffic can occur until the bus
+ * has resumed.
+ */
+ ENDPOINT_READYWAIT_Timeout = 4, /**< The host failed to accept or send the next packet
+ * within the software timeout period set by the
+ * \ref USB_STREAM_TIMEOUT_MS macro.
+ */
+ };
+
+ /* Inline Functions: */
+ /** Configures the specified endpoint number with the given endpoint type, direction, bank size
+ * and banking mode. Once configured, the endpoint may be read from or written to, depending
+ * on its direction.
+ *
+ * \param[in] Number Endpoint number to configure. This must be more than 0 and less than
+ * \ref ENDPOINT_TOTAL_ENDPOINTS.
+ *
+ * \param[in] Type Type of endpoint to configure, a EP_TYPE_* mask. Not all endpoint types
+ * are available on Low Speed USB devices - refer to the USB 2.0 specification.
+ *
+ * \param[in] Direction Endpoint data direction, either \ref ENDPOINT_DIR_OUT or \ref ENDPOINT_DIR_IN.
+ * All endpoints (except Control type) are unidirectional - data may only be read
+ * from or written to the endpoint bank based on its direction, not both.
+ *
+ * \param[in] Size Size of the endpoint's bank, where packets are stored before they are transmitted
+ * to the USB host, or after they have been received from the USB host (depending on
+ * the endpoint's data direction). The bank size must indicate the maximum packet size
+ * that the endpoint can handle.
+ *
+ * \param[in] Banks Number of banks to use for the endpoint being configured, an ENDPOINT_BANK_* mask.
+ * More banks uses more USB DPRAM, but offers better performance. Isochronous type
+ * endpoints <b>must</b> have at least two banks.
+ *
+ * \note Endpoints <b>must</b> be configured in ascending order, or bank corruption will occur.
+ * \n\n
+ *
+ * \note Certain models of USB AVR's endpoints may have different maximum packet sizes based on the endpoint's
+ * index - refer to the chosen USB AVR's datasheet to determine the maximum bank size for each endpoint.
+ * \n\n
+ *
+ * \note The default control endpoint should not be manually configured by the user application, as
+ * it is automatically configured by the library internally.
+ * \n\n
+ *
+ * \note This routine will automatically select the specified endpoint upon success. Upon failure, the endpoint
+ * which failed to reconfigure correctly will be selected.
+ *
+ * \return Boolean true if the configuration succeeded, false otherwise.
+ */
+ static inline bool Endpoint_ConfigureEndpoint(const uint8_t Number,
+ const uint8_t Type,
+ const uint8_t Direction,
+ const uint16_t Size,
+ const uint8_t Banks) ATTR_ALWAYS_INLINE;
+ static inline bool Endpoint_ConfigureEndpoint(const uint8_t Number,
+ const uint8_t Type,
+ const uint8_t Direction,
+ const uint16_t Size,
+ const uint8_t Banks)
+ {
+ return Endpoint_ConfigureEndpoint_Prv(Number, (((Type) << EPTYPE0) | (Direction)),
+ ((1 << ALLOC) | Banks | Endpoint_BytesToEPSizeMask(Size)));
+ }
+
+ /** Indicates the number of bytes currently stored in the current endpoint's selected bank.
+ *
+ * \note The return width of this function may differ, depending on the maximum endpoint bank size
+ * of the selected AVR model.
+ *
+ * \ingroup Group_EndpointRW
+ *
+ * \return Total number of bytes in the currently selected Endpoint's FIFO buffer.
+ */
+ static inline uint16_t Endpoint_BytesInEndpoint(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint16_t Endpoint_BytesInEndpoint(void)
+ {
+ #if defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR)
+ return UEBCX;
+ #elif defined(USB_SERIES_4_AVR)
+ return (((uint16_t)UEBCHX << 8) | UEBCLX);
+ #elif defined(USB_SERIES_2_AVR)
+ return UEBCLX;
+ #endif
+ }
+
+ /** Get 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.
+ *
+ * \return Index of the currently selected endpoint.
+ */
+ static inline uint8_t Endpoint_GetCurrentEndpoint(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint8_t Endpoint_GetCurrentEndpoint(void)
+ {
+ #if !defined(CONTROL_ONLY_DEVICE)
+ return (UENUM & ENDPOINT_EPNUM_MASK);
+ #else
+ return ENDPOINT_CONTROLEP;
+ #endif
+ }
+
+ /** Selects the given endpoint number. If the address from the device descriptors is used, the
+ * value should be masked with the \ref 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.
+ *
+ * \param[in] EndpointNumber Endpoint number to select.
+ */
+ static inline void Endpoint_SelectEndpoint(const uint8_t EndpointNumber) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_SelectEndpoint(const uint8_t EndpointNumber)
+ {
+ #if !defined(CONTROL_ONLY_DEVICE)
+ UENUM = EndpointNumber;
+ #endif
+ }
+
+ /** 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.
+ *
+ * \param[in] EndpointNumber Endpoint number whose FIFO buffers are to be reset.
+ */
+ static inline void Endpoint_ResetFIFO(const uint8_t EndpointNumber) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_ResetFIFO(const uint8_t EndpointNumber)
+ {
+ UERST = (1 << EndpointNumber);
+ UERST = 0;
+ }
+
+ /** 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 via \ref Endpoint_ConfigureEndpoint().
+ */
+ static inline void Endpoint_EnableEndpoint(void) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_EnableEndpoint(void)
+ {
+ UECONX |= (1 << EPEN);
+ }
+
+ /** Disables the currently selected endpoint so that data cannot be sent and received through it
+ * to and from a host.
+ */
+ static inline void Endpoint_DisableEndpoint(void) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_DisableEndpoint(void)
+ {
+ UECONX &= ~(1 << EPEN);
+ }
+
+ /** Determines if the currently selected endpoint is enabled, but not necessarily configured.
+ *
+ * \return Boolean True if the currently selected endpoint is enabled, false otherwise.
+ */
+ static inline bool Endpoint_IsEnabled(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Endpoint_IsEnabled(void)
+ {
+ return ((UECONX & (1 << EPEN)) ? true : false);
+ }
+
+ /** Aborts all pending IN transactions on the currently selected endpoint, once the bank
+ * has been queued for transmission to the host via \ref Endpoint_ClearIN(). This function
+ * will terminate all queued transactions, resetting the endpoint banks ready for a new
+ * packet.
+ *
+ * \ingroup Group_EndpointPacketManagement
+ */
+ static inline void Endpoint_AbortPendingIN(void)
+ {
+ while (UESTA0X & (0x03 << NBUSYBK0))
+ {
+ UEINTX |= (1 << RXOUTI);
+ while (UEINTX & (1 << RXOUTI));
+ }
+ }
+
+ /** Retrieves the number of busy banks in the currently selected endpoint, which have been queued for
+ * transmission via the \ref Endpoint_ClearIN() command, or are awaiting acknowledgement via the
+ * \ref Endpoint_ClearOUT() command.
+ *
+ * \ingroup Group_EndpointPacketManagement
+ *
+ * \return Total number of busy banks in the selected endpoint.
+ */
+ static inline uint8_t Endpoint_GetBusyBanks(void)
+ {
+ return (UESTA0X & (0x03 << NBUSYBK0));
+ }
+
+ /** Determines 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 occurred in the endpoint, if the endpoint
+ * is an OUT direction and no packet (or an empty packet) has been received, or if the endpoint is an IN
+ * direction and the endpoint bank is full.
+ *
+ * \ingroup Group_EndpointPacketManagement
+ *
+ * \return Boolean true if the currently selected endpoint may be read from or written to, depending on its direction.
+ */
+ static inline bool Endpoint_IsReadWriteAllowed(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Endpoint_IsReadWriteAllowed(void)
+ {
+ return ((UEINTX & (1 << RWAL)) ? true : false);
+ }
+
+ /** Determines if the currently selected endpoint is configured.
+ *
+ * \return Boolean true if the currently selected endpoint has been configured, false otherwise.
+ */
+ static inline bool Endpoint_IsConfigured(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Endpoint_IsConfigured(void)
+ {
+ return ((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}).
+ *
+ * \return Mask whose bits indicate which endpoints have interrupted.
+ */
+ static inline uint8_t Endpoint_GetEndpointInterrupts(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint8_t Endpoint_GetEndpointInterrupts(void)
+ {
+ return UEINT;
+ }
+
+ /** Determines if the specified endpoint number has interrupted (valid only for INTERRUPT type
+ * endpoints).
+ *
+ * \param[in] EndpointNumber Index of the endpoint whose interrupt flag should be tested.
+ *
+ * \return Boolean true if the specified endpoint has interrupted, false otherwise.
+ */
+ static inline bool Endpoint_HasEndpointInterrupted(const uint8_t EndpointNumber) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Endpoint_HasEndpointInterrupted(const uint8_t EndpointNumber)
+ {
+ return ((UEINT & (1 << EndpointNumber)) ? true : false);
+ }
+
+ /** Determines if the selected IN endpoint is ready for a new packet to be sent to the host.
+ *
+ * \ingroup Group_EndpointPacketManagement
+ *
+ * \return Boolean true if the current endpoint is ready for an IN packet, false otherwise.
+ */
+ static inline bool Endpoint_IsINReady(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Endpoint_IsINReady(void)
+ {
+ return ((UEINTX & (1 << TXINI)) ? true : false);
+ }
+
+ /** Determines if the selected OUT endpoint has received new packet from the host.
+ *
+ * \ingroup Group_EndpointPacketManagement
+ *
+ * \return Boolean true if current endpoint is has received an OUT packet, false otherwise.
+ */
+ static inline bool Endpoint_IsOUTReceived(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Endpoint_IsOUTReceived(void)
+ {
+ return ((UEINTX & (1 << RXOUTI)) ? true : false);
+ }
+
+ /** Determines if the current CONTROL type endpoint has received a SETUP packet.
+ *
+ * \ingroup Group_EndpointPacketManagement
+ *
+ * \return Boolean true if the selected endpoint has received a SETUP packet, false otherwise.
+ */
+ static inline bool Endpoint_IsSETUPReceived(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Endpoint_IsSETUPReceived(void)
+ {
+ return ((UEINTX & (1 << RXSTPI)) ? true : false);
+ }
+
+ /** Clears a received SETUP packet on the currently selected CONTROL type endpoint, freeing up the
+ * endpoint for the next packet.
+ *
+ * \ingroup Group_EndpointPacketManagement
+ *
+ * \note This is not applicable for non CONTROL type endpoints.
+ */
+ static inline void Endpoint_ClearSETUP(void) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_ClearSETUP(void)
+ {
+ UEINTX &= ~(1 << RXSTPI);
+ }
+
+ /** Sends an IN packet to the host on the currently selected endpoint, freeing up the endpoint for the
+ * next packet and switching to the alternative endpoint bank if double banked.
+ *
+ * \ingroup Group_EndpointPacketManagement
+ */
+ static inline void Endpoint_ClearIN(void) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_ClearIN(void)
+ {
+ #if !defined(CONTROL_ONLY_DEVICE)
+ UEINTX &= ~((1 << TXINI) | (1 << FIFOCON));
+ #else
+ UEINTX &= ~(1 << TXINI);
+ #endif
+ }
+
+ /** Acknowledges an OUT packet to the host on the currently selected endpoint, freeing up the endpoint
+ * for the next packet and switching to the alternative endpoint bank if double banked.
+ *
+ * \ingroup Group_EndpointPacketManagement
+ */
+ static inline void Endpoint_ClearOUT(void) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_ClearOUT(void)
+ {
+ #if !defined(CONTROL_ONLY_DEVICE)
+ UEINTX &= ~((1 << RXOUTI) | (1 << FIFOCON));
+ #else
+ UEINTX &= ~(1 << RXOUTI);
+ #endif
+ }
+
+ /** Stalls the current endpoint, indicating to the host that a logical problem occurred 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 sequence.
+ *
+ * The currently selected endpoint remains stalled until either the \ref Endpoint_ClearStall() macro
+ * is called, or the host issues a CLEAR FEATURE request to the device for the currently selected
+ * endpoint.
+ *
+ * \ingroup Group_EndpointPacketManagement
+ */
+ static inline void Endpoint_StallTransaction(void) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_StallTransaction(void)
+ {
+ UECONX |= (1 << STALLRQ);
+ }
+
+ /** Clears the STALL condition on the currently selected endpoint.
+ *
+ * \ingroup Group_EndpointPacketManagement
+ */
+ static inline void Endpoint_ClearStall(void) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_ClearStall(void)
+ {
+ UECONX |= (1 << STALLRQC);
+ }
+
+ /** Determines if the currently selected endpoint is stalled, false otherwise.
+ *
+ * \ingroup Group_EndpointPacketManagement
+ *
+ * \return Boolean true if the currently selected endpoint is stalled, false otherwise.
+ */
+ static inline bool Endpoint_IsStalled(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Endpoint_IsStalled(void)
+ {
+ return ((UECONX & (1 << STALLRQ)) ? true : false);
+ }
+
+ /** Resets the data toggle of the currently selected endpoint. */
+ static inline void Endpoint_ResetDataToggle(void) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_ResetDataToggle(void)
+ {
+ UECONX |= (1 << RSTDT);
+ }
+
+ /** Determines the currently selected endpoint's direction.
+ *
+ * \return The currently selected endpoint's direction, as a ENDPOINT_DIR_* mask.
+ */
+ static inline uint8_t Endpoint_GetEndpointDirection(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint8_t Endpoint_GetEndpointDirection(void)
+ {
+ return (UECFG0X & ENDPOINT_DIR_IN);
+ }
+
+ /** Sets the direction of the currently selected endpoint.
+ *
+ * \param[in] DirectionMask New endpoint direction, as a ENDPOINT_DIR_* mask.
+ */
+ static inline void Endpoint_SetEndpointDirection(const uint8_t DirectionMask) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_SetEndpointDirection(const uint8_t DirectionMask)
+ {
+ UECFG0X = ((UECFG0X & ~ENDPOINT_DIR_IN) | DirectionMask);
+ }
+
+ /** Reads one byte from the currently selected endpoint's bank, for OUT direction endpoints.
+ *
+ * \ingroup Group_EndpointPrimitiveRW
+ *
+ * \return Next byte in the currently selected endpoint's FIFO buffer.
+ */
+ static inline uint8_t Endpoint_Read_Byte(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint8_t Endpoint_Read_Byte(void)
+ {
+ return UEDATX;
+ }
+
+ /** Writes one byte from the currently selected endpoint's bank, for IN direction endpoints.
+ *
+ * \ingroup Group_EndpointPrimitiveRW
+ *
+ * \param[in] Byte Next byte to write into the the currently selected endpoint's FIFO buffer.
+ */
+ static inline void Endpoint_Write_Byte(const uint8_t Byte) ATTR_ALWAYS_INLINE;
+ 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.
+ *
+ * \ingroup Group_EndpointPrimitiveRW
+ */
+ static inline void Endpoint_Discard_Byte(void) ATTR_ALWAYS_INLINE;
+ 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.
+ *
+ * \ingroup Group_EndpointPrimitiveRW
+ *
+ * \return Next word in the currently selected endpoint's FIFO buffer.
+ */
+ static inline uint16_t Endpoint_Read_Word_LE(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint16_t Endpoint_Read_Word_LE(void)
+ {
+ union
+ {
+ uint16_t Word;
+ uint8_t Bytes[2];
+ } Data;
+
+ Data.Bytes[0] = UEDATX;
+ Data.Bytes[1] = UEDATX;
+
+ return Data.Word;
+ }
+
+ /** Reads two bytes from the currently selected endpoint's bank in big endian format, for OUT
+ * direction endpoints.
+ *
+ * \ingroup Group_EndpointPrimitiveRW
+ *
+ * \return Next word in the currently selected endpoint's FIFO buffer.
+ */
+ static inline uint16_t Endpoint_Read_Word_BE(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint16_t Endpoint_Read_Word_BE(void)
+ {
+ union
+ {
+ uint16_t Word;
+ uint8_t Bytes[2];
+ } Data;
+
+ Data.Bytes[1] = UEDATX;
+ Data.Bytes[0] = UEDATX;
+
+ return Data.Word;
+ }
+
+ /** Writes two bytes to the currently selected endpoint's bank in little endian format, for IN
+ * direction endpoints.
+ *
+ * \ingroup Group_EndpointPrimitiveRW
+ *
+ * \param[in] Word Next word to write to the currently selected endpoint's FIFO buffer.
+ */
+ static inline void Endpoint_Write_Word_LE(const uint16_t Word) ATTR_ALWAYS_INLINE;
+ 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.
+ *
+ * \ingroup Group_EndpointPrimitiveRW
+ *
+ * \param[in] Word Next word to write to the currently selected endpoint's FIFO buffer.
+ */
+ static inline void Endpoint_Write_Word_BE(const uint16_t Word) ATTR_ALWAYS_INLINE;
+ 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.
+ *
+ * \ingroup Group_EndpointPrimitiveRW
+ */
+ static inline void Endpoint_Discard_Word(void) ATTR_ALWAYS_INLINE;
+ 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.
+ *
+ * \ingroup Group_EndpointPrimitiveRW
+ *
+ * \return Next double word in the currently selected endpoint's FIFO buffer.
+ */
+ static inline uint32_t Endpoint_Read_DWord_LE(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ 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.
+ *
+ * \ingroup Group_EndpointPrimitiveRW
+ *
+ * \return Next double word in the currently selected endpoint's FIFO buffer.
+ */
+ static inline uint32_t Endpoint_Read_DWord_BE(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ 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.
+ *
+ * \ingroup Group_EndpointPrimitiveRW
+ *
+ * \param[in] DWord Next double word to write to the currently selected endpoint's FIFO buffer.
+ */
+ static inline void Endpoint_Write_DWord_LE(const uint32_t DWord) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_Write_DWord_LE(const uint32_t DWord)
+ {
+ UEDATX = (DWord & 0xFF);
+ UEDATX = (DWord >> 8);
+ UEDATX = (DWord >> 16);
+ UEDATX = (DWord >> 24);
+ }
+
+ /** Writes four bytes to the currently selected endpoint's bank in big endian format, for IN
+ * direction endpoints.
+ *
+ * \ingroup Group_EndpointPrimitiveRW
+ *
+ * \param[in] DWord Next double word to write to the currently selected endpoint's FIFO buffer.
+ */
+ static inline void Endpoint_Write_DWord_BE(const uint32_t DWord) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_Write_DWord_BE(const uint32_t DWord)
+ {
+ UEDATX = (DWord >> 24);
+ UEDATX = (DWord >> 16);
+ UEDATX = (DWord >> 8);
+ UEDATX = (DWord & 0xFF);
+ }
+
+ /** Discards four bytes from the currently selected endpoint's bank, for OUT direction endpoints.
+ *
+ * \ingroup Group_EndpointPrimitiveRW
+ */
+ static inline void Endpoint_Discard_DWord(void) ATTR_ALWAYS_INLINE;
+ 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: */
+ /** Completes the status stage of a control transfer on a CONTROL type endpoint automatically,
+ * with respect to the data direction. This is a convenience function which can be used to
+ * simplify user control request handling.
+ */
+ void Endpoint_ClearStatusStage(void);
+
+ /** Spin-loops 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.
+ *
+ * \ingroup Group_EndpointRW
+ *
+ * \return A value from the \ref Endpoint_WaitUntilReady_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_WaitUntilReady(void);
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/LUFA/Drivers/USB/LowLevel/Host.c b/LUFA/Drivers/USB/LowLevel/Host.c
new file mode 100644
index 0000000..7f76a1c
--- /dev/null
+++ b/LUFA/Drivers/USB/LowLevel/Host.c
@@ -0,0 +1,355 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2010.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, 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.
+*/
+
+#define __INCLUDE_FROM_USB_DRIVER
+#include "../HighLevel/USBMode.h"
+
+#if defined(USB_CAN_BE_HOST)
+
+#define __INCLUDE_FROM_HOST_C
+#include "Host.h"
+
+void USB_Host_ProcessNextHostState(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;
+ }
+
+ if (!(--WaitMSRemaining))
+ USB_HostState = PostWaitState;
+ }
+
+ break;
+ case HOST_STATE_Powered:
+ WaitMSRemaining = HOST_DEVICE_SETTLE_DELAY_MS;
+
+ USB_HostState = HOST_STATE_Powered_WaitForDeviceSettle;
+ break;
+ case HOST_STATE_Powered_WaitForDeviceSettle:
+ if (WaitMSRemaining--)
+ {
+ _delay_ms(1);
+ break;
+ }
+ else
+ {
+ USB_Host_VBUS_Manual_Off();
+
+ USB_OTGPAD_On();
+ USB_Host_VBUS_Auto_Enable();
+ USB_Host_VBUS_Auto_On();
+
+ USB_HostState = HOST_STATE_Powered_WaitForConnect;
+ }
+
+ break;
+ case HOST_STATE_Powered_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_Host_ResumeBus();
+ Pipe_ClearPipes();
+
+ HOST_TASK_NONBLOCK_WAIT(100, HOST_STATE_Powered_DoReset);
+ }
+
+ break;
+ case HOST_STATE_Powered_DoReset:
+ USB_Host_ResetDevice();
+
+ HOST_TASK_NONBLOCK_WAIT(200, HOST_STATE_Powered_ConfigPipe);
+ break;
+ case HOST_STATE_Powered_ConfigPipe:
+ Pipe_ConfigurePipe(PIPE_CONTROLPIPE, EP_TYPE_CONTROL,
+ PIPE_TOKEN_SETUP, ENDPOINT_CONTROLEP,
+ 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_ControlRequest = (USB_Request_Header_t)
+ {
+ .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE),
+ .bRequest = REQ_GetDescriptor,
+ .wValue = (DTYPE_Device << 8),
+ .wIndex = 0,
+ .wLength = 8,
+ };
+
+ uint8_t DataBuffer[8];
+
+ if ((SubErrorCode = USB_Host_SendControlRequest(DataBuffer)) != HOST_SENDCONTROL_Successful)
+ {
+ ErrorCode = HOST_ENUMERROR_ControlError;
+ break;
+ }
+
+ USB_ControlPipeSize = DataBuffer[offsetof(USB_Descriptor_Device_t, Endpoint0Size)];
+
+ USB_Host_ResetDevice();
+
+ HOST_TASK_NONBLOCK_WAIT(200, HOST_STATE_Default_PostReset);
+ break;
+ case HOST_STATE_Default_PostReset:
+ Pipe_ConfigurePipe(PIPE_CONTROLPIPE, EP_TYPE_CONTROL,
+ PIPE_TOKEN_SETUP, ENDPOINT_CONTROLEP,
+ USB_ControlPipeSize, PIPE_BANK_SINGLE);
+
+ if (!(Pipe_IsConfigured()))
+ {
+ ErrorCode = HOST_ENUMERROR_PipeConfigError;
+ SubErrorCode = 0;
+ break;
+ }
+
+ USB_ControlRequest = (USB_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);
+
+ EVENT_USB_Host_DeviceEnumerationComplete();
+ USB_HostState = HOST_STATE_Addressed;
+ break;
+ }
+
+ if ((ErrorCode != HOST_ENUMERROR_NoError) && (USB_HostState != HOST_STATE_Unattached))
+ {
+ EVENT_USB_Host_DeviceEnumerationFailed(ErrorCode, SubErrorCode);
+
+ USB_Host_VBUS_Auto_Off();
+
+ EVENT_USB_Host_DeviceUnattached();
+
+ USB_ResetInterface();
+ }
+}
+
+uint8_t USB_Host_WaitMS(uint8_t MS)
+{
+ bool BusSuspended = USB_Host_IsBusSuspended();
+ uint8_t ErrorCode = HOST_WAITERROR_Successful;
+ bool HSOFIEnabled = USB_INT_IsEnabled(USB_INT_HSOFI);
+
+ USB_INT_Disable(USB_INT_HSOFI);
+ 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_HostState == HOST_STATE_Unattached) || (USB_CurrentMode != USB_MODE_Host))
+ {
+ 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();
+
+ if (HSOFIEnabled)
+ USB_INT_Enable(USB_INT_HSOFI);
+
+ return ErrorCode;
+}
+
+static void USB_Host_ResetDevice(void)
+{
+ bool BusSuspended = USB_Host_IsBusSuspended();
+
+ USB_INT_Disable(USB_INT_DDISCI);
+
+ USB_Host_ResetBus();
+ while (!(USB_Host_IsBusResetComplete()));
+ USB_Host_ResumeBus();
+
+ bool HSOFIEnabled = USB_INT_IsEnabled(USB_INT_HSOFI);
+
+ USB_INT_Disable(USB_INT_HSOFI);
+ USB_INT_Clear(USB_INT_HSOFI);
+
+ for (uint8_t MSRem = 10; MSRem != 0; MSRem--)
+ {
+ /* Workaround for powerless-pull-up devices. After a USB bus reset,
+ all disconnection interrupts are suppressed 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_HSOFI);
+ USB_INT_Clear(USB_INT_DDISCI);
+ break;
+ }
+
+ _delay_ms(1);
+ }
+
+ if (HSOFIEnabled)
+ USB_INT_Enable(USB_INT_HSOFI);
+
+ if (BusSuspended)
+ USB_Host_SuspendBus();
+
+ USB_INT_Enable(USB_INT_DDISCI);
+}
+
+uint8_t USB_Host_SetDeviceConfiguration(const uint8_t ConfigNumber)
+{
+ USB_ControlRequest = (USB_Request_Header_t)
+ {
+ .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_DEVICE),
+ .bRequest = REQ_SetConfiguration,
+ .wValue = ConfigNumber,
+ .wIndex = 0,
+ .wLength = 0,
+ };
+
+ Pipe_SelectPipe(PIPE_CONTROLPIPE);
+
+ return USB_Host_SendControlRequest(NULL);
+}
+
+uint8_t USB_Host_GetDeviceDescriptor(void* const DeviceDescriptorPtr)
+{
+ USB_ControlRequest = (USB_Request_Header_t)
+ {
+ .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE),
+ .bRequest = REQ_GetDescriptor,
+ .wValue = (DTYPE_Device << 8),
+ .wIndex = 0,
+ .wLength = sizeof(USB_Descriptor_Device_t),
+ };
+
+ Pipe_SelectPipe(PIPE_CONTROLPIPE);
+
+ return USB_Host_SendControlRequest(DeviceDescriptorPtr);
+}
+
+uint8_t USB_Host_GetDeviceStringDescriptor(const uint8_t Index,
+ void* const Buffer,
+ const uint8_t BufferLength)
+{
+ USB_ControlRequest = (USB_Request_Header_t)
+ {
+ .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE),
+ .bRequest = REQ_GetDescriptor,
+ .wValue = (DTYPE_String << 8) | Index,
+ .wIndex = 0,
+ .wLength = BufferLength,
+ };
+
+ Pipe_SelectPipe(PIPE_CONTROLPIPE);
+
+ return USB_Host_SendControlRequest(Buffer);
+}
+
+uint8_t USB_Host_ClearPipeStall(const uint8_t EndpointNum)
+{
+ USB_ControlRequest = (USB_Request_Header_t)
+ {
+ .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_ENDPOINT),
+ .bRequest = REQ_ClearFeature,
+ .wValue = FEATURE_SEL_EndpointHalt,
+ .wIndex = EndpointNum,
+ .wLength = 0,
+ };
+
+ Pipe_SelectPipe(PIPE_CONTROLPIPE);
+
+ return USB_Host_SendControlRequest(NULL);
+}
+
+#endif
+
diff --git a/LUFA/Drivers/USB/LowLevel/Host.h b/LUFA/Drivers/USB/LowLevel/Host.h
new file mode 100644
index 0000000..dce3a95
--- /dev/null
+++ b/LUFA/Drivers/USB/LowLevel/Host.h
@@ -0,0 +1,527 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2010.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, 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
+ * \brief USB host mode definitions.
+ *
+ * This file contains structures, function prototypes and macros related to USB host mode.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB driver
+ * dispatch header located in LUFA/Drivers/USB/USB.h.
+ */
+
+/** \ingroup Group_USB
+ * @defgroup Group_Host Host Management
+ *
+ * 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/StdDescriptors.h"
+ #include "Pipe.h"
+ #include "USBInterrupt.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_USB_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
+ #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
+ * \ref 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.
+ *
+ * The default delay value may be overridden in the user project makefile by definining the
+ * HOST_DEVICE_SETTLE_DELAY_MS token to tbe required delay in milliseconds, and passed to the
+ * compiler using the -D switch.
+ */
+ #define HOST_DEVICE_SETTLE_DELAY_MS 1000
+ #endif
+
+ /* 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 possible USB host state, refer to the USB 2.0 specification.
+ * Several of the USB host states are broken up further into multiple smaller sub-states,
+ * so that they can be internally implemented inside the library in an efficient manner.
+ *
+ * \see \ref USB_HostState, which stores the current host state machine state.
+ */
+ enum USB_Host_States_t
+ {
+ HOST_STATE_WaitForDeviceRemoval = 0, /**< Internally implemented by the library. This state can be
+ * used by the library to wait until the attached device is
+ * removed by the user - useful for when an error occurs or
+ * further communication with the device is not needed. This
+ * allows for other code to run while the state machine is
+ * effectively disabled.
+ */
+ HOST_STATE_WaitForDevice = 1, /**< Internally implemented by the library. This state indicates
+ * that the stack is waiting for an interval to elapse before
+ * continuing with the next step of the device enumeration
+ * process.
+ *
+ * \note Do not manually change to this state in the user code.
+ */
+ HOST_STATE_Unattached = 2, /**< Internally implemented by the library. This state indicates
+ * that the host state machine is waiting for a device to be
+ * attached so that it can start the enumeration process.
+ *
+ * \note Do not manually change to this state in the user code.
+ */
+ HOST_STATE_Powered = 3, /**< Internally implemented by the library. This state indicates
+ * that a device has been attached, and the library's internals
+ * are being configured to begin the enumeration process.
+ *
+ * \note Do not manually change to this state in the user code.
+ */
+ HOST_STATE_Powered_WaitForDeviceSettle = 4, /**< Internally implemented by the library. This state indicates
+ * that the stack is waiting for the initial settling period to
+ * elapse before beginning the enumeration process.
+ *
+ * \note Do not manually change to this state in the user code.
+ */
+ HOST_STATE_Powered_WaitForConnect = 5, /**< Internally implemented by the library. This state indicates
+ * that the stack is waiting for a connection event from the USB
+ * controller to indicate a valid USB device has been attached to
+ * the bus and is ready to be enumerated.
+ *
+ * \note Do not manually change to this state in the user code.
+ */
+ HOST_STATE_Powered_DoReset = 6, /**< Internally implemented by the library. This state indicates
+ * that a valid USB device has been attached, and that it is
+ * will now be reset to ensure it is ready for enumeration.
+ *
+ * \note Do not manually change to this state in the user code.
+ */
+ HOST_STATE_Powered_ConfigPipe = 7, /**< Internally implemented by the library. This state indicates
+ * that the attached device is currently powered and reset, and
+ * that the control pipe is now being configured by the stack.
+ *
+ * \note Do not manually change to this state in the user code.
+ */
+ HOST_STATE_Default = 8, /**< Internally implemented by the library. This state indicates
+ * that the stack is currently retrieving the control endpoint's
+ * size from the device, so that the control pipe can be altered
+ * to match.
+ *
+ * \note Do not manually change to this state in the user code.
+ */
+ HOST_STATE_Default_PostReset = 9, /**< Internally implemented by the library. This state indicates that
+ * the control pipe is being reconfigured to match the retrieved
+ * control endpoint size from the device, and the device's USB bus
+ * address is being set.
+ *
+ * \note Do not manually change to this state in the user code.
+ */
+ HOST_STATE_Default_PostAddressSet = 10, /**< Internally implemented by the library. This state indicates that
+ * the device's address has now been set, and the stack is has now
+ * completed the device enumeration process. This state causes the
+ * stack to change the current USB device address to that set for
+ * the connected device, before progressing to the user-implemented
+ * \ref HOST_STATE_Addressed state for further communications.
+ *
+ * \note Do not manually change to this state in the user code.
+ */
+ HOST_STATE_Addressed = 11, /**< May be implemented by the user project. This state should
+ * set the device configuration before progressing to the
+ * \ref HOST_STATE_Configured state. Other processing (such as the
+ * retrieval and processing of the device descriptor) should also
+ * be placed in this state.
+ */
+ HOST_STATE_Configured = 12, /**< May be implemented by the user project. This state should implement the
+ * actual work performed on the attached device and changed to the
+ * \ref HOST_STATE_Suspended or \ref HOST_STATE_WaitForDeviceRemoval states as needed.
+ */
+ HOST_STATE_Suspended = 15, /**< May be implemented by the user project. This state should be maintained
+ * while the bus is suspended, and changed to either the \ref HOST_STATE_Configured
+ * (after resuming the bus with the USB_Host_ResumeBus() macro) or the
+ * \ref HOST_STATE_WaitForDeviceRemoval states as needed.
+ */
+ };
+
+ /** Enum for the error codes for the \ref EVENT_USB_Host_HostError() event.
+ *
+ * \see \ref Group_Events 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 \ref EVENT_USB_Host_DeviceEnumerationFailed() event.
+ *
+ * \see \ref Group_Events 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 \ref EVENT_USB_Host_DeviceEnumerationFailed()
+ * event.
+ */
+ HOST_ENUMERROR_WaitStage = 1, /**< One of the delays between enumeration steps failed
+ * to complete successfully, 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 successfully.
+ */
+ HOST_ENUMERROR_PipeConfigError = 4, /**< The default control pipe (address 0) failed to
+ * configure correctly.
+ */
+ };
+
+ /* Inline Functions: */
+ /** Returns the current USB frame number, when in host mode. Every millisecond the USB bus is active (i.e. not suspended)
+ * the frame number is incremented by one.
+ */
+ static inline uint16_t USB_Host_GetFrameNumber(void)
+ {
+ return UHFNUM;
+ }
+
+ #if !defined(NO_SOF_EVENTS)
+ /** Enables the host mode Start Of Frame events. When enabled, this causes the
+ * \ref EVENT_USB_Host_StartOfFrame() event to fire once per millisecond, synchronized to the USB bus,
+ * at the start of each USB frame when a device is enumerated while in host mode.
+ *
+ * \note Not available when the NO_SOF_EVENTS compile time token is defined.
+ */
+ static inline void USB_Host_EnableSOFEvents(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Host_EnableSOFEvents(void)
+ {
+ USB_INT_Enable(USB_INT_HSOFI);
+ }
+
+ /** Disables the host mode Start Of Frame events. When disabled, this stops the firing of the
+ * \ref EVENT_USB_Host_StartOfFrame() event when enumerated in host mode.
+ *
+ * \note Not available when the NO_SOF_EVENTS compile time token is defined.
+ */
+ static inline void USB_Host_DisableSOFEvents(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Host_DisableSOFEvents(void)
+ {
+ USB_INT_Disable(USB_INT_HSOFI);
+ }
+ #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.
+ */
+ static inline void USB_Host_ResetBus(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Host_ResetBus(void)
+ {
+ UHCON |= (1 << RESET);
+ }
+
+ /** Determines if a previously issued bus reset (via the \ref USB_Host_ResetBus() macro) has
+ * completed.
+ *
+ * \return Boolean true if no bus reset is currently being sent, false otherwise.
+ */
+ static inline bool USB_Host_IsBusResetComplete(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool USB_Host_IsBusResetComplete(void)
+ {
+ return ((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.
+ */
+ static inline void USB_Host_ResumeBus(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Host_ResumeBus(void)
+ {
+ UHCON |= (1 << SOFEN);
+ }
+
+ /** Suspends the USB bus, preventing any communications from occurring 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.
+ */
+ static inline void USB_Host_SuspendBus(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Host_SuspendBus(void)
+ {
+ UHCON &= ~(1 << SOFEN);
+ }
+
+ /** Determines if the USB bus has been suspended via the use of the \ref 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.
+ *
+ * \return Boolean true if the bus is currently suspended, false otherwise.
+ */
+ static inline bool USB_Host_IsBusSuspended(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool USB_Host_IsBusSuspended(void)
+ {
+ return ((UHCON & (1 << SOFEN)) ? false : true);
+ }
+
+ /** Determines 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).
+ *
+ * \return Boolean true if the attached device is enumerated in Full Speed mode, false otherwise.
+ */
+ static inline bool USB_Host_IsDeviceFullSpeed(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool USB_Host_IsDeviceFullSpeed(void)
+ {
+ return ((USBSTA & (1 << SPEED)) ? true : false);
+ }
+
+ /** Determines 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.
+ *
+ * \return Boolean true if the attached device has sent a Remote Wakeup request, false otherwise.
+ */
+ static inline bool USB_Host_IsRemoteWakeupSent(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool USB_Host_IsRemoteWakeupSent(void)
+ {
+ return ((UHINT & (1 << RXRSMI)) ? true : false);
+ }
+
+ /** Clears the flag indicating that a Remote Wakeup request has been issued by an attached device. */
+ static inline void USB_Host_ClearRemoteWakeupSent(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Host_ClearRemoteWakeupSent(void)
+ {
+ UHINT &= ~(1 << RXRSMI);
+ }
+
+ /** 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.
+ */
+ static inline void USB_Host_ResumeFromWakeupRequest(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Host_ResumeFromWakeupRequest(void)
+ {
+ UHCON |= (1 << RESUME);
+ }
+
+ /** Determines if a resume from Remote Wakeup request is currently being sent to an attached
+ * device.
+ *
+ * \return Boolean true if no resume request is currently being sent, false otherwise.
+ */
+ static inline bool USB_Host_IsResumeFromWakeupRequestSent(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool USB_Host_IsResumeFromWakeupRequestSent(void)
+ {
+ return ((UHCON & (1 << RESUME)) ? false : true);
+ }
+
+ /* Function Prototypes: */
+ /** Convenience function. This routine sends a SetConfiguration standard request to the attached
+ * device, with the given configuration index. This can be used to easily set the device
+ * configuration without creating and sending the request manually.
+ *
+ * \note After this routine returns, the control pipe will be selected.
+ *
+ * \param[in] ConfigNumber Configuration index to send to the device.
+ *
+ * \return A value from the \ref USB_Host_SendControlErrorCodes_t enum to indicate the result.
+ */
+ uint8_t USB_Host_SetDeviceConfiguration(const uint8_t ConfigNumber);
+
+ /** Convenience function. This routine sends a GetDescriptor standard request to the attached
+ * device, requesting the device descriptor. This can be used to easily retrieve information
+ * about the device such as its VID, PID and power requirements.
+ *
+ * \note After this routine returns, the control pipe will be selected.
+ *
+ * \param[out] DeviceDescriptorPtr Pointer to the destination device descriptor structure where
+ * the read data is to be stored.
+ *
+ * \return A value from the \ref USB_Host_SendControlErrorCodes_t enum to indicate the result.
+ */
+ uint8_t USB_Host_GetDeviceDescriptor(void* const DeviceDescriptorPtr);
+
+ /** Convenience function. This routine sends a GetDescriptor standard request to the attached
+ * device, requesting the string descriptor of the specified index. This can be used to easily
+ * retrieve string descriptors from the device by index, after the index is obtained from the
+ * Device or Configuration descriptors.
+ *
+ * \note After this routine returns, the control pipe will be selected.
+ *
+ * \param[in] Index Index of the string index to retrieve.
+ * \param[out] Buffer Pointer to the destination buffer where the retrieved string descriptor is
+ * to be stored.
+ * \param[in] BufferLength Maximum size of the string descriptor which can be stored into the buffer.
+ *
+ * \return A value from the \ref USB_Host_SendControlErrorCodes_t enum to indicate the result.
+ */
+ uint8_t USB_Host_GetDeviceStringDescriptor(const uint8_t Index,
+ void* const Buffer,
+ const uint8_t BufferLength);
+
+ /** Clears a stall condition on the given pipe, via a ClearFeature request to the attached device.
+ *
+ * \note After this routine returns, the control pipe will be selected.
+ *
+ * \param[in] EndpointIndex Index of the endpoint to clear, including the endpoint's direction.
+ *
+ * \return A value from the \ref USB_Host_SendControlErrorCodes_t enum to indicate the result.
+ */
+ uint8_t USB_Host_ClearPipeStall(const uint8_t EndpointIndex);
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ static inline void USB_Host_HostMode_On(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Host_HostMode_On(void)
+ {
+ USBCON |= (1 << HOST);
+ }
+
+ static inline void USB_Host_HostMode_Off(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Host_HostMode_Off(void)
+ {
+ USBCON &= ~(1 << HOST);
+ }
+
+ static inline void USB_Host_VBUS_Auto_Enable(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Host_VBUS_Auto_Enable(void)
+ {
+ OTGCON &= ~(1 << VBUSHWC);
+ UHWCON |= (1 << UVCONE);
+ }
+
+ static inline void USB_Host_VBUS_Manual_Enable(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Host_VBUS_Manual_Enable(void)
+ {
+ OTGCON |= (1 << VBUSHWC);
+ UHWCON &= ~(1 << UVCONE);
+
+ DDRE |= (1 << 7);
+ }
+
+ static inline void USB_Host_VBUS_Auto_On(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Host_VBUS_Auto_On(void)
+ {
+ OTGCON |= (1 << VBUSREQ);
+ }
+
+ static inline void USB_Host_VBUS_Manual_On(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Host_VBUS_Manual_On(void)
+ {
+ PORTE |= (1 << 7);
+ }
+
+ static inline void USB_Host_VBUS_Auto_Off(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Host_VBUS_Auto_Off(void)
+ {
+ OTGCON |= (1 << VBUSRQC);
+ }
+
+ static inline void USB_Host_VBUS_Manual_Off(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Host_VBUS_Manual_Off(void)
+ {
+ PORTE &= ~(1 << 7);
+ }
+
+ static inline void USB_Host_SetDeviceAddress(const uint8_t Address) ATTR_ALWAYS_INLINE;
+ static inline void USB_Host_SetDeviceAddress(const uint8_t Address)
+ {
+ UHADDR = (Address & 0x7F);
+ }
+
+ /* Enums: */
+ enum USB_Host_WaitMSErrorCodes_t
+ {
+ HOST_WAITERROR_Successful = 0,
+ HOST_WAITERROR_DeviceDisconnect = 1,
+ HOST_WAITERROR_PipeError = 2,
+ HOST_WAITERROR_SetupStalled = 3,
+ };
+
+ /* Function Prototypes: */
+ void USB_Host_ProcessNextHostState(void);
+ uint8_t USB_Host_WaitMS(uint8_t MS);
+
+ #if defined(__INCLUDE_FROM_HOST_C)
+ static void USB_Host_ResetDevice(void);
+ #endif
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/LUFA/Drivers/USB/LowLevel/OTG.h b/LUFA/Drivers/USB/LowLevel/OTG.h
new file mode 100644
index 0000000..d213552
--- /dev/null
+++ b/LUFA/Drivers/USB/LowLevel/OTG.h
@@ -0,0 +1,155 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2010.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, 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
+ * \brief USB OTG mode definitions.
+ *
+ * This file contains structures, function prototypes and macros related to USB OTG mode, where two USB devices
+ * may be linked directly together and exchange host/device roles as needed.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB driver
+ * dispatch header located in LUFA/Drivers/USB/USB.h.
+ */
+
+/** \ingroup Group_USB
+ * @defgroup Group_OTG USB On The Go (OTG) Management
+ *
+ * This module contains 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.
+ *
+ * @{
+ */
+
+#ifndef __USBOTG_H__
+#define __USBOTG_H__
+
+ /* Includes: */
+ #include <avr/io.h>
+ #include <stdbool.h>
+
+ #include "../../../Common/Common.h"
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_USB_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Mask for the VBUS pulsing method of SRP, supported by some OTG devices.
+ *
+ * \see \ref USB_OTG_Device_InitiateSRP().
+ */
+ #define USB_OTG_SRP_VBUS (1 << SRPSEL)
+
+ /** Mask for the Data + pulsing method of SRP, supported by some OTG devices.
+ *
+ * \see \ref USB_OTG_Device_InitiateSRP().
+ */
+ #define USB_OTG_STP_DATA 0
+
+ /* Inline Functions: */
+ /** Initiate a Host Negotiation Protocol request. This indicates to the other connected device
+ * that the device wishes to change device/host roles.
+ */
+ static inline void USB_OTG_Device_RequestHNP(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_OTG_Device_RequestHNP(void)
+ {
+ OTGCON |= (1 << HNPREQ);
+ }
+
+ /** Cancel a Host Negotiation Protocol request. This stops a pending HNP request to the other
+ * connected device.
+ */
+ static inline void USB_OTG_Device_CancelHNPRequest(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_OTG_Device_CancelHNPRequest(void)
+ {
+ OTGCON &= ~(1 << HNPREQ);
+ }
+
+ /** Determines if the device is currently sending a HNP to an attached host.
+ *
+ * \return Boolean true if currently sending a HNP to the other connected device, false otherwise
+ */
+ static inline bool USB_OTG_Device_IsSendingHNP(void) ATTR_ALWAYS_INLINE;
+ static inline bool USB_OTG_Device_IsSendingHNP(void)
+ {
+ return ((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 pull-up resistor.
+ *
+ * \param[in] SRPTypeMask Mask indicating the type of SRP to use, either \ref USB_OTG_SRP_VBUS or
+ * \ref USB_OTG_STP_DATA.
+ */
+ static inline void USB_OTG_Device_InitiateSRP(const uint8_t SRPTypeMask) ATTR_ALWAYS_INLINE;
+ static inline void USB_OTG_Device_InitiateSRP(const uint8_t SRPTypeMask)
+ {
+ OTGCON = ((OTGCON & ~(1 << SRPSEL)) | (SRPTypeMask | (1 << SRPREQ)));
+ }
+
+ /** Accepts a HNP from a connected device, indicating that both devices should exchange
+ * device/host roles.
+ */
+ static inline void USB_OTG_Host_AcceptHNP(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_OTG_Host_AcceptHNP(void)
+ {
+ OTGCON |= (1 << HNPREQ);
+ }
+
+ /** Rejects a HNP from a connected device, indicating that both devices should remain in their
+ * current device/host roles.
+ */
+ static inline void USB_OTG_Host_RejectHNP(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_OTG_Host_RejectHNP(void)
+ {
+ OTGCON &= ~(1 << HNPREQ);
+ }
+
+ /** Indicates if the connected device is not currently sending a HNP request.
+ *
+ * \return Boolean true if a HNP is currently being issued by the connected device, false otherwise.
+ */
+ static inline bool USB_OTG_Host_IsHNPReceived(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool USB_OTG_Host_IsHNPReceived(void)
+ {
+ return ((OTGCON & (1 << HNPREQ)) ? true : false);
+ }
+
+#endif
+
+/** @} */
+
diff --git a/LUFA/Drivers/USB/LowLevel/Pipe.c b/LUFA/Drivers/USB/LowLevel/Pipe.c
new file mode 100644
index 0000000..c414129
--- /dev/null
+++ b/LUFA/Drivers/USB/LowLevel/Pipe.c
@@ -0,0 +1,140 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2010.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, 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.
+*/
+
+#define __INCLUDE_FROM_USB_DRIVER
+#include "../HighLevel/USBMode.h"
+
+#if defined(USB_CAN_BE_HOST)
+
+#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 & PIPE_EPNUM_MASK) << PEPNUM0));
+ UPCFG1X = ((1 << ALLOC) | Banks | Pipe_BytesToEPSizeMask(Size));
+
+ Pipe_SetInfiniteINRequests();
+
+ return Pipe_IsConfigured();
+}
+
+void Pipe_ClearPipes(void)
+{
+ UPINT = 0;
+
+ for (uint8_t PNum = 0; PNum < PIPE_TOTAL_PIPES; PNum++)
+ {
+ Pipe_SelectPipe(PNum);
+ UPIENX = 0;
+ UPINTX = 0;
+ UPCFG1X = 0;
+ Pipe_DisablePipe();
+ }
+}
+
+bool Pipe_IsEndpointBound(const uint8_t EndpointAddress)
+{
+ uint8_t PrevPipeNumber = Pipe_GetCurrentPipe();
+
+ for (uint8_t PNum = 0; PNum < PIPE_TOTAL_PIPES; PNum++)
+ {
+ Pipe_SelectPipe(PNum);
+
+ if (!(Pipe_IsConfigured()))
+ continue;
+
+ uint8_t PipeToken = Pipe_GetPipeToken();
+ bool PipeTokenCorrect = true;
+
+ if (PipeToken != PIPE_TOKEN_SETUP)
+ PipeTokenCorrect = (PipeToken == ((EndpointAddress & PIPE_EPDIR_MASK) ? PIPE_TOKEN_IN : PIPE_TOKEN_OUT));
+
+ if (PipeTokenCorrect && (Pipe_BoundEndpointNumber() == (EndpointAddress & PIPE_EPNUM_MASK)))
+ return true;
+ }
+
+ Pipe_SelectPipe(PrevPipeNumber);
+ return false;
+}
+
+uint8_t Pipe_WaitUntilReady(void)
+{
+ #if (USB_STREAM_TIMEOUT_MS < 0xFF)
+ uint8_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS;
+ #else
+ uint16_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS;
+ #endif
+
+ uint16_t PreviousFrameNumber = USB_Host_GetFrameNumber();
+
+ for (;;)
+ {
+ if (Pipe_GetPipeToken() == PIPE_TOKEN_IN)
+ {
+ if (Pipe_IsINReceived())
+ return PIPE_READYWAIT_NoError;
+ }
+ else
+ {
+ if (Pipe_IsOUTReady())
+ return PIPE_READYWAIT_NoError;
+ }
+
+ if (Pipe_IsStalled())
+ return PIPE_READYWAIT_PipeStalled;
+ else if (USB_HostState == HOST_STATE_Unattached)
+ return PIPE_READYWAIT_DeviceDisconnected;
+
+ uint16_t CurrentFrameNumber = USB_Host_GetFrameNumber();
+
+ if (CurrentFrameNumber != PreviousFrameNumber)
+ {
+ PreviousFrameNumber = CurrentFrameNumber;
+
+ if (!(TimeoutMSRem--))
+ return PIPE_READYWAIT_Timeout;
+ }
+ }
+}
+
+#endif
+
diff --git a/LUFA/Drivers/USB/LowLevel/Pipe.h b/LUFA/Drivers/USB/LowLevel/Pipe.h
new file mode 100644
index 0000000..7bdb508
--- /dev/null
+++ b/LUFA/Drivers/USB/LowLevel/Pipe.h
@@ -0,0 +1,941 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2010.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, 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
+ * \brief USB host pipe management definitions.
+ *
+ * This file contains structures, function prototypes and macros related to the management of the device's
+ * data pipes when the library is initialized in USB host mode.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB driver
+ * dispatch header located in LUFA/Drivers/USB/USB.h.
+ */
+
+/** \ingroup Group_PipeManagement
+ * @defgroup Group_PipeRW Pipe Data Reading and Writing
+ *
+ * Functions, macros, variables, enums and types related to data reading and writing from and to pipes.
+ */
+
+/** \ingroup Group_PipeRW
+ * @defgroup Group_PipePrimitiveRW Read/Write of Primitive Data Types
+ *
+ * Functions, macros, variables, enums and types related to data reading and writing of primitive data types
+ * from and to pipes.
+ */
+
+/** \ingroup Group_PipeManagement
+ * @defgroup Group_PipePacketManagement Pipe Packet Management
+ *
+ * Functions, macros, variables, enums and types related to packet management of pipes.
+ */
+
+/** \ingroup Group_PipeManagement
+ * @defgroup Group_PipeControlReq Pipe Control Request Management
+ *
+ * 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.
+ */
+
+/** \ingroup Group_USB
+ * @defgroup Group_PipeManagement Pipe Management
+ *
+ * This module contains 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/receive functions
+ * for various data types.
+ *
+ * @{
+ */
+
+#ifndef __PIPE_H__
+#define __PIPE_H__
+
+ /* Includes: */
+ #include <avr/io.h>
+ #include <stdbool.h>
+
+ #include "../../../Common/Common.h"
+ #include "../HighLevel/USBTask.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_USB_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** \name Pipe Error Flag Masks */
+ //@{
+ /** Mask for \ref Pipe_GetErrorFlags(), indicating that an overflow error occurred in the pipe on the received data. */
+ #define PIPE_ERRORFLAG_OVERFLOW (1 << 6)
+
+ /** Mask for \ref Pipe_GetErrorFlags(), indicating that an underflow error occurred in the pipe on the received data. */
+ #define PIPE_ERRORFLAG_UNDERFLOW (1 << 5)
+
+ /** Mask for \ref Pipe_GetErrorFlags(), indicating that a CRC error occurred in the pipe on the received data. */
+ #define PIPE_ERRORFLAG_CRC16 (1 << 4)
+
+ /** Mask for \ref Pipe_GetErrorFlags(), indicating that a hardware timeout error occurred in the pipe. */
+ #define PIPE_ERRORFLAG_TIMEOUT (1 << 3)
+
+ /** Mask for \ref Pipe_GetErrorFlags(), indicating that a hardware PID error occurred in the pipe. */
+ #define PIPE_ERRORFLAG_PID (1 << 2)
+
+ /** Mask for \ref Pipe_GetErrorFlags(), indicating that a hardware data PID error occurred in the pipe. */
+ #define PIPE_ERRORFLAG_DATAPID (1 << 1)
+
+ /** Mask for \ref Pipe_GetErrorFlags(), indicating that a hardware data toggle error occurred in the pipe. */
+ #define PIPE_ERRORFLAG_DATATGL (1 << 0)
+ //@}
+
+ /** \name Pipe Token Masks */
+ //@{
+ /** Token mask for \ref 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 (0 << PTOKEN0)
+
+ /** Token mask for \ref 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 (1 << PTOKEN0)
+
+ /** Token mask for \ref Pipe_ConfigurePipe(). This sets the pipe as a OUT token (for non-CONTROL type pipes),
+ * indicating that the pipe data will flow from host to device.
+ */
+ #define PIPE_TOKEN_OUT (2 << PTOKEN0)
+ //@}
+
+ /** \name Pipe Bank Mode Masks */
+ //@{
+ /** Mask for the bank mode selection for the \ref 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 << EPBK0)
+
+ /** Mask for the bank mode selection for the \ref 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 64
+
+ /** 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 0x0F
+
+ /** Endpoint direction mask, for masking against endpoint addresses to retrieve the endpoint's
+ * direction for comparing with the ENDPOINT_DESCRIPTOR_DIR_* masks.
+ */
+ #define PIPE_EPDIR_MASK 0x80
+
+ /* Enums: */
+ /** Enum for the possible error return codes of the Pipe_WaitUntilReady function.
+ *
+ * \ingroup Group_PipeRW
+ */
+ 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
+ * \ref USB_STREAM_TIMEOUT_MS macro.
+ */
+ };
+
+ /* Inline Functions: */
+ /** Indicates the number of bytes currently stored in the current pipes's selected bank.
+ *
+ * \note The return width of this function may differ, depending on the maximum pipe bank size
+ * of the selected AVR model.
+ *
+ * \ingroup Group_PipeRW
+ *
+ * \return Total number of bytes in the currently selected Pipe's FIFO buffer.
+ */
+ static inline uint16_t Pipe_BytesInPipe(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint16_t Pipe_BytesInPipe(void)
+ {
+ return UPBCX;
+ }
+
+ /** 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.
+ *
+ * \return Index of the currently selected pipe.
+ */
+ static inline uint8_t Pipe_GetCurrentPipe(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint8_t Pipe_GetCurrentPipe(void)
+ {
+ return (UPNUM & PIPE_PIPENUM_MASK);
+ }
+
+ /** 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.
+ *
+ * \param[in] PipeNumber Index of the pipe to select.
+ */
+ static inline void Pipe_SelectPipe(const uint8_t PipeNumber) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_SelectPipe(const uint8_t PipeNumber)
+ {
+ UPNUM = PipeNumber;
+ }
+
+ /** Resets the desired pipe, including the pipe banks and flags.
+ *
+ * \param[in] PipeNumber Index of the pipe to reset.
+ */
+ static inline void Pipe_ResetPipe(const uint8_t PipeNumber) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_ResetPipe(const uint8_t PipeNumber)
+ {
+ UPRST = (1 << PipeNumber);
+ UPRST = 0;
+ }
+
+ /** Enables the currently selected pipe so that data can be sent and received through it to and from
+ * an attached device.
+ *
+ * \pre The currently selected pipe must first be configured properly via \ref Pipe_ConfigurePipe().
+ */
+ static inline void Pipe_EnablePipe(void) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_EnablePipe(void)
+ {
+ UPCONX |= (1 << PEN);
+ }
+
+ /** Disables the currently selected pipe so that data cannot be sent and received through it to and
+ * from an attached device.
+ */
+ static inline void Pipe_DisablePipe(void) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_DisablePipe(void)
+ {
+ UPCONX &= ~(1 << PEN);
+ }
+
+ /** Determines if the currently selected pipe is enabled, but not necessarily configured.
+ *
+ * \return Boolean True if the currently selected pipe is enabled, false otherwise.
+ */
+ static inline bool Pipe_IsEnabled(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Pipe_IsEnabled(void)
+ {
+ return ((UPCONX & (1 << PEN)) ? true : false);
+ }
+
+ /** Gets the current pipe token, indicating the pipe's data direction and type.
+ *
+ * \return The current pipe token, as a PIPE_TOKEN_* mask.
+ */
+ static inline uint8_t Pipe_GetPipeToken(void) ATTR_ALWAYS_INLINE;
+ static inline uint8_t Pipe_GetPipeToken(void)
+ {
+ return (UPCFG0X & (0x03 << PTOKEN0));
+ }
+
+ /** Sets the token for the currently selected pipe to one of the tokens specified by the PIPE_TOKEN_*
+ * masks. This can be used on CONTROL type pipes, to allow for bidirectional transfer of data during
+ * control requests, or on regular pipes to allow for half-duplex bidirectional data transfer to devices
+ * which have two endpoints of opposite direction sharing the same endpoint address within the device.
+ *
+ * \param[in] Token New pipe token to set the selected pipe to, as a PIPE_TOKEN_* mask.
+ */
+ static inline void Pipe_SetPipeToken(const uint8_t Token) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_SetPipeToken(const uint8_t Token)
+ {
+ UPCFG0X = ((UPCFG0X & ~(0x03 << PTOKEN0)) | Token);
+ }
+
+ /** Configures the currently selected pipe to allow for an unlimited number of IN requests. */
+ static inline void Pipe_SetInfiniteINRequests(void) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_SetInfiniteINRequests(void)
+ {
+ UPCONX |= (1 << INMODE);
+ }
+
+ /** 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.
+ *
+ * \param[in] TotalINRequests Total number of IN requests that the pipe may receive before freezing.
+ */
+ static inline void Pipe_SetFiniteINRequests(const uint8_t TotalINRequests) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_SetFiniteINRequests(const uint8_t TotalINRequests)
+ {
+ UPCONX &= ~(1 << INMODE);
+ UPINRQX = TotalINRequests;
+ }
+
+ /** Determines if the currently selected pipe is configured.
+ *
+ * \return Boolean true if the selected pipe is configured, false otherwise.
+ */
+ static inline bool Pipe_IsConfigured(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Pipe_IsConfigured(void)
+ {
+ return ((UPSTAX & (1 << CFGOK)) ? true : false);
+ }
+
+ /** Retrieves the endpoint number of the endpoint within the attached device that the currently selected
+ * pipe is bound to.
+ *
+ * \return Endpoint number the currently selected pipe is bound to.
+ */
+ static inline uint8_t Pipe_BoundEndpointNumber(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint8_t Pipe_BoundEndpointNumber(void)
+ {
+ return ((UPCFG0X >> PEPNUM0) & PIPE_EPNUM_MASK);
+ }
+
+ /** Sets the period between interrupts for an INTERRUPT type pipe to a specified number of milliseconds.
+ *
+ * \param[in] Milliseconds Number of milliseconds between each pipe poll.
+ */
+ static inline void Pipe_SetInterruptPeriod(const uint8_t Milliseconds) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_SetInterruptPeriod(const uint8_t Milliseconds)
+ {
+ UPCFG2X = Milliseconds;
+ }
+
+ /** Returns a mask indicating which pipe's interrupt periods have elapsed, indicating that the pipe should
+ * be serviced.
+ *
+ * \return Mask whose bits indicate which pipes have interrupted.
+ */
+ static inline uint8_t Pipe_GetPipeInterrupts(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint8_t Pipe_GetPipeInterrupts(void)
+ {
+ return UPINT;
+ }
+
+ /** Determines if the specified pipe number has interrupted (valid only for INTERRUPT type
+ * pipes).
+ *
+ * \param[in] PipeNumber Index of the pipe whose interrupt flag should be tested.
+ *
+ * \return Boolean true if the specified pipe has interrupted, false otherwise.
+ */
+ static inline bool Pipe_HasPipeInterrupted(const uint8_t PipeNumber) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Pipe_HasPipeInterrupted(const uint8_t PipeNumber)
+ {
+ return ((UPINT & (1 << PipeNumber)) ? true : false);
+ }
+
+ /** Unfreezes the selected pipe, allowing it to communicate with an attached device. */
+ static inline void Pipe_Unfreeze(void) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_Unfreeze(void)
+ {
+ UPCONX &= ~(1 << PFREEZE);
+ }
+
+ /** Freezes the selected pipe, preventing it from communicating with an attached device. */
+ static inline void Pipe_Freeze(void) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_Freeze(void)
+ {
+ UPCONX |= (1 << PFREEZE);
+ }
+
+ /** Determines if the currently selected pipe is frozen, and not able to accept data.
+ *
+ * \return Boolean true if the currently selected pipe is frozen, false otherwise.
+ */
+ static inline bool Pipe_IsFrozen(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Pipe_IsFrozen(void)
+ {
+ return ((UPCONX & (1 << PFREEZE)) ? true : false);
+ }
+
+ /** Clears the master pipe error flag. */
+ static inline void Pipe_ClearError(void) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_ClearError(void)
+ {
+ UPINTX &= ~(1 << PERRI);
+ }
+
+ /** Determines 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 \ref Pipe_GetErrorFlags() macro for information on retrieving the exact error flag.
+ *
+ * \return Boolean true if an error has occurred on the selected pipe, false otherwise.
+ */
+ static inline bool Pipe_IsError(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Pipe_IsError(void)
+ {
+ return ((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.
+ */
+ static inline void Pipe_ClearErrorFlags(void) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_ClearErrorFlags(void)
+ {
+ UPERRX = 0;
+ }
+
+ /** Gets a mask of the hardware error flags which have occurred on the currently selected pipe. This
+ * value can then be masked against the PIPE_ERRORFLAG_* masks to determine what error has occurred.
+ *
+ * \return Mask comprising of PIPE_ERRORFLAG_* bits indicating what error has occurred on the selected pipe.
+ */
+ static inline uint8_t Pipe_GetErrorFlags(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint8_t Pipe_GetErrorFlags(void)
+ {
+ return ((UPERRX & (PIPE_ERRORFLAG_CRC16 | PIPE_ERRORFLAG_TIMEOUT |
+ PIPE_ERRORFLAG_PID | PIPE_ERRORFLAG_DATAPID |
+ PIPE_ERRORFLAG_DATATGL)) |
+ (UPSTAX & (PIPE_ERRORFLAG_OVERFLOW | PIPE_ERRORFLAG_UNDERFLOW)));
+ }
+
+ /** Retrieves the number of busy banks in the currently selected pipe, which have been queued for
+ * transmission via the \ref Pipe_ClearOUT() command, or are awaiting acknowledgement via the
+ * \ref Pipe_ClearIN() command.
+ *
+ * \ingroup Group_PipePacketManagement
+ *
+ * \return Total number of busy banks in the selected pipe.
+ */
+ static inline uint8_t Pipe_GetBusyBanks(void)
+ {
+ return (UPSTAX & (0x03 << NBUSYBK0));
+ }
+
+ /** Determines 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 occurred in the pipe, or if the pipe
+ * is an IN direction and no packet (or an empty packet) has been received, or if the pipe is an OUT
+ * direction and the pipe bank is full.
+ *
+ * \note This function is not valid on CONTROL type pipes.
+ *
+ * \ingroup Group_PipePacketManagement
+ *
+ * \return Boolean true if the currently selected pipe may be read from or written to, depending on its direction.
+ */
+ static inline bool Pipe_IsReadWriteAllowed(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Pipe_IsReadWriteAllowed(void)
+ {
+ return ((UPINTX & (1 << RWAL)) ? true : false);
+ }
+
+ /** Determines if a packet has been received on the currently selected IN pipe from the attached device.
+ *
+ * \ingroup Group_PipePacketManagement
+ *
+ * \return Boolean true if the current pipe has received an IN packet, false otherwise.
+ */
+ static inline bool Pipe_IsINReceived(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Pipe_IsINReceived(void)
+ {
+ return ((UPINTX & (1 << RXINI)) ? true : false);
+ }
+
+ /** Determines if the currently selected OUT pipe is ready to send an OUT packet to the attached device.
+ *
+ * \ingroup Group_PipePacketManagement
+ *
+ * \return Boolean true if the current pipe is ready for an OUT packet, false otherwise.
+ */
+ static inline bool Pipe_IsOUTReady(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Pipe_IsOUTReady(void)
+ {
+ return ((UPINTX & (1 << TXOUTI)) ? true : false);
+ }
+
+ /** Determines if no SETUP request is currently being sent to the attached device on the selected
+ * CONTROL type pipe.
+ *
+ * \ingroup Group_PipePacketManagement
+ *
+ * \return Boolean true if the current pipe is ready for a SETUP packet, false otherwise.
+ */
+ static inline bool Pipe_IsSETUPSent(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Pipe_IsSETUPSent(void)
+ {
+ return ((UPINTX & (1 << TXSTPI)) ? true : false);
+ }
+
+ /** Sends the currently selected CONTROL type pipe's contents to the device as a SETUP packet.
+ *
+ * \ingroup Group_PipePacketManagement
+ */
+ static inline void Pipe_ClearSETUP(void) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_ClearSETUP(void)
+ {
+ UPINTX &= ~((1 << TXSTPI) | (1 << FIFOCON));
+ }
+
+ /** Acknowledges the reception of a setup IN request from the attached device on the currently selected
+ * pipe, freeing the bank ready for the next packet.
+ *
+ * \ingroup Group_PipePacketManagement
+ */
+ static inline void Pipe_ClearIN(void) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_ClearIN(void)
+ {
+ UPINTX &= ~((1 << RXINI) | (1 << FIFOCON));
+ }
+
+ /** Sends the currently selected pipe's contents to the device as an OUT packet on the selected pipe, freeing
+ * the bank ready for the next packet.
+ *
+ * \ingroup Group_PipePacketManagement
+ */
+ static inline void Pipe_ClearOUT(void) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_ClearOUT(void)
+ {
+ UPINTX &= ~((1 << TXOUTI) | (1 << FIFOCON));
+ }
+
+ /** Determines if the device sent a NAK (Negative Acknowledge) in response to the last sent packet on
+ * the currently selected pipe. This occurs 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 cleared using \ref Pipe_ClearNAKReceived() before the previous (or any other) packet
+ * can be re-sent.
+ *
+ * \ingroup Group_PipePacketManagement
+ *
+ * \return Boolean true if an NAK has been received on the current pipe, false otherwise.
+ */
+ static inline bool Pipe_IsNAKReceived(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Pipe_IsNAKReceived(void)
+ {
+ return ((UPINTX & (1 << NAKEDI)) ? true : false);
+ }
+
+ /** Clears the NAK condition on the currently selected pipe.
+ *
+ * \ingroup Group_PipePacketManagement
+ *
+ * \see \ref Pipe_IsNAKReceived() for more details.
+ */
+ static inline void Pipe_ClearNAKReceived(void) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_ClearNAKReceived(void)
+ {
+ UPINTX &= ~(1 << NAKEDI);
+ }
+
+ /** Determines if the currently selected pipe has had the STALL condition set by the attached device.
+ *
+ * \ingroup Group_PipePacketManagement
+ *
+ * \return Boolean true if the current pipe has been stalled by the attached device, false otherwise.
+ */
+ static inline bool Pipe_IsStalled(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Pipe_IsStalled(void)
+ {
+ return ((UPINTX & (1 << RXSTALLI)) ? true : false);
+ }
+
+ /** Clears the STALL condition detection flag on the currently selected pipe, but does not clear the
+ * STALL condition itself (this must be done via a ClearFeature control request to the device).
+ *
+ * \ingroup Group_PipePacketManagement
+ */
+ static inline void Pipe_ClearStall(void) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_ClearStall(void)
+ {
+ UPINTX &= ~(1 << RXSTALLI);
+ }
+
+ /** Reads one byte from the currently selected pipe's bank, for OUT direction pipes.
+ *
+ * \ingroup Group_PipePrimitiveRW
+ *
+ * \return Next byte in the currently selected pipe's FIFO buffer.
+ */
+ static inline uint8_t Pipe_Read_Byte(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint8_t Pipe_Read_Byte(void)
+ {
+ return UPDATX;
+ }
+
+ /** Writes one byte from the currently selected pipe's bank, for IN direction pipes.
+ *
+ * \ingroup Group_PipePrimitiveRW
+ *
+ * \param[in] Byte Next byte to write into the the currently selected pipe's FIFO buffer.
+ */
+ static inline void Pipe_Write_Byte(const uint8_t Byte) ATTR_ALWAYS_INLINE;
+ 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.
+ *
+ * \ingroup Group_PipePrimitiveRW
+ */
+ static inline void Pipe_Discard_Byte(void) ATTR_ALWAYS_INLINE;
+ 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.
+ *
+ * \ingroup Group_PipePrimitiveRW
+ *
+ * \return Next word in the currently selected pipe's FIFO buffer.
+ */
+ static inline uint16_t Pipe_Read_Word_LE(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint16_t Pipe_Read_Word_LE(void)
+ {
+ union
+ {
+ uint16_t Word;
+ uint8_t Bytes[2];
+ } Data;
+
+ Data.Bytes[0] = UPDATX;
+ Data.Bytes[1] = UPDATX;
+
+ return Data.Word;
+ }
+
+ /** Reads two bytes from the currently selected pipe's bank in big endian format, for OUT
+ * direction pipes.
+ *
+ * \ingroup Group_PipePrimitiveRW
+ *
+ * \return Next word in the currently selected pipe's FIFO buffer.
+ */
+ static inline uint16_t Pipe_Read_Word_BE(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint16_t Pipe_Read_Word_BE(void)
+ {
+ union
+ {
+ uint16_t Word;
+ uint8_t Bytes[2];
+ } Data;
+
+ Data.Bytes[1] = UPDATX;
+ Data.Bytes[0] = UPDATX;
+
+ return Data.Word;
+ }
+
+ /** Writes two bytes to the currently selected pipe's bank in little endian format, for IN
+ * direction pipes.
+ *
+ * \ingroup Group_PipePrimitiveRW
+ *
+ * \param[in] Word Next word to write to the currently selected pipe's FIFO buffer.
+ */
+ static inline void Pipe_Write_Word_LE(const uint16_t Word) ATTR_ALWAYS_INLINE;
+ 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.
+ *
+ * \ingroup Group_PipePrimitiveRW
+ *
+ * \param[in] Word Next word to write to the currently selected pipe's FIFO buffer.
+ */
+ static inline void Pipe_Write_Word_BE(const uint16_t Word) ATTR_ALWAYS_INLINE;
+ 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.
+ *
+ * \ingroup Group_PipePrimitiveRW
+ */
+ static inline void Pipe_Discard_Word(void) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_Discard_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.
+ *
+ * \ingroup Group_PipePrimitiveRW
+ *
+ * \return Next double word in the currently selected pipe's FIFO buffer.
+ */
+ static inline uint32_t Pipe_Read_DWord_LE(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ 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.
+ *
+ * \ingroup Group_PipePrimitiveRW
+ *
+ * \return Next double word in the currently selected pipe's FIFO buffer.
+ */
+ static inline uint32_t Pipe_Read_DWord_BE(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ 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.
+ *
+ * \ingroup Group_PipePrimitiveRW
+ *
+ * \param[in] DWord Next double word to write to the currently selected pipe's FIFO buffer.
+ */
+ static inline void Pipe_Write_DWord_LE(const uint32_t DWord) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_Write_DWord_LE(const uint32_t DWord)
+ {
+ UPDATX = (DWord & 0xFF);
+ UPDATX = (DWord >> 8);
+ UPDATX = (DWord >> 16);
+ UPDATX = (DWord >> 24);
+ }
+
+ /** Writes four bytes to the currently selected pipe's bank in big endian format, for IN
+ * direction pipes.
+ *
+ * \ingroup Group_PipePrimitiveRW
+ *
+ * \param[in] DWord Next double word to write to the currently selected pipe's FIFO buffer.
+ */
+ static inline void Pipe_Write_DWord_BE(const uint32_t DWord) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_Write_DWord_BE(const uint32_t DWord)
+ {
+ UPDATX = (DWord >> 24);
+ UPDATX = (DWord >> 16);
+ UPDATX = (DWord >> 8);
+ UPDATX = (DWord & 0xFF);
+ }
+
+ /** Discards four bytes from the currently selected pipe's bank, for OUT direction pipes.
+ *
+ * \ingroup Group_PipePrimitiveRW
+ */
+ static inline void Pipe_Discard_DWord(void) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_Discard_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.
+ *
+ * A newly configured pipe is frozen by default, and must be unfrozen before use via the \ref Pipe_Unfreeze()
+ * before being used. Pipes should be kept frozen unless waiting for data from a device while in IN mode, or
+ * sending data to the device in OUT mode. IN type pipes are also automatically configured to accept infinite
+ * numbers of IN requests without automatic freezing - this can be overridden by a call to
+ * \ref Pipe_SetFiniteINRequests().
+ *
+ * \param[in] Number Pipe number to configure. This must be more than 0 and less than \ref PIPE_TOTAL_PIPES.
+ *
+ * \param[in] Type Type of pipe to configure, a EP_TYPE_* mask. Not all pipe types are available on Low
+ * Speed USB devices - refer to the USB 2.0 specification.
+ *
+ * \param[in] Token Pipe data token, either \ref PIPE_TOKEN_SETUP, \ref PIPE_TOKEN_OUT or \ref PIPE_TOKEN_IN.
+ * All pipes (except Control type) are unidirectional - data may only be read from or
+ * written to the pipe bank based on its direction, not both.
+ *
+ * \param[in] EndpointNumber Endpoint index within the attached device that the pipe should interface to.
+ *
+ * \param[in] Size Size of the pipe's bank, where packets are stored before they are transmitted to
+ * the USB device, or after they have been received from the USB device (depending on
+ * the pipe's data direction). The bank size must indicate the maximum packet size that
+ * the pipe can handle.
+ *
+ * \param[in] Banks Number of banks to use for the pipe being configured, a PIPE_BANK_* mask. More banks
+ * uses more USB DPRAM, but offers better performance. Isochronous type pipes <b>must</b>
+ * have at least two banks.
+ *
+ * \note Endpoints <b>must</b> be configured in ascending order, or bank corruption will occur.
+ * \n\n
+ *
+ * \note Certain models of USB AVR's pipes may have different maximum packet sizes based on the pipe's
+ * index - refer to the chosen USB AVR's datasheet to determine the maximum bank size for each pipe.
+ * \n\n
+ *
+ * \note The default control pipe should not be manually configured by the user application, as it is
+ * automatically configured by the library internally.
+ * \n\n
+ *
+ * \note This routine will automatically select the specified pipe upon success. Upon failure, the pipe which
+ * failed to reconfigure correctly will be selected.
+ *
+ * \return Boolean true if the configuration succeeded, 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);
+
+ /** Spin-loops until the currently selected non-control pipe is ready for the next packed of data to be read
+ * or written to it, aborting in the case of an error condition (such as a timeout or device disconnect).
+ *
+ * \ingroup Group_PipeRW
+ *
+ * \return A value from the \ref Pipe_WaitUntilReady_ErrorCodes_t enum.
+ */
+ uint8_t Pipe_WaitUntilReady(void);
+
+ /** Determines if a pipe has been bound to the given device endpoint address. If a pipe which is bound to the given
+ * endpoint is found, it is automatically selected.
+ *
+ * \param[in] EndpointAddress Address and direction mask of the endpoint within the attached device to check.
+ *
+ * \return Boolean true if a pipe bound to the given endpoint address of the specified direction is found, false
+ * otherwise.
+ */
+ bool Pipe_IsEndpointBound(const uint8_t EndpointAddress);
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #if !defined(ENDPOINT_CONTROLEP)
+ #define ENDPOINT_CONTROLEP 0
+ #endif
+
+ /* Inline Functions: */
+ static inline uint8_t Pipe_BytesToEPSizeMask(const uint16_t Bytes) ATTR_WARN_UNUSED_RESULT ATTR_CONST ATTR_ALWAYS_INLINE;
+ static inline uint8_t Pipe_BytesToEPSizeMask(const uint16_t Bytes)
+ {
+ uint8_t MaskVal = 0;
+ uint16_t CheckBytes = 8;
+
+ while ((CheckBytes < Bytes) && (CheckBytes < PIPE_MAX_SIZE))
+ {
+ MaskVal++;
+ CheckBytes <<= 1;
+ }
+
+ return (MaskVal << EPSIZE0);
+ }
+
+ /* Function Prototypes: */
+ void Pipe_ClearPipes(void);
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/LUFA/Drivers/USB/LowLevel/USBController.c b/LUFA/Drivers/USB/LowLevel/USBController.c
new file mode 100644
index 0000000..b7f6bc7
--- /dev/null
+++ b/LUFA/Drivers/USB/LowLevel/USBController.c
@@ -0,0 +1,232 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2010.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, 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.
+*/
+
+#define __INCLUDE_FROM_USB_DRIVER
+#define __INCLUDE_FROM_USB_CONTROLLER_C
+#include "USBController.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
+ )
+{
+ #if !defined(USE_STATIC_OPTIONS)
+ USB_Options = Options;
+ #endif
+
+ if (!(USB_Options & USB_OPT_REG_DISABLED))
+ USB_REG_On();
+ else
+ USB_REG_Off();
+
+ #if defined(USB_CAN_BE_BOTH)
+ if (Mode == USB_MODE_UID)
+ {
+ UHWCON |= (1 << UIDE);
+ USB_INT_Enable(USB_INT_IDTI);
+ USB_CurrentMode = USB_GetUSBModeFromUID();
+ }
+ else
+ {
+ USB_CurrentMode = Mode;
+ }
+ #endif
+
+ USB_IsInitialized = true;
+
+ USB_ResetInterface();
+}
+
+void USB_ShutDown(void)
+{
+ USB_INT_DisableAllInterrupts();
+ USB_INT_ClearAllInterrupts();
+
+ USB_Detach();
+ USB_Controller_Disable();
+
+ if (!(USB_Options & USB_OPT_MANUAL_PLL))
+ USB_PLL_Off();
+
+ USB_REG_Off();
+
+ #if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR)
+ USB_OTGPAD_Off();
+ #endif
+
+ #if defined(USB_CAN_BE_BOTH)
+ USB_CurrentMode = USB_MODE_None;
+ #endif
+
+ USB_IsInitialized = false;
+}
+
+void USB_ResetInterface(void)
+{
+ #if defined(USB_CAN_BE_BOTH)
+ bool UIDModeSelectEnabled = ((UHWCON & (1 << UIDE)) != 0);
+ #endif
+
+ USB_INT_DisableAllInterrupts();
+ USB_INT_ClearAllInterrupts();
+
+ USB_Controller_Reset();
+
+ if (!(USB_Options & USB_OPT_MANUAL_PLL))
+ {
+ #if defined(USB_SERIES_4_AVR)
+ PLLFRQ = ((1 << PLLUSB) | (1 << PDIV3) | (1 << PDIV1));
+ #endif
+
+ USB_PLL_On();
+ while (!(USB_PLL_IsReady()));
+ }
+
+ #if defined(USB_CAN_BE_BOTH)
+ if (UIDModeSelectEnabled)
+ {
+ UHWCON |= (1 << UIDE);
+ USB_INT_Enable(USB_INT_IDTI);
+ }
+ #endif
+
+ USB_CLK_Unfreeze();
+
+ if (USB_CurrentMode == USB_MODE_Device)
+ {
+ #if defined(USB_CAN_BE_DEVICE)
+ #if (defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR))
+ UHWCON |= (1 << UIMOD);
+ #endif
+
+ USB_Init_Device();
+ #endif
+ }
+ else if (USB_CurrentMode == USB_MODE_Host)
+ {
+ #if defined(USB_CAN_BE_HOST)
+ UHWCON &= ~(1 << UIMOD);
+ USB_Init_Host();
+ #endif
+ }
+
+ #if (defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR))
+ USB_OTGPAD_On();
+ #endif
+}
+
+#if defined(USB_CAN_BE_DEVICE)
+static void USB_Init_Device(void)
+{
+ USB_DeviceState = DEVICE_STATE_Unattached;
+ USB_ConfigurationNumber = 0;
+
+ #if !defined(NO_DEVICE_REMOTE_WAKEUP)
+ USB_RemoteWakeupEnabled = false;
+ #endif
+
+ #if !defined(NO_DEVICE_SELF_POWER)
+ USB_CurrentlySelfPowered = false;
+ #endif
+
+ #if !defined(FIXED_CONTROL_ENDPOINT_SIZE)
+ USB_Descriptor_Device_t* DeviceDescriptorPtr;
+
+ if (CALLBACK_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
+
+ #if (defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR))
+ if (USB_Options & USB_DEVICE_OPT_LOWSPEED)
+ USB_Device_SetLowSpeed();
+ else
+ USB_Device_SetFullSpeed();
+
+ USB_INT_Enable(USB_INT_VBUS);
+ #endif
+
+ Endpoint_ConfigureEndpoint(ENDPOINT_CONTROLEP, EP_TYPE_CONTROL,
+ ENDPOINT_DIR_OUT, USB_ControlEndpointSize,
+ ENDPOINT_BANK_SINGLE);
+
+ USB_INT_Clear(USB_INT_SUSPI);
+ USB_INT_Enable(USB_INT_SUSPI);
+ USB_INT_Enable(USB_INT_EORSTI);
+
+ USB_Attach();
+}
+#endif
+
+#if defined(USB_CAN_BE_HOST)
+static void USB_Init_Host(void)
+{
+ USB_HostState = HOST_STATE_Unattached;
+ USB_ControlPipeSize = PIPE_CONTROLPIPE_DEFAULT_SIZE;
+
+ USB_Host_HostMode_On();
+
+ USB_Host_VBUS_Auto_Off();
+ USB_Host_VBUS_Manual_Enable();
+ USB_Host_VBUS_Manual_On();
+
+ USB_INT_Enable(USB_INT_SRPI);
+ USB_INT_Enable(USB_INT_BCERRI);
+
+ USB_Attach();
+}
+#endif
+
diff --git a/LUFA/Drivers/USB/LowLevel/USBController.h b/LUFA/Drivers/USB/LowLevel/USBController.h
new file mode 100644
index 0000000..3ac73aa
--- /dev/null
+++ b/LUFA/Drivers/USB/LowLevel/USBController.h
@@ -0,0 +1,471 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2010.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, 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
+ * \brief USB low level USB controller definitions.
+ *
+ * This file contains structures, function prototypes and macros related to the low level configuration of the
+ * USB controller, to start, stop and reset the USB library core.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB driver
+ * dispatch header located in LUFA/Drivers/USB/USB.h.
+ */
+
+/** \ingroup Group_USB
+ * @defgroup Group_USBManagement USB Interface Management
+ *
+ * Functions, macros, variables, enums and types related to the setup and management of the USB interface.
+ *
+ * @{
+ */
+
+#ifndef __USBCONTROLLER_H__
+#define __USBCONTROLLER_H__
+
+ /* Includes: */
+ #include <avr/io.h>
+ #include <avr/interrupt.h>
+ #include <stdbool.h>
+
+ #include "../HighLevel/USBMode.h"
+
+ #include "../../../Common/Common.h"
+ #include "../HighLevel/USBMode.h"
+ #include "../HighLevel/Events.h"
+ #include "../HighLevel/USBTask.h"
+ #include "USBInterrupt.h"
+
+ #if defined(USB_CAN_BE_HOST) || defined(__DOXYGEN__)
+ #include "Host.h"
+ #include "OTG.h"
+ #include "Pipe.h"
+ #include "../HighLevel/HostStandardReq.h"
+ #include "../HighLevel/PipeStream.h"
+ #endif
+
+ #if defined(USB_CAN_BE_DEVICE) || defined(__DOXYGEN__)
+ #include "Device.h"
+ #include "Endpoint.h"
+ #include "../HighLevel/DeviceStandardReq.h"
+ #include "../HighLevel/EndpointStream.h"
+ #endif
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks and Defines: */
+ #if !defined(__INCLUDE_FROM_USB_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
+ #endif
+
+ #if !defined(F_CLOCK)
+ #error F_CLOCK is not defined. You must define F_CLOCK to the frequency of the unprescaled input clock in your project makefile.
+ #endif
+
+ #if (F_CLOCK == 8000000)
+ #if (defined(__AVR_AT90USB82__) || defined(__AVR_AT90USB162__) || \
+ defined(__AVR_ATmega8U2__) || defined(__AVR_ATmega16U2__) || \
+ defined(__AVR_ATmega32U2__))
+ #define USB_PLL_PSC 0
+ #elif (defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__))
+ #define USB_PLL_PSC 0
+ #elif (defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) || defined(__AVR_ATmega32U6__))
+ #define USB_PLL_PSC ((1 << PLLP1) | (1 << PLLP0))
+ #elif (defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1287__))
+ #define USB_PLL_PSC ((1 << PLLP1) | (1 << PLLP0))
+ #endif
+ #elif (F_CLOCK == 16000000)
+ #if (defined(__AVR_AT90USB82__) || defined(__AVR_AT90USB162__) || \
+ defined(__AVR_ATmega8U2__) || defined(__AVR_ATmega16U2__) || \
+ defined(__AVR_ATmega32U2__))
+ #define USB_PLL_PSC (1 << PLLP0)
+ #elif (defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__))
+ #define USB_PLL_PSC (1 << PINDIV)
+ #elif (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))
+ #endif
+ #endif
+
+ #if !defined(USB_PLL_PSC)
+ #error No PLL prescale value available for chosen F_CLOCK value and AVR model.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** \name USB Controller Option Masks */
+ //@{
+ /** Regulator disable option mask for \ref 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 \ref 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 \ref 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 \ref 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)
+ //@}
+
+ /** \name Endpoint/Pipe Type Masks */
+ //@{
+ /** Mask for a CONTROL type endpoint or pipe.
+ *
+ * \note See \ref Group_EndpointManagement and \ref Group_PipeManagement for endpoint/pipe functions.
+ */
+ #define EP_TYPE_CONTROL 0x00
+
+ /** Mask for an ISOCHRONOUS type endpoint or pipe.
+ *
+ * \note See \ref Group_EndpointManagement and \ref Group_PipeManagement for endpoint/pipe functions.
+ */
+ #define EP_TYPE_ISOCHRONOUS 0x01
+
+ /** Mask for a BULK type endpoint or pipe.
+ *
+ * \note See \ref Group_EndpointManagement and \ref Group_PipeManagement for endpoint/pipe functions.
+ */
+ #define EP_TYPE_BULK 0x02
+
+ /** Mask for an INTERRUPT type endpoint or pipe.
+ *
+ * \note See \ref Group_EndpointManagement and \ref Group_PipeManagement for endpoint/pipe functions.
+ */
+ #define EP_TYPE_INTERRUPT 0x03
+ //@}
+
+ #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 acknowledged within this time period, the stream function will fail.
+ *
+ * This value may be overridden in the user project makefile as the value of the
+ * \ref USB_STREAM_TIMEOUT_MS token, and passed to the compiler using the -D switch.
+ */
+ #define USB_STREAM_TIMEOUT_MS 100
+ #endif
+
+ /* Inline Functions: */
+ #if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR) || defined(__DOXYGEN__)
+ /** Returns boolean true if the VBUS line is currently high (i.e. the USB host is supplying power),
+ * otherwise returns false.
+ *
+ * \note This function is not available on some AVR models which do not support hardware VBUS monitoring.
+ */
+ static inline bool USB_VBUS_GetStatus(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool USB_VBUS_GetStatus(void)
+ {
+ return ((USBSTA & (1 << VBUS)) ? true : false);
+ }
+ #endif
+
+ /** Detaches the device from the USB bus. This has the effect of removing the device from any
+ * attached host, ceasing USB communications. If no host is present, this prevents any host from
+ * enumerating the device once attached until \ref USB_Attach() is called.
+ */
+ static inline void USB_Detach(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Detach(void)
+ {
+ UDCON |= (1 << DETACH);
+ }
+
+ /** 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.
+ */
+ static inline void USB_Attach(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Attach(void)
+ {
+ UDCON &= ~(1 << DETACH);
+ }
+
+ /* 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 interrupts for the device and host mode enumeration processes,
+ * the user must enable global interrupts before or shortly after this function is called. In
+ * device mode, interrupts must be enabled within 500ms of this function being called to ensure
+ * that the host does not time out whilst enumerating the device. In host mode, interrupts may be
+ * enabled at the application's leisure however enumeration will not begin of an attached device
+ * until after this has occurred.
+ *
+ * Calling this function when the USB interface is already initialized will cause a complete USB
+ * interface reset and re-enumeration.
+ *
+ * \param[in] Mode This is a mask indicating what mode the USB interface is to be initialized to, a value
+ * from the \ref USB_Modes_t enum.
+ *
+ * \param[in] 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,
+ * the mode can be statically set in the project makefile by defining the token USB_DEVICE_ONLY
+ * (for device mode) or USB_HOST_ONLY (for host mode), 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.
+ * \n\n
+ *
+ * \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.
+ * \n\n
+ *
+ * \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 \ref 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);
+
+ /* Global Variables: */
+ #if (!defined(USB_HOST_ONLY) && !defined(USB_DEVICE_ONLY)) || defined(__DOXYGEN__)
+ /** Indicates the mode that the USB interface is currently initialized to, a value from the
+ * \ref USB_Modes_t enum.
+ *
+ * \note This variable should be treated as read-only in the user application, and never manually
+ * changed in value.
+ * \n\n
+ *
+ * \note When the controller is initialized into UID autodetection mode, this variable will hold the
+ * currently selected USB mode (i.e. \ref USB_MODE_Device or \ref USB_MODE_Host). If the controller
+ * is fixed into a specific mode (either through the USB_DEVICE_ONLY or USB_HOST_ONLY compile time
+ * options, or a limitation of the USB controller in the chosen device model) this will evaluate to
+ * a constant of the appropriate value and will never evaluate to \ref USB_MODE_None even when the
+ * USB interface is not initialized.
+ */
+ extern volatile uint8_t USB_CurrentMode;
+ #elif defined(USB_HOST_ONLY)
+ #define USB_CurrentMode USB_MODE_Host
+ #elif defined(USB_DEVICE_ONLY)
+ #define USB_CurrentMode USB_MODE_Device
+ #endif
+
+ #if !defined(USE_STATIC_OPTIONS) || defined(__DOXYGEN__)
+ /** Indicates the current USB options that the USB interface was initialized with when \ref 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.
+ */
+ extern volatile uint8_t USB_Options;
+ #elif defined(USE_STATIC_OPTIONS)
+ #define USB_Options USE_STATIC_OPTIONS
+ #endif
+
+ /* Enums: */
+ /** Enum for the possible USB controller modes, for initialization via \ref USB_Init() and indication back to the
+ * user application via \ref USB_CurrentMode.
+ */
+ enum USB_Modes_t
+ {
+ USB_MODE_None = 0, /**< Indicates that the controller is currently not initialized in any specific USB mode. */
+ USB_MODE_Device = 1, /**< Indicates that the controller is currently initialized in USB Device mode. */
+ USB_MODE_Host = 2, /**< Indicates that the controller is currently initialized in USB Host mode. */
+ USB_MODE_UID = 3, /**< Indicates that the controller should determine the USB mode from the UID pin of the
+ * USB connector.
+ */
+ };
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Function Prototypes: */
+ #if defined(__INCLUDE_FROM_USB_CONTROLLER_C)
+ #if defined(USB_CAN_BE_DEVICE)
+ static void USB_Init_Device(void);
+ #endif
+
+ #if defined(USB_CAN_BE_HOST)
+ static void USB_Init_Host(void);
+ #endif
+ #endif
+
+ /* Inline Functions: */
+ static inline void USB_PLL_On(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_PLL_On(void)
+ {
+ PLLCSR = USB_PLL_PSC;
+ PLLCSR |= (1 << PLLE);
+ }
+
+ static inline void USB_PLL_Off(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_PLL_Off(void)
+ {
+ PLLCSR = 0;
+ }
+
+ static inline bool USB_PLL_IsReady(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool USB_PLL_IsReady(void)
+ {
+ return ((PLLCSR & (1 << PLOCK)) ? true : false);
+ }
+
+ static inline void USB_REG_On(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_REG_On(void)
+ {
+ #if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR)
+ UHWCON |= (1 << UVREGE);
+ #else
+ REGCR &= ~(1 << REGDIS);
+ #endif
+ }
+
+ static inline void USB_REG_Off(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_REG_Off(void)
+ {
+ #if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR)
+ UHWCON &= ~(1 << UVREGE);
+ #else
+ REGCR |= (1 << REGDIS);
+ #endif
+ }
+
+ #if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR)
+ static inline void USB_OTGPAD_On(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_OTGPAD_On(void)
+ {
+ USBCON |= (1 << OTGPADE);
+ }
+
+ static inline void USB_OTGPAD_Off(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_OTGPAD_Off(void)
+ {
+ USBCON &= ~(1 << OTGPADE);
+ }
+ #endif
+
+ static inline void USB_CLK_Freeze(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_CLK_Freeze(void)
+ {
+ USBCON |= (1 << FRZCLK);
+ }
+
+ static inline void USB_CLK_Unfreeze(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_CLK_Unfreeze(void)
+ {
+ USBCON &= ~(1 << FRZCLK);
+ }
+
+ static inline void USB_Controller_Enable(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Controller_Enable(void)
+ {
+ USBCON |= (1 << USBE);
+ }
+
+ static inline void USB_Controller_Disable(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Controller_Disable(void)
+ {
+ USBCON &= ~(1 << USBE);
+ }
+
+ static inline void USB_Controller_Reset(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Controller_Reset(void)
+ {
+ const uint8_t Temp = USBCON;
+
+ USBCON = (Temp & ~(1 << USBE));
+ USBCON = (Temp | (1 << USBE));
+ }
+
+ #if defined(USB_CAN_BE_BOTH)
+ static inline uint8_t USB_GetUSBModeFromUID(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint8_t USB_GetUSBModeFromUID(void)
+ {
+ if (USBSTA & (1 << ID))
+ return USB_MODE_Device;
+ else
+ return USB_MODE_Host;
+ }
+ #endif
+
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/LUFA/Drivers/USB/LowLevel/USBInterrupt.c b/LUFA/Drivers/USB/LowLevel/USBInterrupt.c
new file mode 100644
index 0000000..c3e87e3
--- /dev/null
+++ b/LUFA/Drivers/USB/LowLevel/USBInterrupt.c
@@ -0,0 +1,269 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2010.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, 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.
+*/
+
+#define __INCLUDE_FROM_USB_DRIVER
+#include "USBInterrupt.h"
+
+void USB_INT_DisableAllInterrupts(void)
+{
+ #if defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR)
+ USBCON &= ~((1 << VBUSTE) | (1 << IDTE));
+ #elif defined(USB_SERIES_4_AVR)
+ USBCON &= ~(1 << VBUSTE);
+ #endif
+
+ #if defined(USB_CAN_BE_BOTH)
+ OTGIEN = 0;
+ #endif
+
+ #if defined(USB_CAN_BE_HOST)
+ UHIEN = 0;
+ #endif
+
+ #if defined(USB_CAN_BE_DEVICE)
+ UDIEN = 0;
+ #endif
+}
+
+void USB_INT_ClearAllInterrupts(void)
+{
+ #if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR)
+ USBINT = 0;
+ #endif
+
+ #if defined(USB_CAN_BE_BOTH)
+ OTGINT = 0;
+ #endif
+
+ #if defined(USB_CAN_BE_HOST)
+ UHINT = 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_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR)
+ if (USB_INT_HasOccurred(USB_INT_VBUS) && USB_INT_IsEnabled(USB_INT_VBUS))
+ {
+ USB_INT_Clear(USB_INT_VBUS);
+
+ if (USB_VBUS_GetStatus())
+ {
+ USB_DeviceState = DEVICE_STATE_Powered;
+ EVENT_USB_Device_Connect();
+ }
+ else
+ {
+ USB_DeviceState = DEVICE_STATE_Unattached;
+ EVENT_USB_Device_Disconnect();
+ }
+ }
+ #endif
+
+ if (USB_INT_HasOccurred(USB_INT_SUSPI) && USB_INT_IsEnabled(USB_INT_SUSPI))
+ {
+ USB_INT_Clear(USB_INT_SUSPI);
+
+ USB_INT_Disable(USB_INT_SUSPI);
+ USB_INT_Enable(USB_INT_WAKEUPI);
+
+ USB_CLK_Freeze();
+
+ if (!(USB_Options & USB_OPT_MANUAL_PLL))
+ USB_PLL_Off();
+
+ #if defined(USB_SERIES_2_AVR) && !defined(NO_LIMITED_CONTROLLER_CONNECT)
+ USB_DeviceState = DEVICE_STATE_Unattached;
+ EVENT_USB_Device_Disconnect();
+ #else
+ USB_DeviceState = DEVICE_STATE_Suspended;
+ EVENT_USB_Device_Suspend();
+ #endif
+ }
+
+ if (USB_INT_HasOccurred(USB_INT_WAKEUPI) && USB_INT_IsEnabled(USB_INT_WAKEUPI))
+ {
+ if (!(USB_Options & USB_OPT_MANUAL_PLL))
+ {
+ USB_PLL_On();
+ while (!(USB_PLL_IsReady()));
+ }
+
+ USB_CLK_Unfreeze();
+
+ USB_INT_Clear(USB_INT_WAKEUPI);
+
+ USB_INT_Disable(USB_INT_WAKEUPI);
+ USB_INT_Enable(USB_INT_SUSPI);
+
+ if (USB_ConfigurationNumber)
+ USB_DeviceState = DEVICE_STATE_Configured;
+ else
+ USB_DeviceState = (USB_Device_IsAddressSet()) ? DEVICE_STATE_Configured : DEVICE_STATE_Powered;
+
+ #if defined(USB_SERIES_2_AVR) && !defined(NO_LIMITED_CONTROLLER_CONNECT)
+ EVENT_USB_Device_Connect();
+ #else
+ EVENT_USB_Device_WakeUp();
+ #endif
+ }
+
+ if (USB_INT_HasOccurred(USB_INT_EORSTI) && USB_INT_IsEnabled(USB_INT_EORSTI))
+ {
+ USB_INT_Clear(USB_INT_EORSTI);
+
+ USB_DeviceState = DEVICE_STATE_Default;
+ USB_ConfigurationNumber = 0;
+
+ USB_INT_Clear(USB_INT_SUSPI);
+ USB_INT_Disable(USB_INT_SUSPI);
+ USB_INT_Enable(USB_INT_WAKEUPI);
+
+ Endpoint_ConfigureEndpoint(ENDPOINT_CONTROLEP, EP_TYPE_CONTROL,
+ ENDPOINT_DIR_OUT, USB_ControlEndpointSize,
+ ENDPOINT_BANK_SINGLE);
+
+ #if defined(INTERRUPT_CONTROL_ENDPOINT)
+ USB_INT_Enable(USB_INT_RXSTPI);
+ #endif
+
+ EVENT_USB_Device_Reset();
+ }
+
+ #if !defined(NO_SOF_EVENTS)
+ if (USB_INT_HasOccurred(USB_INT_SOFI) && USB_INT_IsEnabled(USB_INT_SOFI))
+ {
+ USB_INT_Clear(USB_INT_SOFI);
+
+ EVENT_USB_Device_StartOfFrame();
+ }
+ #endif
+ #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);
+
+ EVENT_USB_Host_DeviceUnattached();
+
+ 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();
+
+ EVENT_USB_Host_HostError(HOST_ERROR_VBusVoltageDip);
+ EVENT_USB_Host_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);
+
+ EVENT_USB_Host_DeviceAttached();
+
+ USB_INT_Enable(USB_INT_DDISCI);
+
+ USB_HostState = HOST_STATE_Powered;
+ }
+
+ if (USB_INT_HasOccurred(USB_INT_BCERRI) && USB_INT_IsEnabled(USB_INT_BCERRI))
+ {
+ USB_INT_Clear(USB_INT_BCERRI);
+
+ EVENT_USB_Host_DeviceEnumerationFailed(HOST_ENUMERROR_NoDeviceDetected, 0);
+ EVENT_USB_Host_DeviceUnattached();
+
+ USB_ResetInterface();
+ }
+
+ #if !defined(NO_SOF_EVENTS)
+ if (USB_INT_HasOccurred(USB_INT_HSOFI) && USB_INT_IsEnabled(USB_INT_HSOFI))
+ {
+ USB_INT_Clear(USB_INT_HSOFI);
+
+ EVENT_USB_Host_StartOfFrame();
+ }
+ #endif
+ #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_DeviceState != DEVICE_STATE_Unattached)
+ EVENT_USB_Device_Disconnect();
+
+ if (USB_HostState != HOST_STATE_Unattached)
+ EVENT_USB_Host_DeviceUnattached();
+
+ USB_CurrentMode = USB_GetUSBModeFromUID();
+ USB_ResetInterface();
+
+ EVENT_USB_UIDChange();
+ }
+ #endif
+}
+
+#if defined(INTERRUPT_CONTROL_ENDPOINT) && defined(USB_CAN_BE_DEVICE)
+ISR(USB_COM_vect, ISR_BLOCK)
+{
+ uint8_t PrevSelectedEndpoint = Endpoint_GetCurrentEndpoint();
+
+ Endpoint_SelectEndpoint(ENDPOINT_CONTROLEP);
+ USB_INT_Disable(USB_INT_RXSTPI);
+
+ NONATOMIC_BLOCK(NONATOMIC_FORCEOFF)
+ {
+ USB_Device_ProcessControlRequest();
+ }
+
+ Endpoint_SelectEndpoint(ENDPOINT_CONTROLEP);
+ USB_INT_Enable(USB_INT_RXSTPI);
+ Endpoint_SelectEndpoint(PrevSelectedEndpoint);
+}
+#endif
+
diff --git a/LUFA/Drivers/USB/LowLevel/USBInterrupt.h b/LUFA/Drivers/USB/LowLevel/USBInterrupt.h
new file mode 100644
index 0000000..5d0c991
--- /dev/null
+++ b/LUFA/Drivers/USB/LowLevel/USBInterrupt.h
@@ -0,0 +1,106 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2010.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, 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
+ * \brief USB controller interrupt service routine management.
+ *
+ * This file contains definitions required for the correct handling of low level USB service routine interrupts
+ * from the USB controller.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB driver
+ * dispatch header located in LUFA/Drivers/USB/USB.h.
+ */
+
+#ifndef __USBINTERRUPT_H__
+#define __USBINTERRUPT_H__
+
+ /* Includes: */
+ #include <avr/io.h>
+ #include <avr/interrupt.h>
+ #include <util/atomic.h>
+ #include <stdbool.h>
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_USB_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define USB_INT_Enable(int) MACROS{ USB_INT_GET_EN_REG(int) |= USB_INT_GET_EN_MASK(int); }MACROE
+ #define USB_INT_Disable(int) MACROS{ USB_INT_GET_EN_REG(int) &= ~(USB_INT_GET_EN_MASK(int)); }MACROE
+ #define USB_INT_Clear(int) MACROS{ USB_INT_GET_INT_REG(int) &= ~(USB_INT_GET_INT_MASK(int)); }MACROE
+ #define USB_INT_IsEnabled(int) ((USB_INT_GET_EN_REG(int) & USB_INT_GET_EN_MASK(int)) ? true : false)
+ #define USB_INT_HasOccurred(int) ((USB_INT_GET_INT_REG(int) & USB_INT_GET_INT_MASK(int)) ? true : false)
+
+ #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_WAKEUPI UDIEN , (1 << WAKEUPE), UDINT , (1 << WAKEUPI)
+ #define USB_INT_SUSPI 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)
+ #define USB_INT_RXSTPI UEIENX, (1 << RXSTPE) , UEINTX, (1 << RXSTPI)
+
+ /* Includes: */
+ #include "../../../Common/Common.h"
+ #include "../HighLevel/USBMode.h"
+ #include "../HighLevel/Events.h"
+ #include "USBController.h"
+
+ /* Function Prototypes: */
+ void USB_INT_ClearAllInterrupts(void);
+ void USB_INT_DisableAllInterrupts(void);
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+