1
0
Fork 0

Squashed 'lib/lufa/' content from commit 385d40300

git-subtree-dir: lib/lufa
git-subtree-split: 385d4030035dbaf41591309dbde47653bd03841b
This commit is contained in:
Jack Humbert 2017-07-07 11:55:23 -04:00
commit 60b30c0363
1455 changed files with 394541 additions and 0 deletions

View file

@ -0,0 +1,51 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
#include "../../../../Common/Common.h"
#if (ARCH == ARCH_UC3)
#define __INCLUDE_FROM_USB_DRIVER
#include "../USBMode.h"
#if defined(USB_CAN_BE_DEVICE)
#include "../Device.h"
void USB_Device_SendRemoteWakeup(void)
{
USB_CLK_Unfreeze();
AVR32_USBB.UDCON.rmwkup = true;
while (AVR32_USBB.UDCON.rmwkup);
}
#endif
#endif

View file

@ -0,0 +1,267 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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 definitions for the AVR32 UC3 microcontrollers.
* \copydetails Group_Device_UC3
*
* \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_Device
* \defgroup Group_Device_UC3 Device Management (UC3)
* \brief USB Device definitions for the AVR32 UC3 microcontrollers.
*
* Architecture specific USB Device definitions for the Atmel 32-bit UC3 AVR microcontrollers.
*
* @{
*/
#ifndef __USBDEVICE_UC3_H__
#define __USBDEVICE_UC3_H__
/* Includes: */
#include "../../../../Common/Common.h"
#include "../USBController.h"
#include "../StdDescriptors.h"
#include "../USBInterrupt.h"
#include "../Endpoint.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 USB Device Mode Option Masks */
//@{
/** 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 Restrictions apply on the number, size and type of endpoints which can be used
* when running in low speed mode - please refer to the USB 2.0 specification.
*/
#define USB_DEVICE_OPT_LOWSPEED (1 << 0)
/** 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)
#if defined(USB_SERIES_UC3A3_AVR32) || defined(USB_SERIES_UC3A4_AVR32) || defined(__DOXYGEN__)
/** Mask for the Options parameter of the \ref USB_Init() function. This indicates that the
* USB interface should be initialized in high speed (480Mb/s) mode.
*/
#define USB_DEVICE_OPT_HIGHSPEED (1 << 1)
#endif
//@}
#if (!defined(NO_INTERNAL_SERIAL) && \
(defined(USB_SERIES_UC3A3_AVR32) || defined(USB_SERIES_UC3A4_AVR32) || \
defined(__DOXYGEN__)))
/** String descriptor index for the device's unique serial number string descriptor within the device.
* This unique serial number is used by the host to associate resources to the device (such as drivers or COM port
* number allocations) to a device regardless of the port it is plugged in to on the host. Some microcontrollers contain
* a unique serial number internally, and setting the device descriptors serial number string index to this value
* will cause it to use the internal serial number.
*
* On unsupported devices, this will evaluate to \ref NO_DESCRIPTOR and so will force the host to create a pseudo-serial
* number for the device.
*/
#define USE_INTERNAL_SERIAL 0xDC
/** Length of the device's unique internal serial number, in bits, if present on the selected microcontroller
* model.
*/
#define INTERNAL_SERIAL_LENGTH_BITS 120
/** Start address of the internal serial number, in the appropriate address space, if present on the selected microcontroller
* model.
*/
#define INTERNAL_SERIAL_START_ADDRESS 0x80800204
#else
#define USE_INTERNAL_SERIAL NO_DESCRIPTOR
#define INTERNAL_SERIAL_LENGTH_BITS 0
#define INTERNAL_SERIAL_START_ADDRESS 0
#endif
/* 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 function 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_Device_RemoteWakeupEnabled flag is set). When the \c NO_DEVICE_REMOTE_WAKEUP
* compile time option is used, this function is unavailable.
*
* \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_StdDescriptors for more information on the RMWAKEUP feature and device descriptors.
*/
void USB_Device_SendRemoteWakeup(void);
/* 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.
*
* \return Current USB frame number from the USB controller.
*/
static inline uint16_t USB_Device_GetFrameNumber(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
static inline uint16_t USB_Device_GetFrameNumber(void)
{
return AVR32_USBB.UDFNUM.fnum;
}
#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 \c 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 \c 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
/* Private Interface - For use in library only: */
#if !defined(__DOXYGEN__)
/* Inline Functions: */
static inline void USB_Device_SetLowSpeed(void) ATTR_ALWAYS_INLINE;
static inline void USB_Device_SetLowSpeed(void)
{
AVR32_USBB.UDCON.ls = true;
}
static inline void USB_Device_SetFullSpeed(void) ATTR_ALWAYS_INLINE;
static inline void USB_Device_SetFullSpeed(void)
{
AVR32_USBB.UDCON.ls = false;
#if defined(USB_DEVICE_OPT_HIGHSPEED)
AVR32_USBB.UDCON.spdconf = 3;
#endif
}
#if defined(USB_DEVICE_OPT_HIGHSPEED)
static inline void USB_Device_SetHighSpeed(void) ATTR_ALWAYS_INLINE;
static inline void USB_Device_SetHighSpeed(void)
{
AVR32_USBB.UDCON.ls = false;
AVR32_USBB.UDCON.spdconf = 0;
}
#endif
static inline void USB_Device_SetDeviceAddress(const uint8_t Address) ATTR_ALWAYS_INLINE;
static inline void USB_Device_SetDeviceAddress(const uint8_t Address)
{
AVR32_USBB.UDCON.uadd = Address;
}
static inline void USB_Device_EnableDeviceAddress(const uint8_t Address) ATTR_ALWAYS_INLINE;
static inline void USB_Device_EnableDeviceAddress(const uint8_t Address)
{
(void)Address;
AVR32_USBB.UDCON.adden = true;
}
static inline bool USB_Device_IsAddressSet(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
static inline bool USB_Device_IsAddressSet(void)
{
return AVR32_USBB.UDCON.adden;
}
#if (USE_INTERNAL_SERIAL != NO_DESCRIPTOR)
static inline void USB_Device_GetSerialString(uint16_t* const UnicodeString) ATTR_NON_NULL_PTR_ARG(1);
static inline void USB_Device_GetSerialString(uint16_t* const UnicodeString)
{
uint_reg_t CurrentGlobalInt = GetGlobalInterruptMask();
GlobalInterruptDisable();
uint8_t* SigReadAddress = (uint8_t*)INTERNAL_SERIAL_START_ADDRESS;
for (uint8_t SerialCharNum = 0; SerialCharNum < (INTERNAL_SERIAL_LENGTH_BITS / 4); SerialCharNum++)
{
uint8_t SerialByte = *SigReadAddress;
if (SerialCharNum & 0x01)
{
SerialByte >>= 4;
SigReadAddress++;
}
SerialByte &= 0x0F;
UnicodeString[SerialCharNum] = cpu_to_le16((SerialByte >= 10) ?
(('A' - 10) + SerialByte) : ('0' + SerialByte));
}
SetGlobalInterruptMask(CurrentGlobalInt);
}
#endif
#endif
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,235 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
#include "../../../../Common/Common.h"
#if (ARCH == ARCH_UC3)
#define __INCLUDE_FROM_USB_DRIVER
#include "../USBMode.h"
#if defined(USB_CAN_BE_DEVICE)
#include "EndpointStream_UC3.h"
#if !defined(CONTROL_ONLY_DEVICE)
uint8_t Endpoint_Discard_Stream(uint16_t Length,
uint16_t* const BytesProcessed)
{
uint8_t ErrorCode;
uint16_t BytesInTransfer = 0;
if ((ErrorCode = Endpoint_WaitUntilReady()))
return ErrorCode;
if (BytesProcessed != NULL)
Length -= *BytesProcessed;
while (Length)
{
if (!(Endpoint_IsReadWriteAllowed()))
{
Endpoint_ClearOUT();
if (BytesProcessed != NULL)
{
*BytesProcessed += BytesInTransfer;
return ENDPOINT_RWSTREAM_IncompleteTransfer;
}
if ((ErrorCode = Endpoint_WaitUntilReady()))
return ErrorCode;
}
else
{
Endpoint_Discard_8();
Length--;
BytesInTransfer++;
}
}
return ENDPOINT_RWSTREAM_NoError;
}
uint8_t Endpoint_Null_Stream(uint16_t Length,
uint16_t* const BytesProcessed)
{
uint8_t ErrorCode;
uint16_t BytesInTransfer = 0;
if ((ErrorCode = Endpoint_WaitUntilReady()))
return ErrorCode;
if (BytesProcessed != NULL)
Length -= *BytesProcessed;
while (Length)
{
if (!(Endpoint_IsReadWriteAllowed()))
{
Endpoint_ClearIN();
if (BytesProcessed != NULL)
{
*BytesProcessed += BytesInTransfer;
return ENDPOINT_RWSTREAM_IncompleteTransfer;
}
if ((ErrorCode = Endpoint_WaitUntilReady()))
return ErrorCode;
}
else
{
Endpoint_Write_8(0);
Length--;
BytesInTransfer++;
}
}
return ENDPOINT_RWSTREAM_NoError;
}
/* The following abuses the C preprocessor in order to copy-paste common code with slight alterations,
* so that the code needs to be written once. It is a crude form of templating to reduce code maintenance. */
#define TEMPLATE_FUNC_NAME Endpoint_Write_Stream_LE
#define TEMPLATE_BUFFER_TYPE const void*
#define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearIN()
#define TEMPLATE_BUFFER_OFFSET(Length) 0
#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr += Amount
#define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_8(*BufferPtr)
#include "Template/Template_Endpoint_RW.c"
#define TEMPLATE_FUNC_NAME Endpoint_Write_Stream_BE
#define TEMPLATE_BUFFER_TYPE const void*
#define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearIN()
#define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1)
#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr -= Amount
#define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_8(*BufferPtr)
#include "Template/Template_Endpoint_RW.c"
#define TEMPLATE_FUNC_NAME Endpoint_Read_Stream_LE
#define TEMPLATE_BUFFER_TYPE void*
#define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearOUT()
#define TEMPLATE_BUFFER_OFFSET(Length) 0
#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr += Amount
#define TEMPLATE_TRANSFER_BYTE(BufferPtr) *BufferPtr = Endpoint_Read_8()
#include "Template/Template_Endpoint_RW.c"
#define TEMPLATE_FUNC_NAME Endpoint_Read_Stream_BE
#define TEMPLATE_BUFFER_TYPE void*
#define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearOUT()
#define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1)
#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr -= Amount
#define TEMPLATE_TRANSFER_BYTE(BufferPtr) *BufferPtr = Endpoint_Read_8()
#include "Template/Template_Endpoint_RW.c"
#if defined(ARCH_HAS_FLASH_ADDRESS_SPACE)
#define TEMPLATE_FUNC_NAME Endpoint_Write_PStream_LE
#define TEMPLATE_BUFFER_TYPE const void*
#define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearIN()
#define TEMPLATE_BUFFER_OFFSET(Length) 0
#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr += Amount
#define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_8(pgm_read_byte(BufferPtr))
#include "Template/Template_Endpoint_RW.c"
#define TEMPLATE_FUNC_NAME Endpoint_Write_PStream_BE
#define TEMPLATE_BUFFER_TYPE const void*
#define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearIN()
#define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1)
#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr -= Amount
#define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_8(pgm_read_byte(BufferPtr))
#include "Template/Template_Endpoint_RW.c"
#endif
#if defined(ARCH_HAS_EEPROM_ADDRESS_SPACE)
#define TEMPLATE_FUNC_NAME Endpoint_Write_EStream_LE
#define TEMPLATE_BUFFER_TYPE const void*
#define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearIN()
#define TEMPLATE_BUFFER_OFFSET(Length) 0
#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr += Amount
#define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_8(eeprom_read_byte(BufferPtr))
#include "Template/Template_Endpoint_RW.c"
#define TEMPLATE_FUNC_NAME Endpoint_Write_EStream_BE
#define TEMPLATE_BUFFER_TYPE const void*
#define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearIN()
#define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1)
#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr -= Amount
#define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_8(eeprom_read_byte(BufferPtr))
#include "Template/Template_Endpoint_RW.c"
#define TEMPLATE_FUNC_NAME Endpoint_Read_EStream_LE
#define TEMPLATE_BUFFER_TYPE void*
#define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearOUT()
#define TEMPLATE_BUFFER_OFFSET(Length) 0
#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr += Amount
#define TEMPLATE_TRANSFER_BYTE(BufferPtr) eeprom_update_byte(BufferPtr, Endpoint_Read_8())
#include "Template/Template_Endpoint_RW.c"
#define TEMPLATE_FUNC_NAME Endpoint_Read_EStream_BE
#define TEMPLATE_BUFFER_TYPE void*
#define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearOUT()
#define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1)
#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr -= Amount
#define TEMPLATE_TRANSFER_BYTE(BufferPtr) eeprom_update_byte(BufferPtr, Endpoint_Read_8())
#include "Template/Template_Endpoint_RW.c"
#endif
#endif
#define TEMPLATE_FUNC_NAME Endpoint_Write_Control_Stream_LE
#define TEMPLATE_BUFFER_OFFSET(Length) 0
#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr += Amount
#define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_8(*BufferPtr)
#include "Template/Template_Endpoint_Control_W.c"
#define TEMPLATE_FUNC_NAME Endpoint_Write_Control_Stream_BE
#define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1)
#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr -= Amount
#define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_8(*BufferPtr)
#include "Template/Template_Endpoint_Control_W.c"
#define TEMPLATE_FUNC_NAME Endpoint_Read_Control_Stream_LE
#define TEMPLATE_BUFFER_OFFSET(Length) 0
#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr += Amount
#define TEMPLATE_TRANSFER_BYTE(BufferPtr) *BufferPtr = Endpoint_Read_8()
#include "Template/Template_Endpoint_Control_R.c"
#define TEMPLATE_FUNC_NAME Endpoint_Read_Control_Stream_BE
#define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1)
#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr -= Amount
#define TEMPLATE_TRANSFER_BYTE(BufferPtr) *BufferPtr = Endpoint_Read_8()
#include "Template/Template_Endpoint_Control_R.c"
#endif
#endif

View file

@ -0,0 +1,438 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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 Endpoint data stream transmission and reception management for the AVR32 UC3 microcontrollers.
* \copydetails Group_EndpointStreamRW_UC3
*
* \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_EndpointStreamRW
* \defgroup Group_EndpointStreamRW_UC3 Read/Write of Multi-Byte Streams (UC3)
* \brief Endpoint data stream transmission and reception management for the Atmel AVR32 UC3 architecture.
*
* Functions, macros, variables, enums and types related to data reading and writing of data streams from
* and to endpoints.
*
* @{
*/
#ifndef __ENDPOINT_STREAM_UC3_H__
#define __ENDPOINT_STREAM_UC3_H__
/* Includes: */
#include "../../../../Common/Common.h"
#include "../USBMode.h"
#include "../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: */
/* Function Prototypes: */
/** \name Stream functions for null data */
//@{
/** Reads and discards the given number of bytes from the currently selected endpoint's bank,
* discarding fully read packets from the host as needed. The last packet is not automatically
* discarded once the remaining bytes has been read; the user is responsible for manually
* discarding the last packet from the host via the \ref Endpoint_ClearOUT() macro.
*
* If the BytesProcessed parameter is \c NULL, the entire stream transfer is attempted at once,
* failing or succeeding as a single unit. If the BytesProcessed parameter points to a valid
* storage location, the transfer will instead be performed as a series of chunks. Each time
* the endpoint bank becomes empty while there is still data to process (and after the current
* packet has been acknowledged) the BytesProcessed location will be updated with the total number
* of bytes processed in the stream, and the function will exit with an error code of
* \ref ENDPOINT_RWSTREAM_IncompleteTransfer. This allows for any abort checking to be performed
* in the user code - to continue the transfer, call the function again with identical parameters
* and it will resume until the BytesProcessed value reaches the total transfer length.
*
* <b>Single Stream Transfer Example:</b>
* \code
* uint8_t ErrorCode;
*
* if ((ErrorCode = Endpoint_Discard_Stream(512, NULL)) != ENDPOINT_RWSTREAM_NoError)
* {
* // Stream failed to complete - check ErrorCode here
* }
* \endcode
*
* <b>Partial Stream Transfers Example:</b>
* \code
* uint8_t ErrorCode;
* uint16_t BytesProcessed;
*
* BytesProcessed = 0;
* while ((ErrorCode = Endpoint_Discard_Stream(512, &BytesProcessed)) == ENDPOINT_RWSTREAM_IncompleteTransfer)
* {
* // Stream not yet complete - do other actions here, abort if required
* }
*
* if (ErrorCode != ENDPOINT_RWSTREAM_NoError)
* {
* // Stream failed to complete - check ErrorCode here
* }
* \endcode
*
* \note This routine should not be used on CONTROL type endpoints.
*
* \param[in] Length Number of bytes to discard via the currently selected endpoint.
* \param[in] BytesProcessed Pointer to a location where the total number of bytes processed in the current
* transaction should be updated, \c NULL if the entire stream should be read at once.
*
* \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
*/
uint8_t Endpoint_Discard_Stream(uint16_t Length,
uint16_t* const BytesProcessed);
/** Writes a given number of zeroed bytes to the currently selected endpoint's bank, sending
* full packets to the host as needed. The last packet is not automatically sent once the
* remaining bytes have been written; the user is responsible for manually sending the last
* packet to the host via the \ref Endpoint_ClearIN() macro.
*
* If the BytesProcessed parameter is \c NULL, the entire stream transfer is attempted at once,
* failing or succeeding as a single unit. If the BytesProcessed parameter points to a valid
* storage location, the transfer will instead be performed as a series of chunks. Each time
* the endpoint bank becomes full while there is still data to process (and after the current
* packet transmission has been initiated) the BytesProcessed location will be updated with the
* total number of bytes processed in the stream, and the function will exit with an error code of
* \ref ENDPOINT_RWSTREAM_IncompleteTransfer. This allows for any abort checking to be performed
* in the user code - to continue the transfer, call the function again with identical parameters
* and it will resume until the BytesProcessed value reaches the total transfer length.
*
* <b>Single Stream Transfer Example:</b>
* \code
* uint8_t ErrorCode;
*
* if ((ErrorCode = Endpoint_Null_Stream(512, NULL)) != ENDPOINT_RWSTREAM_NoError)
* {
* // Stream failed to complete - check ErrorCode here
* }
* \endcode
*
* <b>Partial Stream Transfers Example:</b>
* \code
* uint8_t ErrorCode;
* uint16_t BytesProcessed;
*
* BytesProcessed = 0;
* while ((ErrorCode = Endpoint_Null_Stream(512, &BytesProcessed)) == ENDPOINT_RWSTREAM_IncompleteTransfer)
* {
* // Stream not yet complete - do other actions here, abort if required
* }
*
* if (ErrorCode != ENDPOINT_RWSTREAM_NoError)
* {
* // Stream failed to complete - check ErrorCode here
* }
* \endcode
*
* \note This routine should not be used on CONTROL type endpoints.
*
* \param[in] Length Number of zero bytes to send via the currently selected endpoint.
* \param[in] BytesProcessed Pointer to a location where the total number of bytes processed in the current
* transaction should be updated, \c NULL if the entire stream should be read at once.
*
* \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
*/
uint8_t Endpoint_Null_Stream(uint16_t Length,
uint16_t* const BytesProcessed);
//@}
/** \name Stream functions for RAM source/destination data */
//@{
/** Writes the given number of bytes to the endpoint from the given buffer in little endian,
* sending full packets to the host as needed. The last packet filled is not automatically sent;
* the user is responsible for manually sending the last written packet to the host via the
* \ref Endpoint_ClearIN() macro.
*
* If the BytesProcessed parameter is \c NULL, the entire stream transfer is attempted at once,
* failing or succeeding as a single unit. If the BytesProcessed parameter points to a valid
* storage location, the transfer will instead be performed as a series of chunks. Each time
* the endpoint bank becomes full while there is still data to process (and after the current
* packet transmission has been initiated) the BytesProcessed location will be updated with the
* total number of bytes processed in the stream, and the function will exit with an error code of
* \ref ENDPOINT_RWSTREAM_IncompleteTransfer. This allows for any abort checking to be performed
* in the user code - to continue the transfer, call the function again with identical parameters
* and it will resume until the BytesProcessed value reaches the total transfer length.
*
* <b>Single Stream Transfer Example:</b>
* \code
* uint8_t DataStream[512];
* uint8_t ErrorCode;
*
* if ((ErrorCode = Endpoint_Write_Stream_LE(DataStream, sizeof(DataStream),
* NULL)) != ENDPOINT_RWSTREAM_NoError)
* {
* // Stream failed to complete - check ErrorCode here
* }
* \endcode
*
* <b>Partial Stream Transfers Example:</b>
* \code
* uint8_t DataStream[512];
* uint8_t ErrorCode;
* uint16_t BytesProcessed;
*
* BytesProcessed = 0;
* while ((ErrorCode = Endpoint_Write_Stream_LE(DataStream, sizeof(DataStream),
* &BytesProcessed)) == ENDPOINT_RWSTREAM_IncompleteTransfer)
* {
* // Stream not yet complete - do other actions here, abort if required
* }
*
* if (ErrorCode != ENDPOINT_RWSTREAM_NoError)
* {
* // Stream failed to complete - check ErrorCode here
* }
* \endcode
*
* \note This routine should not be used on CONTROL type endpoints.
*
* \param[in] Buffer Pointer to the source data buffer to read from.
* \param[in] Length Number of bytes to read for the currently selected endpoint into the buffer.
* \param[in] BytesProcessed Pointer to a location where the total number of bytes processed in the current
* transaction should be updated, \c NULL if the entire stream should be written at once.
*
* \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
*/
uint8_t Endpoint_Write_Stream_LE(const void* const Buffer,
uint16_t Length,
uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
/** Writes the given number of bytes to the endpoint from the given buffer in big endian,
* sending full packets to the host as needed. The last packet filled is not automatically sent;
* the user is responsible for manually sending the last written packet to the host via the
* \ref Endpoint_ClearIN() macro.
*
* \note This routine should not be used on CONTROL type endpoints.
*
* \param[in] Buffer Pointer to the source data buffer to read from.
* \param[in] Length Number of bytes to read for the currently selected endpoint into the buffer.
* \param[in] BytesProcessed Pointer to a location where the total number of bytes processed in the current
* transaction should be updated, \c NULL if the entire stream should be written at once.
*
* \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
*/
uint8_t Endpoint_Write_Stream_BE(const void* const Buffer,
uint16_t Length,
uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
/** Reads the given number of bytes from the endpoint from the given buffer in little endian,
* discarding fully read packets from the host as needed. The last packet is not automatically
* discarded once the remaining bytes has been read; the user is responsible for manually
* discarding the last packet from the host via the \ref Endpoint_ClearOUT() macro.
*
* If the BytesProcessed parameter is \c NULL, the entire stream transfer is attempted at once,
* failing or succeeding as a single unit. If the BytesProcessed parameter points to a valid
* storage location, the transfer will instead be performed as a series of chunks. Each time
* the endpoint bank becomes empty while there is still data to process (and after the current
* packet has been acknowledged) the BytesProcessed location will be updated with the total number
* of bytes processed in the stream, and the function will exit with an error code of
* \ref ENDPOINT_RWSTREAM_IncompleteTransfer. This allows for any abort checking to be performed
* in the user code - to continue the transfer, call the function again with identical parameters
* and it will resume until the BytesProcessed value reaches the total transfer length.
*
* <b>Single Stream Transfer Example:</b>
* \code
* uint8_t DataStream[512];
* uint8_t ErrorCode;
*
* if ((ErrorCode = Endpoint_Read_Stream_LE(DataStream, sizeof(DataStream),
* NULL)) != ENDPOINT_RWSTREAM_NoError)
* {
* // Stream failed to complete - check ErrorCode here
* }
* \endcode
*
* <b>Partial Stream Transfers Example:</b>
* \code
* uint8_t DataStream[512];
* uint8_t ErrorCode;
* uint16_t BytesProcessed;
*
* BytesProcessed = 0;
* while ((ErrorCode = Endpoint_Read_Stream_LE(DataStream, sizeof(DataStream),
* &BytesProcessed)) == ENDPOINT_RWSTREAM_IncompleteTransfer)
* {
* // Stream not yet complete - do other actions here, abort if required
* }
*
* if (ErrorCode != ENDPOINT_RWSTREAM_NoError)
* {
* // Stream failed to complete - check ErrorCode here
* }
* \endcode
*
* \note This routine should not be used on CONTROL type endpoints.
*
* \param[out] Buffer Pointer to the destination data buffer to write to.
* \param[in] Length Number of bytes to send via the currently selected endpoint.
* \param[in] BytesProcessed Pointer to a location where the total number of bytes processed in the current
* transaction should be updated, \c NULL if the entire stream should be read at once.
*
* \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
*/
uint8_t Endpoint_Read_Stream_LE(void* const Buffer,
uint16_t Length,
uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
/** Reads the given number of bytes from the endpoint from the given buffer in big endian,
* discarding fully read packets from the host as needed. The last packet is not automatically
* discarded once the remaining bytes has been read; the user is responsible for manually
* discarding the last packet from the host via the \ref Endpoint_ClearOUT() macro.
*
* \note This routine should not be used on CONTROL type endpoints.
*
* \param[out] Buffer Pointer to the destination data buffer to write to.
* \param[in] Length Number of bytes to send via the currently selected endpoint.
* \param[in] BytesProcessed Pointer to a location where the total number of bytes processed in the current
* transaction should be updated, \c NULL if the entire stream should be read at once.
*
* \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
*/
uint8_t Endpoint_Read_Stream_BE(void* const Buffer,
uint16_t Length,
uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
/** Writes the given number of bytes to the CONTROL type endpoint from the given buffer in little endian,
* sending full packets to the host as needed. The host OUT acknowledgement is not automatically cleared
* in both failure and success states; the user is responsible for manually clearing the status OUT packet
* to finalize the transfer's status stage via the \ref Endpoint_ClearOUT() macro.
*
* \note This function automatically sends the last packet in the data stage of the transaction; when the
* function returns, the user is responsible for clearing the <b>status</b> stage of the transaction.
* Note that the status stage packet is sent or received in the opposite direction of the data flow.
* \n\n
*
* \note This routine should only be used on CONTROL type endpoints.
*
* \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained
* together; i.e. the entire stream data must be read or written at the one time.
*
* \param[in] Buffer Pointer to the source data buffer to read from.
* \param[in] Length Number of bytes to read for the currently selected endpoint into the buffer.
*
* \return A value from the \ref Endpoint_ControlStream_RW_ErrorCodes_t enum.
*/
uint8_t Endpoint_Write_Control_Stream_LE(const void* const Buffer,
uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
/** Writes the given number of bytes to the CONTROL type endpoint from the given buffer in big endian,
* sending full packets to the host as needed. The host OUT acknowledgement is not automatically cleared
* in both failure and success states; the user is responsible for manually clearing the status OUT packet
* to finalize the transfer's status stage via the \ref Endpoint_ClearOUT() macro.
*
* \note This function automatically sends the last packet in the data stage of the transaction; when the
* function returns, the user is responsible for clearing the <b>status</b> stage of the transaction.
* Note that the status stage packet is sent or received in the opposite direction of the data flow.
* \n\n
*
* \note This routine should only be used on CONTROL type endpoints.
*
* \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained
* together; i.e. the entire stream data must be read or written at the one time.
*
* \param[in] Buffer Pointer to the source data buffer to read from.
* \param[in] Length Number of bytes to read for the currently selected endpoint into the buffer.
*
* \return A value from the \ref Endpoint_ControlStream_RW_ErrorCodes_t enum.
*/
uint8_t Endpoint_Write_Control_Stream_BE(const void* const Buffer,
uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
/** Reads the given number of bytes from the CONTROL endpoint from the given buffer in little endian,
* discarding fully read packets from the host as needed. The device IN acknowledgement is not
* automatically sent after success or failure states; the user is responsible for manually sending the
* status IN packet to finalize the transfer's status stage via the \ref Endpoint_ClearIN() macro.
*
* \note This function automatically sends the last packet in the data stage of the transaction; when the
* function returns, the user is responsible for clearing the <b>status</b> stage of the transaction.
* Note that the status stage packet is sent or received in the opposite direction of the data flow.
* \n\n
*
* \note This routine should only be used on CONTROL type endpoints.
*
* \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained
* together; i.e. the entire stream data must be read or written at the one time.
*
* \param[out] Buffer Pointer to the destination data buffer to write to.
* \param[in] Length Number of bytes to send via the currently selected endpoint.
*
* \return A value from the \ref Endpoint_ControlStream_RW_ErrorCodes_t enum.
*/
uint8_t Endpoint_Read_Control_Stream_LE(void* const Buffer,
uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
/** Reads the given number of bytes from the CONTROL endpoint from the given buffer in big endian,
* discarding fully read packets from the host as needed. The device IN acknowledgement is not
* automatically sent after success or failure states; the user is responsible for manually sending the
* status IN packet to finalize the transfer's status stage via the \ref Endpoint_ClearIN() macro.
*
* \note This function automatically sends the last packet in the data stage of the transaction; when the
* function returns, the user is responsible for clearing the <b>status</b> stage of the transaction.
* Note that the status stage packet is sent or received in the opposite direction of the data flow.
* \n\n
*
* \note This routine should only be used on CONTROL type endpoints.
*
* \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained
* together; i.e. the entire stream data must be read or written at the one time.
*
* \param[out] Buffer Pointer to the destination data buffer to write to.
* \param[in] Length Number of bytes to send via the currently selected endpoint.
*
* \return A value from the \ref Endpoint_ControlStream_RW_ErrorCodes_t enum.
*/
uint8_t Endpoint_Read_Control_Stream_BE(void* const Buffer,
uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
//@}
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,196 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
#include "../../../../Common/Common.h"
#if (ARCH == ARCH_UC3)
#define __INCLUDE_FROM_USB_DRIVER
#include "../USBMode.h"
#if defined(USB_CAN_BE_DEVICE)
#include "../Endpoint.h"
#if !defined(FIXED_CONTROL_ENDPOINT_SIZE)
uint8_t USB_Device_ControlEndpointSize = ENDPOINT_CONTROLEP_DEFAULT_SIZE;
#endif
volatile uint32_t USB_Endpoint_SelectedEndpoint = ENDPOINT_CONTROLEP;
volatile uint8_t* USB_Endpoint_FIFOPos[ENDPOINT_TOTAL_ENDPOINTS];
bool Endpoint_ConfigureEndpointTable(const USB_Endpoint_Table_t* const Table,
const uint8_t Entries)
{
for (uint8_t i = 0; i < Entries; i++)
{
if (!(Table[i].Address))
continue;
if (!(Endpoint_ConfigureEndpoint(Table[i].Address, Table[i].Type, Table[i].Size, Table[i].Banks)))
{
return false;
}
}
return true;
}
bool Endpoint_ConfigureEndpoint_Prv(const uint8_t Number,
const uint32_t UECFG0Data)
{
USB_Endpoint_FIFOPos[Number] = &AVR32_USBB_SLAVE[Number * ENDPOINT_HSB_ADDRESS_SPACE_SIZE];
#if defined(CONTROL_ONLY_DEVICE) || defined(ORDERED_EP_CONFIG)
Endpoint_SelectEndpoint(Number);
Endpoint_EnableEndpoint();
(&AVR32_USBB.uecfg0)[Number] = 0;
(&AVR32_USBB.uecfg0)[Number] = UECFG0Data;
return Endpoint_IsConfigured();
#else
for (uint8_t EPNum = Number; EPNum < ENDPOINT_TOTAL_ENDPOINTS; EPNum++)
{
uint32_t UECFG0Temp;
Endpoint_SelectEndpoint(EPNum);
if (EPNum == Number)
{
UECFG0Temp = UECFG0Data;
}
else
{
UECFG0Temp = (&AVR32_USBB.uecfg0)[EPNum];
}
if (!(UECFG0Temp & AVR32_USBB_ALLOC_MASK))
continue;
Endpoint_DisableEndpoint();
(&AVR32_USBB.uecfg0)[EPNum] &= ~AVR32_USBB_ALLOC_MASK;
Endpoint_EnableEndpoint();
(&AVR32_USBB.uecfg0)[EPNum] = UECFG0Temp;
if (!(Endpoint_IsConfigured()))
return false;
}
Endpoint_SelectEndpoint(Number);
return true;
#endif
}
void Endpoint_ClearEndpoints(void)
{
for (uint8_t EPNum = 0; EPNum < ENDPOINT_TOTAL_ENDPOINTS; EPNum++)
{
Endpoint_SelectEndpoint(EPNum);
(&AVR32_USBB.uecfg0)[EPNum] = 0;
(&AVR32_USBB.uecon0clr)[EPNum] = -1;
USB_Endpoint_FIFOPos[EPNum] = &AVR32_USBB_SLAVE[EPNum * 0x10000];
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
#endif

View file

@ -0,0 +1,794 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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 Endpoint definitions for the AVR32 UC3 microcontrollers.
* \copydetails Group_EndpointManagement_UC3
*
* \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_EndpointRW
* \defgroup Group_EndpointRW_UC3 Endpoint Data Reading and Writing (UC3)
* \brief Endpoint data read/write definitions for the Atmel AVR32 UC3 architecture.
*
* Functions, macros, variables, enums and types related to data reading and writing from and to endpoints.
*/
/** \ingroup Group_EndpointPrimitiveRW
* \defgroup Group_EndpointPrimitiveRW_UC3 Read/Write of Primitive Data Types (UC3)
* \brief Endpoint primitive read/write definitions for the Atmel AVR32 UC3 architecture.
*
* Functions, macros, variables, enums and types related to data reading and writing of primitive data types
* from and to endpoints.
*/
/** \ingroup Group_EndpointPacketManagement
* \defgroup Group_EndpointPacketManagement_UC3 Endpoint Packet Management (UC3)
* \brief Endpoint packet management definitions for the Atmel AVR32 UC3 architecture.
*
* Functions, macros, variables, enums and types related to packet management of endpoints.
*/
/** \ingroup Group_EndpointManagement
* \defgroup Group_EndpointManagement_UC3 Endpoint Management (UC3)
* \brief Endpoint management definitions for the Atmel AVR32 UC3 architecture.
*
* 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_UC3_H__
#define __ENDPOINT_UC3_H__
/* Includes: */
#include "../../../../Common/Common.h"
#include "../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_HSB_ADDRESS_SPACE_SIZE (64 * 1024UL)
/* Inline Functions: */
static inline uint32_t Endpoint_BytesToEPSizeMask(const uint16_t Bytes) ATTR_WARN_UNUSED_RESULT ATTR_CONST
ATTR_ALWAYS_INLINE;
static inline uint32_t Endpoint_BytesToEPSizeMask(const uint16_t Bytes)
{
uint8_t MaskVal = 0;
uint16_t CheckBytes = 8;
while (CheckBytes < Bytes)
{
MaskVal++;
CheckBytes <<= 1;
}
return (MaskVal << AVR32_USBB_EPSIZE_OFFSET);
}
/* Function Prototypes: */
void Endpoint_ClearEndpoints(void);
bool Endpoint_ConfigureEndpoint_Prv(const uint8_t Number,
const uint32_t UECFGXData);
/* External Variables: */
extern volatile uint32_t USB_Endpoint_SelectedEndpoint;
extern volatile uint8_t* USB_Endpoint_FIFOPos[];
#endif
/* Public Interface - May be used in end-application: */
/* Macros: */
#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 \c FIXED_CONTROL_ENDPOINT_SIZE token is defined.
*/
#define ENDPOINT_CONTROLEP_DEFAULT_SIZE 8
#endif
#if !defined(CONTROL_ONLY_DEVICE) || defined(__DOXYGEN__)
#if defined(USB_SERIES_UC3A3_AVR32) || defined(USB_SERIES_UC3A4_AVR32)
#define ENDPOINT_TOTAL_ENDPOINTS 8
#else
/** Total number of endpoints (including the default control endpoint at address 0) which may
* be used in the device. Different AVR models support different amounts of endpoints,
* this value reflects the maximum number of endpoints for the currently selected AVR model.
*/
#define ENDPOINT_TOTAL_ENDPOINTS 7
#endif
#else
#define ENDPOINT_TOTAL_ENDPOINTS 1
#endif
/* Enums: */
/** Enum for the possible error return codes of the \ref Endpoint_WaitUntilReady() function.
*
* \ingroup Group_EndpointRW_UC3
*/
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 address with the given endpoint type, bank size and number of hardware
* banks. Once configured, the endpoint may be read from or written to, depending on its direction.
*
* \param[in] Address Endpoint address to configure.
*
* \param[in] Type Type of endpoint to configure, a \c EP_TYPE_* mask. Not all endpoint types
* are available on Low Speed USB devices - refer to the USB 2.0 specification.
*
* \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 hardware banks to use for the endpoint being configured.
*
* \attention When the \c ORDERED_EP_CONFIG compile time option is used, Endpoints <b>must</b> be configured in
* ascending order, or bank corruption will occur.
*
* \note Different endpoints may have different maximum packet sizes based on the endpoint's index - refer to
* the chosen microcontroller model'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 \c true if the configuration succeeded, \c false otherwise.
*/
static inline bool Endpoint_ConfigureEndpoint(const uint8_t Address,
const uint8_t Type,
const uint16_t Size,
const uint8_t Banks) ATTR_ALWAYS_INLINE;
static inline bool Endpoint_ConfigureEndpoint(const uint8_t Address,
const uint8_t Type,
const uint16_t Size,
const uint8_t Banks)
{
uint8_t Number = (Address & ENDPOINT_EPNUM_MASK);
if (Number >= ENDPOINT_TOTAL_ENDPOINTS)
return false;
return Endpoint_ConfigureEndpoint_Prv(Number,
(AVR32_USBB_ALLOC_MASK |
((uint32_t)Type << AVR32_USBB_EPTYPE_OFFSET) |
((Address & ENDPOINT_DIR_IN) ? AVR32_USBB_UECFG0_EPDIR_MASK : 0) |
((Banks > 1) ? AVR32_USBB_UECFG0_EPBK_SINGLE : AVR32_USBB_UECFG0_EPBK_DOUBLE) |
Endpoint_BytesToEPSizeMask(Size)));
}
/** Indicates the number of bytes currently stored in the current endpoint's selected bank.
*
* \ingroup Group_EndpointRW_UC3
*
* \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)
{
return (&AVR32_USBB.UESTA0)[USB_Endpoint_SelectedEndpoint].byct;
}
/** Determines the currently selected endpoint's direction.
*
* \return The currently selected endpoint's direction, as a \c ENDPOINT_DIR_* mask.
*/
static inline uint32_t Endpoint_GetEndpointDirection(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline uint32_t Endpoint_GetEndpointDirection(void)
{
return ((&AVR32_USBB.UECFG0)[USB_Endpoint_SelectedEndpoint].epdir ? ENDPOINT_DIR_IN : ENDPOINT_DIR_OUT);
}
/** Get the endpoint address of the currently selected endpoint. This is typically used to save
* the currently selected endpoint 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)
{
return (USB_Endpoint_SelectedEndpoint | Endpoint_GetEndpointDirection());
}
/** Selects the given endpoint address.
*
* Any endpoint operations which do not require the endpoint address to be indicated will operate on
* the currently selected endpoint.
*
* \param[in] Address Endpoint address to select.
*/
static inline void Endpoint_SelectEndpoint(const uint8_t Address) ATTR_ALWAYS_INLINE;
static inline void Endpoint_SelectEndpoint(const uint8_t Address)
{
USB_Endpoint_SelectedEndpoint = (Address & ENDPOINT_EPNUM_MASK);
}
/** Resets the endpoint bank FIFO. This clears all the endpoint banks and resets the USB controller's
* data In and Out pointers to the bank's contents.
*
* \param[in] Address Endpoint number whose FIFO buffers are to be reset.
*/
static inline void Endpoint_ResetEndpoint(const uint8_t Address) ATTR_ALWAYS_INLINE;
static inline void Endpoint_ResetEndpoint(const uint8_t Address)
{
uint32_t EndpointNumber = (Address & ENDPOINT_EPNUM_MASK);
AVR32_USBB.uerst |= (AVR32_USBB_EPRST0_MASK << EndpointNumber);
AVR32_USBB.uerst &= ~(AVR32_USBB_EPRST0_MASK << EndpointNumber);
USB_Endpoint_FIFOPos[EndpointNumber] = &AVR32_USBB_SLAVE[EndpointNumber * ENDPOINT_HSB_ADDRESS_SPACE_SIZE];
}
/** 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)
{
AVR32_USBB.uerst |= (AVR32_USBB_EPEN0_MASK << USB_Endpoint_SelectedEndpoint);
}
/** 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)
{
AVR32_USBB.uerst &= ~(AVR32_USBB_EPEN0_MASK << USB_Endpoint_SelectedEndpoint);
}
/** Determines if the currently selected endpoint is enabled, but not necessarily configured.
*
* \return Boolean \c true if the currently selected endpoint is enabled, \c false otherwise.
*/
static inline bool Endpoint_IsEnabled(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool Endpoint_IsEnabled(void)
{
return ((AVR32_USBB.uerst & (AVR32_USBB_EPEN0_MASK << USB_Endpoint_SelectedEndpoint)) ? true : false);
}
/** 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_UC3
*
* \return Total number of busy banks in the selected endpoint.
*/
static inline uint8_t Endpoint_GetBusyBanks(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
static inline uint8_t Endpoint_GetBusyBanks(void)
{
return (&AVR32_USBB.UESTA0)[USB_Endpoint_SelectedEndpoint].nbusybk;
}
/** 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_UC3
*/
static inline void Endpoint_AbortPendingIN(void)
{
while (Endpoint_GetBusyBanks() != 0)
{
(&AVR32_USBB.UECON0SET)[USB_Endpoint_SelectedEndpoint].killbks = true;
while ((&AVR32_USBB.UECON0)[USB_Endpoint_SelectedEndpoint].killbk);
}
}
/** 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_UC3
*
* \return Boolean \c 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 (&AVR32_USBB.UESTA0)[USB_Endpoint_SelectedEndpoint].rwall;
}
/** Determines if the currently selected endpoint is configured.
*
* \return Boolean \c true if the currently selected endpoint has been configured, \c false otherwise.
*/
static inline bool Endpoint_IsConfigured(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool Endpoint_IsConfigured(void)
{
return (&AVR32_USBB.UESTA0)[USB_Endpoint_SelectedEndpoint].cfgok;
}
/** 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 <tt>(1 << <i>{Endpoint Number}</i>)</tt>.
*
* \return Mask whose bits indicate which endpoints have interrupted.
*/
static inline uint32_t Endpoint_GetEndpointInterrupts(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline uint32_t Endpoint_GetEndpointInterrupts(void)
{
return ((AVR32_USBB.udint & (AVR32_USBB_EP6INT_MASK | AVR32_USBB_EP5INT_MASK |
AVR32_USBB_EP4INT_MASK | AVR32_USBB_EP3INT_MASK |
AVR32_USBB_EP2INT_MASK | AVR32_USBB_EP1INT_MASK |
AVR32_USBB_EP0INT_MASK)) >> AVR32_USBB_EP0INT_OFFSET);
}
/** Determines if the specified endpoint number has interrupted (valid only for INTERRUPT type
* endpoints).
*
* \param[in] Address Address of the endpoint whose interrupt flag should be tested.
*
* \return Boolean \c true if the specified endpoint has interrupted, \c false otherwise.
*/
static inline bool Endpoint_HasEndpointInterrupted(const uint8_t Address) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool Endpoint_HasEndpointInterrupted(const uint8_t Address)
{
return ((Endpoint_GetEndpointInterrupts() & (AVR32_USBB_EP0INT_MASK << (Address & ENDPOINT_EPNUM_MASK))) ? true : false);
}
/** Determines if the selected IN endpoint is ready for a new packet to be sent to the host.
*
* \ingroup Group_EndpointPacketManagement_UC3
*
* \return Boolean \c true if the current endpoint is ready for an IN packet, \c false otherwise.
*/
static inline bool Endpoint_IsINReady(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool Endpoint_IsINReady(void)
{
return (&AVR32_USBB.UESTA0)[USB_Endpoint_SelectedEndpoint].txini;
}
/** Determines if the selected OUT endpoint has received new packet from the host.
*
* \ingroup Group_EndpointPacketManagement_UC3
*
* \return Boolean \c true if current endpoint is has received an OUT packet, \c false otherwise.
*/
static inline bool Endpoint_IsOUTReceived(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool Endpoint_IsOUTReceived(void)
{
return (&AVR32_USBB.UESTA0)[USB_Endpoint_SelectedEndpoint].rxouti;
}
/** Determines if the current CONTROL type endpoint has received a SETUP packet.
*
* \ingroup Group_EndpointPacketManagement_UC3
*
* \return Boolean \c true if the selected endpoint has received a SETUP packet, \c false otherwise.
*/
static inline bool Endpoint_IsSETUPReceived(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool Endpoint_IsSETUPReceived(void)
{
return (&AVR32_USBB.UESTA0)[USB_Endpoint_SelectedEndpoint].rxstpi;
}
/** Clears a received SETUP packet on the currently selected CONTROL type endpoint, freeing up the
* endpoint for the next packet.
*
* \ingroup Group_EndpointPacketManagement_UC3
*
* \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)
{
(&AVR32_USBB.UESTA0CLR)[USB_Endpoint_SelectedEndpoint].rxstpic = true;
USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint] = &AVR32_USBB_SLAVE[USB_Endpoint_SelectedEndpoint * ENDPOINT_HSB_ADDRESS_SPACE_SIZE];
}
/** 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_UC3
*/
static inline void Endpoint_ClearIN(void) ATTR_ALWAYS_INLINE;
static inline void Endpoint_ClearIN(void)
{
(&AVR32_USBB.UESTA0CLR)[USB_Endpoint_SelectedEndpoint].txinic = true;
(&AVR32_USBB.UECON0CLR)[USB_Endpoint_SelectedEndpoint].fifoconc = true;
USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint] = &AVR32_USBB_SLAVE[USB_Endpoint_SelectedEndpoint * ENDPOINT_HSB_ADDRESS_SPACE_SIZE];
}
/** 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_UC3
*/
static inline void Endpoint_ClearOUT(void) ATTR_ALWAYS_INLINE;
static inline void Endpoint_ClearOUT(void)
{
(&AVR32_USBB.UESTA0CLR)[USB_Endpoint_SelectedEndpoint].rxoutic = true;
(&AVR32_USBB.UECON0CLR)[USB_Endpoint_SelectedEndpoint].fifoconc = true;
USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint] = &AVR32_USBB_SLAVE[USB_Endpoint_SelectedEndpoint * ENDPOINT_HSB_ADDRESS_SPACE_SIZE];
}
/** 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_UC3
*/
static inline void Endpoint_StallTransaction(void) ATTR_ALWAYS_INLINE;
static inline void Endpoint_StallTransaction(void)
{
(&AVR32_USBB.UECON0SET)[USB_Endpoint_SelectedEndpoint].stallrqs = true;
}
/** Clears the STALL condition on the currently selected endpoint.
*
* \ingroup Group_EndpointPacketManagement_UC3
*/
static inline void Endpoint_ClearStall(void) ATTR_ALWAYS_INLINE;
static inline void Endpoint_ClearStall(void)
{
(&AVR32_USBB.UECON0CLR)[USB_Endpoint_SelectedEndpoint].stallrqc = true;
}
/** Determines if the currently selected endpoint is stalled, \c false otherwise.
*
* \ingroup Group_EndpointPacketManagement_UC3
*
* \return Boolean \c true if the currently selected endpoint is stalled, \c false otherwise.
*/
static inline bool Endpoint_IsStalled(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool Endpoint_IsStalled(void)
{
return (&AVR32_USBB.UECON0)[USB_Endpoint_SelectedEndpoint].stallrq;
}
/** Resets the data toggle of the currently selected endpoint. */
static inline void Endpoint_ResetDataToggle(void) ATTR_ALWAYS_INLINE;
static inline void Endpoint_ResetDataToggle(void)
{
(&AVR32_USBB.UECON0SET)[USB_Endpoint_SelectedEndpoint].rstdts = true;
}
/** Sets the direction of the currently selected endpoint.
*
* \param[in] DirectionMask New endpoint direction, as a \c ENDPOINT_DIR_* mask.
*/
static inline void Endpoint_SetEndpointDirection(const uint32_t DirectionMask) ATTR_ALWAYS_INLINE;
static inline void Endpoint_SetEndpointDirection(const uint32_t DirectionMask)
{
(&AVR32_USBB.UECFG0)[USB_Endpoint_SelectedEndpoint].epdir = (DirectionMask == ENDPOINT_DIR_IN);
}
/** Reads one byte from the currently selected endpoint's bank, for OUT direction endpoints.
*
* \ingroup Group_EndpointPrimitiveRW_UC3
*
* \return Next byte in the currently selected endpoint's FIFO buffer.
*/
static inline uint8_t Endpoint_Read_8(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline uint8_t Endpoint_Read_8(void)
{
return *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++);
}
/** Writes one byte to the currently selected endpoint's bank, for IN direction endpoints.
*
* \ingroup Group_EndpointPrimitiveRW_UC3
*
* \param[in] Data Data to write into the the currently selected endpoint's FIFO buffer.
*/
static inline void Endpoint_Write_8(const uint8_t Data) ATTR_ALWAYS_INLINE;
static inline void Endpoint_Write_8(const uint8_t Data)
{
*(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++) = Data;
}
/** Discards one byte from the currently selected endpoint's bank, for OUT direction endpoints.
*
* \ingroup Group_EndpointPrimitiveRW_UC3
*/
static inline void Endpoint_Discard_8(void) ATTR_ALWAYS_INLINE;
static inline void Endpoint_Discard_8(void)
{
uint8_t Dummy;
Dummy = *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++);
(void)Dummy;
}
/** Reads two bytes from the currently selected endpoint's bank in little endian format, for OUT
* direction endpoints.
*
* \ingroup Group_EndpointPrimitiveRW_UC3
*
* \return Next two bytes in the currently selected endpoint's FIFO buffer.
*/
static inline uint16_t Endpoint_Read_16_LE(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline uint16_t Endpoint_Read_16_LE(void)
{
uint16_t Byte0 = *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++);
uint16_t Byte1 = *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++);
return ((Byte1 << 8) | Byte0);
}
/** Reads two bytes from the currently selected endpoint's bank in big endian format, for OUT
* direction endpoints.
*
* \ingroup Group_EndpointPrimitiveRW_UC3
*
* \return Next two bytes in the currently selected endpoint's FIFO buffer.
*/
static inline uint16_t Endpoint_Read_16_BE(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline uint16_t Endpoint_Read_16_BE(void)
{
uint16_t Byte0 = *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++);
uint16_t Byte1 = *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++);
return ((Byte0 << 8) | Byte1);
}
/** Writes two bytes to the currently selected endpoint's bank in little endian format, for IN
* direction endpoints.
*
* \ingroup Group_EndpointPrimitiveRW_UC3
*
* \param[in] Data Data to write to the currently selected endpoint's FIFO buffer.
*/
static inline void Endpoint_Write_16_LE(const uint16_t Data) ATTR_ALWAYS_INLINE;
static inline void Endpoint_Write_16_LE(const uint16_t Data)
{
*(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++) = (Data & 0xFF);
*(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++) = (Data >> 8);
}
/** Writes two bytes to the currently selected endpoint's bank in big endian format, for IN
* direction endpoints.
*
* \ingroup Group_EndpointPrimitiveRW_UC3
*
* \param[in] Data Data to write to the currently selected endpoint's FIFO buffer.
*/
static inline void Endpoint_Write_16_BE(const uint16_t Data) ATTR_ALWAYS_INLINE;
static inline void Endpoint_Write_16_BE(const uint16_t Data)
{
*(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++) = (Data >> 8);
*(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++) = (Data & 0xFF);
}
/** Discards two bytes from the currently selected endpoint's bank, for OUT direction endpoints.
*
* \ingroup Group_EndpointPrimitiveRW_UC3
*/
static inline void Endpoint_Discard_16(void) ATTR_ALWAYS_INLINE;
static inline void Endpoint_Discard_16(void)
{
uint8_t Dummy;
Dummy = *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++);
Dummy = *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++);
(void)Dummy;
}
/** Reads four bytes from the currently selected endpoint's bank in little endian format, for OUT
* direction endpoints.
*
* \ingroup Group_EndpointPrimitiveRW_UC3
*
* \return Next four bytes in the currently selected endpoint's FIFO buffer.
*/
static inline uint32_t Endpoint_Read_32_LE(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline uint32_t Endpoint_Read_32_LE(void)
{
uint32_t Byte0 = *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++);
uint32_t Byte1 = *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++);
uint32_t Byte2 = *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++);
uint32_t Byte3 = *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++);
return ((Byte3 << 24) | (Byte2 << 16) | (Byte1 << 8) | Byte0);
}
/** Reads four bytes from the currently selected endpoint's bank in big endian format, for OUT
* direction endpoints.
*
* \ingroup Group_EndpointPrimitiveRW_UC3
*
* \return Next four bytes in the currently selected endpoint's FIFO buffer.
*/
static inline uint32_t Endpoint_Read_32_BE(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline uint32_t Endpoint_Read_32_BE(void)
{
uint32_t Byte0 = *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++);
uint32_t Byte1 = *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++);
uint32_t Byte2 = *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++);
uint32_t Byte3 = *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++);
return ((Byte0 << 24) | (Byte1 << 16) | (Byte2 << 8) | Byte3);
}
/** Writes four bytes to the currently selected endpoint's bank in little endian format, for IN
* direction endpoints.
*
* \ingroup Group_EndpointPrimitiveRW_UC3
*
* \param[in] Data Data to write to the currently selected endpoint's FIFO buffer.
*/
static inline void Endpoint_Write_32_LE(const uint32_t Data) ATTR_ALWAYS_INLINE;
static inline void Endpoint_Write_32_LE(const uint32_t Data)
{
*(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++) = (Data & 0xFF);
*(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++) = (Data >> 8);
*(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++) = (Data >> 16);
*(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++) = (Data >> 24);
}
/** Writes four bytes to the currently selected endpoint's bank in big endian format, for IN
* direction endpoints.
*
* \ingroup Group_EndpointPrimitiveRW_UC3
*
* \param[in] Data Data to write to the currently selected endpoint's FIFO buffer.
*/
static inline void Endpoint_Write_32_BE(const uint32_t Data) ATTR_ALWAYS_INLINE;
static inline void Endpoint_Write_32_BE(const uint32_t Data)
{
*(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++) = (Data >> 24);
*(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++) = (Data >> 16);
*(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++) = (Data >> 8);
*(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++) = (Data & 0xFF);
}
/** Discards four bytes from the currently selected endpoint's bank, for OUT direction endpoints.
*
* \ingroup Group_EndpointPrimitiveRW_UC3
*/
static inline void Endpoint_Discard_32(void) ATTR_ALWAYS_INLINE;
static inline void Endpoint_Discard_32(void)
{
uint8_t Dummy;
Dummy = *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++);
Dummy = *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++);
Dummy = *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++);
Dummy = *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++);
(void)Dummy;
}
/* 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 \c 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
* \c FIXED_CONTROL_ENDPOINT_SIZE token - it is recommended that the \c FIXED_CONTROL_ENDPOINT_SIZE token
* be used in the device descriptors to ensure this.
*
* \attention 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_Device_ControlEndpointSize;
#else
#define USB_Device_ControlEndpointSize FIXED_CONTROL_ENDPOINT_SIZE
#endif
/* Function Prototypes: */
/** Configures a table of endpoint descriptions, in sequence. This function can be used to configure multiple
* endpoints at the same time.
*
* \note Endpoints with a zero address will be ignored, thus this function cannot be used to configure the
* control endpoint.
*
* \param[in] Table Pointer to a table of endpoint descriptions.
* \param[in] Entries Number of entries in the endpoint table to configure.
*
* \return Boolean \c true if all endpoints configured successfully, \c false otherwise.
*/
bool Endpoint_ConfigureEndpointTable(const USB_Endpoint_Table_t* const Table,
const uint8_t Entries);
/** 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.
*
* \note This routine should not be called on non CONTROL type endpoints.
*/
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_UC3
*
* \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
/** @} */

View file

@ -0,0 +1,297 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
#include "../../../../Common/Common.h"
#if (ARCH == ARCH_UC3)
#define __INCLUDE_FROM_USB_DRIVER
#include "../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();
#if defined(NO_AUTO_VBUS_MANAGEMENT)
USB_Host_VBUS_Manual_Enable();
USB_Host_VBUS_Manual_On();
#endif
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:
if (!(Pipe_ConfigurePipe(PIPE_CONTROLPIPE, EP_TYPE_CONTROL, ENDPOINT_CONTROLEP, PIPE_CONTROLPIPE_DEFAULT_SIZE, 1)))
{
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];
Pipe_SelectPipe(PIPE_CONTROLPIPE);
if ((SubErrorCode = USB_Host_SendControlRequest(DataBuffer)) != HOST_SENDCONTROL_Successful)
{
ErrorCode = HOST_ENUMERROR_ControlError;
break;
}
USB_Host_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:
if (!(Pipe_ConfigurePipe(PIPE_CONTROLPIPE, EP_TYPE_CONTROL, ENDPOINT_CONTROLEP, USB_Host_ControlPipeSize, 1)))
{
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);
USB_HostState = HOST_STATE_Addressed;
EVENT_USB_Host_DeviceEnumerationComplete();
break;
default:
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())
{
Pipe_ClearError();
ErrorCode = HOST_WAITERROR_PipeError;
break;
}
if (Pipe_IsStalled())
{
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();
USB_Host_ConfigurationNumber = 0;
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);
}
#endif
#endif

View file

@ -0,0 +1,363 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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 definitions for the AVR32 UC3B microcontrollers.
* \copydetails Group_Host_UC3B
*
* \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_Host
* \defgroup Group_Host_UC3B Host Management (UC3B)
* \brief USB Host definitions for the AVR32 UC3B microcontrollers.
*
* Architecture specific USB Host definitions for the Atmel 32-bit AVR UC3B microcontrollers.
*
* @{
*/
#ifndef __USBHOST_UC3B_H__
#define __USBHOST_UC3B_H__
/* Includes: */
#include "../../../../Common/Common.h"
#include "../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(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 defining the
* \c HOST_DEVICE_SETTLE_DELAY_MS token to the 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 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.
*
* \return Current USB frame number from the USB controller.
*/
static inline uint16_t USB_Host_GetFrameNumber(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline uint16_t USB_Host_GetFrameNumber(void)
{
return AVR32_USBB_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 This function is not available when the \c 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 This function is not available when the \c 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)
{
AVR32_USBB.UHCON.reset = true;
}
/** Determines if a previously issued bus reset (via the \ref USB_Host_ResetBus() macro) has
* completed.
*
* \return Boolean \c true if no bus reset is currently being sent, \c false otherwise.
*/
static inline bool USB_Host_IsBusResetComplete(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool USB_Host_IsBusResetComplete(void)
{
return AVR32_USBB.UHCON.reset;
}
/** 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)
{
AVR32_USBB.UHCON.sofe = true;
}
/** 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.
*
* \note While the USB bus is suspended, all USB interrupt sources are also disabled; this means that
* some events (such as device disconnections) will not fire until the bus is resumed.
*/
static inline void USB_Host_SuspendBus(void) ATTR_ALWAYS_INLINE;
static inline void USB_Host_SuspendBus(void)
{
AVR32_USBB.UHCON.sofe = false;
}
/** 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 \c true if the bus is currently suspended, \c false otherwise.
*/
static inline bool USB_Host_IsBusSuspended(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool USB_Host_IsBusSuspended(void)
{
return AVR32_USBB.UHCON.sofe;
}
/** 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 \c true if the attached device is enumerated in Full Speed mode, \c false otherwise.
*/
static inline bool USB_Host_IsDeviceFullSpeed(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool USB_Host_IsDeviceFullSpeed(void)
{
return (AVR32_USBB.USBSTA.speed == AVR32_USBB_SPEED_FULL);
}
/** 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, \c false otherwise.
*
* \return Boolean \c true if the attached device has sent a Remote Wakeup request, \c false otherwise.
*/
static inline bool USB_Host_IsRemoteWakeupSent(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool USB_Host_IsRemoteWakeupSent(void)
{
return AVR32_USBB.UHINT.rxrsmi;
}
/** 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)
{
AVR32_USBB.UHINTCLR.rxrsmic = true;
}
/** 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)
{
AVR32_USBB.UHCON.resume = true;
}
/** Determines if a resume from Remote Wakeup request is currently being sent to an attached
* device.
*
* \return Boolean \c true if no resume request is currently being sent, \c false otherwise.
*/
static inline bool USB_Host_IsResumeFromWakeupRequestSent(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool USB_Host_IsResumeFromWakeupRequestSent(void)
{
return AVR32_USBB.UHCON.resume;
}
/* 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)
{
// Not required for UC3B
}
static inline void USB_Host_HostMode_Off(void) ATTR_ALWAYS_INLINE;
static inline void USB_Host_HostMode_Off(void)
{
// Not required for UC3B
}
static inline void USB_Host_VBUS_Auto_Enable(void) ATTR_ALWAYS_INLINE;
static inline void USB_Host_VBUS_Auto_Enable(void)
{
AVR32_USBB.USBCON.vbushwc = false;
}
static inline void USB_Host_VBUS_Manual_Enable(void) ATTR_ALWAYS_INLINE;
static inline void USB_Host_VBUS_Manual_Enable(void)
{
AVR32_USBB.USBCON.vbushwc = true;
}
static inline void USB_Host_VBUS_Auto_On(void) ATTR_ALWAYS_INLINE;
static inline void USB_Host_VBUS_Auto_On(void)
{
AVR32_USBB.USBSTASET.vbusrqs = true;
}
static inline void USB_Host_VBUS_Manual_On(void) ATTR_ALWAYS_INLINE;
static inline void USB_Host_VBUS_Manual_On(void)
{
AVR32_USBB.USBSTASET.vbusrqs = true;
}
static inline void USB_Host_VBUS_Auto_Off(void) ATTR_ALWAYS_INLINE;
static inline void USB_Host_VBUS_Auto_Off(void)
{
AVR32_USBB.USBSTACLR.vbusrqc = true;
}
static inline void USB_Host_VBUS_Manual_Off(void) ATTR_ALWAYS_INLINE;
static inline void USB_Host_VBUS_Manual_Off(void)
{
AVR32_USBB.USBSTACLR.vbusrqc = true;
}
static inline void USB_Host_SetDeviceAddress(const uint8_t Address) ATTR_ALWAYS_INLINE;
static inline void USB_Host_SetDeviceAddress(const uint8_t Address)
{
AVR32_USBB.UHADDR1.uhaddr_p0 = Address;
AVR32_USBB.UHADDR1.uhaddr_p1 = Address;
AVR32_USBB.UHADDR1.uhaddr_p2 = Address;
AVR32_USBB.UHADDR1.uhaddr_p3 = Address;
AVR32_USBB.UHADDR2.uhaddr_p4 = Address;
AVR32_USBB.UHADDR2.uhaddr_p5 = Address;
AVR32_USBB.UHADDR2.uhaddr_p6 = Address;
}
/* 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
/** @} */

View file

@ -0,0 +1,166 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
#include "../../../../Common/Common.h"
#if (ARCH == ARCH_UC3)
#define __INCLUDE_FROM_USB_DRIVER
#include "../USBMode.h"
#if defined(USB_CAN_BE_HOST)
#include "PipeStream_UC3.h"
uint8_t Pipe_Discard_Stream(uint16_t Length,
uint16_t* const BytesProcessed)
{
uint8_t ErrorCode;
uint16_t BytesInTransfer = 0;
Pipe_SetPipeToken(PIPE_TOKEN_IN);
if ((ErrorCode = Pipe_WaitUntilReady()))
return ErrorCode;
if (BytesProcessed != NULL)
Length -= *BytesProcessed;
while (Length)
{
if (!(Pipe_IsReadWriteAllowed()))
{
Pipe_ClearIN();
if (BytesProcessed != NULL)
{
*BytesProcessed += BytesInTransfer;
return PIPE_RWSTREAM_IncompleteTransfer;
}
if ((ErrorCode = Pipe_WaitUntilReady()))
return ErrorCode;
}
else
{
Pipe_Discard_8();
Length--;
BytesInTransfer++;
}
}
return PIPE_RWSTREAM_NoError;
}
uint8_t Pipe_Null_Stream(uint16_t Length,
uint16_t* const BytesProcessed)
{
uint8_t ErrorCode;
uint16_t BytesInTransfer = 0;
Pipe_SetPipeToken(PIPE_TOKEN_OUT);
if ((ErrorCode = Pipe_WaitUntilReady()))
return ErrorCode;
if (BytesProcessed != NULL)
Length -= *BytesProcessed;
while (Length)
{
if (!(Pipe_IsReadWriteAllowed()))
{
Pipe_ClearOUT();
if (BytesProcessed != NULL)
{
*BytesProcessed += BytesInTransfer;
return PIPE_RWSTREAM_IncompleteTransfer;
}
USB_USBTask();
if ((ErrorCode = Pipe_WaitUntilReady()))
return ErrorCode;
}
else
{
Pipe_Write_8(0);
Length--;
BytesInTransfer++;
}
}
return PIPE_RWSTREAM_NoError;
}
/* The following abuses the C preprocessor in order to copy-paste common code with slight alterations,
* so that the code needs to be written once. It is a crude form of templating to reduce code maintenance. */
#define TEMPLATE_FUNC_NAME Pipe_Write_Stream_LE
#define TEMPLATE_BUFFER_TYPE const void*
#define TEMPLATE_TOKEN PIPE_TOKEN_OUT
#define TEMPLATE_CLEAR_PIPE() Pipe_ClearOUT()
#define TEMPLATE_BUFFER_OFFSET(Length) 0
#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) DataStream += Amount
#define TEMPLATE_TRANSFER_BYTE(BufferPtr) Pipe_Write_8(*BufferPtr)
#include "Template/Template_Pipe_RW.c"
#define TEMPLATE_FUNC_NAME Pipe_Write_Stream_BE
#define TEMPLATE_BUFFER_TYPE const void*
#define TEMPLATE_TOKEN PIPE_TOKEN_OUT
#define TEMPLATE_CLEAR_PIPE() Pipe_ClearOUT()
#define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1)
#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) DataStream -= Amount
#define TEMPLATE_TRANSFER_BYTE(BufferPtr) Pipe_Write_8(*BufferPtr)
#include "Template/Template_Pipe_RW.c"
#define TEMPLATE_FUNC_NAME Pipe_Read_Stream_LE
#define TEMPLATE_BUFFER_TYPE void*
#define TEMPLATE_TOKEN PIPE_TOKEN_IN
#define TEMPLATE_CLEAR_PIPE() Pipe_ClearIN()
#define TEMPLATE_BUFFER_OFFSET(Length) 0
#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) DataStream += Amount
#define TEMPLATE_TRANSFER_BYTE(BufferPtr) *BufferPtr = Pipe_Read_8()
#include "Template/Template_Pipe_RW.c"
#define TEMPLATE_FUNC_NAME Pipe_Read_Stream_BE
#define TEMPLATE_BUFFER_TYPE void*
#define TEMPLATE_TOKEN PIPE_TOKEN_IN
#define TEMPLATE_CLEAR_PIPE() Pipe_ClearIN()
#define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1)
#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) DataStream -= Amount
#define TEMPLATE_TRANSFER_BYTE(BufferPtr) *BufferPtr = Pipe_Read_8()
#include "Template/Template_Pipe_RW.c"
#endif
#endif

View file

@ -0,0 +1,352 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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 Pipe data stream transmission and reception management for the AVR32 UC3 microcontrollers.
* \copydetails Group_PipeStreamRW_UC3
*
* \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_PipeStreamRW
* \defgroup Group_PipeStreamRW_UC3 Read/Write of Multi-Byte Streams (UC3)
* \brief Pipe data stream transmission and reception management for the Atmel AVR32 UC3 architecture.
*
* Functions, macros, variables, enums and types related to data reading and writing of data streams from
* and to pipes.
*
* @{
*/
#ifndef __PIPE_STREAM_UC3_H__
#define __PIPE_STREAM_UC3_H__
/* Includes: */
#include "../../../../Common/Common.h"
#include "../USBMode.h"
#include "../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: */
/* Function Prototypes: */
/** \name Stream functions for null data */
//@{
/** Reads and discards the given number of bytes from the pipe, discarding fully read packets from the host
* as needed. The last packet is not automatically discarded once the remaining bytes has been read; the
* user is responsible for manually discarding the last packet from the device via the \ref Pipe_ClearIN() macro.
*
* If the BytesProcessed parameter is \c NULL, the entire stream transfer is attempted at once, failing or
* succeeding as a single unit. If the BytesProcessed parameter points to a valid storage location, the transfer
* will instead be performed as a series of chunks. Each time the pipe bank becomes empty while there is still data
* to process (and after the current packet has been acknowledged) the BytesProcessed location will be updated with
* the total number of bytes processed in the stream, and the function will exit with an error code of
* \ref PIPE_RWSTREAM_IncompleteTransfer. This allows for any abort checking to be performed in the user code - to
* continue the transfer, call the function again with identical parameters and it will resume until the BytesProcessed
* value reaches the total transfer length.
*
* <b>Single Stream Transfer Example:</b>
* \code
* uint8_t ErrorCode;
*
* if ((ErrorCode = Pipe_Discard_Stream(512, NULL)) != PIPE_RWSTREAM_NoError)
* {
* // Stream failed to complete - check ErrorCode here
* }
* \endcode
*
* <b>Partial Stream Transfers Example:</b>
* \code
* uint8_t ErrorCode;
* uint16_t BytesProcessed;
*
* BytesProcessed = 0;
* while ((ErrorCode = Pipe_Discard_Stream(512, &BytesProcessed)) == PIPE_RWSTREAM_IncompleteTransfer)
* {
* // Stream not yet complete - do other actions here, abort if required
* }
*
* if (ErrorCode != PIPE_RWSTREAM_NoError)
* {
* // Stream failed to complete - check ErrorCode here
* }
* \endcode
*
* \note The pipe token is set automatically, thus this can be used on bi-directional pipes directly without
* having to explicitly change the data direction with a call to \ref Pipe_SetPipeToken().
*
* \param[in] Length Number of bytes to discard via the currently selected pipe.
* \param[in] BytesProcessed Pointer to a location where the total number of bytes already processed should
* updated, \c NULL if the entire stream should be processed at once.
*
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
*/
uint8_t Pipe_Discard_Stream(uint16_t Length,
uint16_t* const BytesProcessed);
/** Writes a given number of zeroed bytes to the pipe, sending full pipe packets from the host to the device
* as needed. The last packet is not automatically sent once the remaining bytes has been written; the
* user is responsible for manually discarding the last packet from the device via the \ref Pipe_ClearOUT() macro.
*
* If the BytesProcessed parameter is \c NULL, the entire stream transfer is attempted at once, failing or
* succeeding as a single unit. If the BytesProcessed parameter points to a valid storage location, the transfer
* will instead be performed as a series of chunks. Each time the pipe bank becomes full while there is still data
* to process (and after the current packet transmission has been initiated) the BytesProcessed location will be
* updated with the total number of bytes processed in the stream, and the function will exit with an error code of
* \ref PIPE_RWSTREAM_IncompleteTransfer. This allows for any abort checking to be performed in the user code - to
* continue the transfer, call the function again with identical parameters and it will resume until the BytesProcessed
* value reaches the total transfer length.
*
* <b>Single Stream Transfer Example:</b>
* \code
* uint8_t ErrorCode;
*
* if ((ErrorCode = Pipe_Null_Stream(512, NULL)) != PIPE_RWSTREAM_NoError)
* {
* // Stream failed to complete - check ErrorCode here
* }
* \endcode
*
* <b>Partial Stream Transfers Example:</b>
* \code
* uint8_t ErrorCode;
* uint16_t BytesProcessed;
*
* BytesProcessed = 0;
* while ((ErrorCode = Pipe_Null_Stream(512, &BytesProcessed)) == PIPE_RWSTREAM_IncompleteTransfer)
* {
* // Stream not yet complete - do other actions here, abort if required
* }
*
* if (ErrorCode != PIPE_RWSTREAM_NoError)
* {
* // Stream failed to complete - check ErrorCode here
* }
* \endcode
*
* \note The pipe token is set automatically, thus this can be used on bi-directional pipes directly without
* having to explicitly change the data direction with a call to \ref Pipe_SetPipeToken().
*
* \param[in] Length Number of zero bytes to write via the currently selected pipe.
* \param[in] BytesProcessed Pointer to a location where the total number of bytes already processed should
* updated, \c NULL if the entire stream should be processed at once.
*
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
*/
uint8_t Pipe_Null_Stream(uint16_t Length,
uint16_t* const BytesProcessed);
//@}
/** \name Stream functions for RAM source/destination data */
//@{
/** Writes the given number of bytes to the pipe from the given buffer in little endian,
* sending full packets to the device as needed. The last packet filled is not automatically sent;
* the user is responsible for manually sending the last written packet to the host via the
* \ref Pipe_ClearOUT() macro. Between each USB packet, the given stream callback function is
* executed repeatedly until the next packet is ready, allowing for early aborts of stream transfers.
*
* If the BytesProcessed parameter is \c NULL, the entire stream transfer is attempted at once,
* failing or succeeding as a single unit. If the BytesProcessed parameter points to a valid
* storage location, the transfer will instead be performed as a series of chunks. Each time
* the pipe bank becomes full while there is still data to process (and after the current
* packet transmission has been initiated) the BytesProcessed location will be updated with the
* total number of bytes processed in the stream, and the function will exit with an error code of
* \ref PIPE_RWSTREAM_IncompleteTransfer. This allows for any abort checking to be performed
* in the user code - to continue the transfer, call the function again with identical parameters
* and it will resume until the BytesProcessed value reaches the total transfer length.
*
* <b>Single Stream Transfer Example:</b>
* \code
* uint8_t DataStream[512];
* uint8_t ErrorCode;
*
* if ((ErrorCode = Pipe_Write_Stream_LE(DataStream, sizeof(DataStream),
* NULL)) != PIPE_RWSTREAM_NoError)
* {
* // Stream failed to complete - check ErrorCode here
* }
* \endcode
*
* <b>Partial Stream Transfers Example:</b>
* \code
* uint8_t DataStream[512];
* uint8_t ErrorCode;
* uint16_t BytesProcessed;
*
* BytesProcessed = 0;
* while ((ErrorCode = Pipe_Write_Stream_LE(DataStream, sizeof(DataStream),
* &BytesProcessed)) == PIPE_RWSTREAM_IncompleteTransfer)
* {
* // Stream not yet complete - do other actions here, abort if required
* }
*
* if (ErrorCode != PIPE_RWSTREAM_NoError)
* {
* // Stream failed to complete - check ErrorCode here
* }
* \endcode
*
* \note The pipe token is set automatically, thus this can be used on bi-directional pipes directly without
* having to explicitly change the data direction with a call to \ref Pipe_SetPipeToken().
*
* \param[in] Buffer Pointer to the source data buffer to read from.
* \param[in] Length Number of bytes to read for the currently selected pipe into the buffer.
* \param[in] BytesProcessed Pointer to a location where the total number of bytes already processed should
* updated, \c NULL if the entire stream should be written at once.
*
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
*/
uint8_t Pipe_Write_Stream_LE(const void* const Buffer,
uint16_t Length,
uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
/** Writes the given number of bytes to the pipe from the given buffer in big endian,
* sending full packets to the device as needed. The last packet filled is not automatically sent;
* the user is responsible for manually sending the last written packet to the host via the
* \ref Pipe_ClearOUT() macro. Between each USB packet, the given stream callback function is
* executed repeatedly until the next packet is ready, allowing for early aborts of stream transfers.
*
* \note The pipe token is set automatically, thus this can be used on bi-directional pipes directly without
* having to explicitly change the data direction with a call to \ref Pipe_SetPipeToken().
*
* \param[in] Buffer Pointer to the source data buffer to read from.
* \param[in] Length Number of bytes to read for the currently selected pipe into the buffer.
* \param[in] BytesProcessed Pointer to a location where the total number of bytes already processed should
* updated, \c NULL if the entire stream should be written at once.
*
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
*/
uint8_t Pipe_Write_Stream_BE(const void* const Buffer,
uint16_t Length,
uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
/** Reads the given number of bytes from the pipe into the given buffer in little endian,
* sending full packets to the device as needed. The last packet filled is not automatically sent;
* the user is responsible for manually sending the last written packet to the host via the
* \ref Pipe_ClearIN() macro. Between each USB packet, the given stream callback function is
* executed repeatedly until the next packet is ready, allowing for early aborts of stream transfers.
*
* If the BytesProcessed parameter is \c NULL, the entire stream transfer is attempted at once,
* failing or succeeding as a single unit. If the BytesProcessed parameter points to a valid
* storage location, the transfer will instead be performed as a series of chunks. Each time
* the pipe bank becomes empty while there is still data to process (and after the current
* packet has been acknowledged) the BytesProcessed location will be updated with the total number
* of bytes processed in the stream, and the function will exit with an error code of
* \ref PIPE_RWSTREAM_IncompleteTransfer. This allows for any abort checking to be performed
* in the user code - to continue the transfer, call the function again with identical parameters
* and it will resume until the BytesProcessed value reaches the total transfer length.
*
* <b>Single Stream Transfer Example:</b>
* \code
* uint8_t DataStream[512];
* uint8_t ErrorCode;
*
* if ((ErrorCode = Pipe_Read_Stream_LE(DataStream, sizeof(DataStream),
* NULL)) != PIPE_RWSTREAM_NoError)
* {
* // Stream failed to complete - check ErrorCode here
* }
* \endcode
*
* <b>Partial Stream Transfers Example:</b>
* \code
* uint8_t DataStream[512];
* uint8_t ErrorCode;
* uint16_t BytesProcessed;
*
* BytesProcessed = 0;
* while ((ErrorCode = Pipe_Read_Stream_LE(DataStream, sizeof(DataStream),
* &BytesProcessed)) == PIPE_RWSTREAM_IncompleteTransfer)
* {
* // Stream not yet complete - do other actions here, abort if required
* }
*
* if (ErrorCode != PIPE_RWSTREAM_NoError)
* {
* // Stream failed to complete - check ErrorCode here
* }
* \endcode
*
* \note The pipe token is set automatically, thus this can be used on bi-directional pipes directly without
* having to explicitly change the data direction with a call to \ref Pipe_SetPipeToken().
*
* \param[out] Buffer Pointer to the source data buffer to write to.
* \param[in] Length Number of bytes to read for the currently selected pipe to read from.
* \param[in] BytesProcessed Pointer to a location where the total number of bytes already processed should
* updated, \c NULL if the entire stream should be read at once.
*
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
*/
uint8_t Pipe_Read_Stream_LE(void* const Buffer,
uint16_t Length,
uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
/** Reads the given number of bytes from the pipe into the given buffer in big endian,
* sending full packets to the device as needed. The last packet filled is not automatically sent;
* the user is responsible for manually sending the last written packet to the host via the
* \ref Pipe_ClearIN() macro. Between each USB packet, the given stream callback function is
* executed repeatedly until the next packet is ready, allowing for early aborts of stream transfers.
*
* \note The pipe token is set automatically, thus this can be used on bi-directional pipes directly without
* having to explicitly change the data direction with a call to \ref Pipe_SetPipeToken().
*
* \param[out] Buffer Pointer to the source data buffer to write to.
* \param[in] Length Number of bytes to read for the currently selected pipe to read from.
* \param[in] BytesProcessed Pointer to a location where the total number of bytes already processed should
* updated, \c NULL if the entire stream should be read at once.
*
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
*/
uint8_t Pipe_Read_Stream_BE(void* const Buffer,
uint16_t Length,
uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
//@}
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,209 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
#include "../../../../Common/Common.h"
#if (ARCH == ARCH_UC3)
#define __INCLUDE_FROM_USB_DRIVER
#include "../USBMode.h"
#if defined(USB_CAN_BE_HOST)
#include "../Pipe.h"
uint8_t USB_Host_ControlPipeSize = PIPE_CONTROLPIPE_DEFAULT_SIZE;
volatile uint32_t USB_Pipe_SelectedPipe = PIPE_CONTROLPIPE;
volatile uint8_t* USB_Pipe_FIFOPos[PIPE_TOTAL_PIPES];
bool Pipe_ConfigurePipeTable(const USB_Pipe_Table_t* const Table,
const uint8_t Entries)
{
for (uint8_t i = 0; i < Entries; i++)
{
if (!(Table[i].Address))
continue;
if (!(Pipe_ConfigurePipe(Table[i].Address, Table[i].Type, Table[i].EndpointAddress, Table[i].Size, Table[i].Banks)))
{
return false;
}
}
return true;
}
bool Pipe_ConfigurePipe(const uint8_t Address,
const uint8_t Type,
const uint8_t EndpointAddress,
const uint16_t Size,
const uint8_t Banks)
{
uint8_t Number = (Address & PIPE_EPNUM_MASK);
uint8_t Token = (Address & PIPE_DIR_IN) ? PIPE_TOKEN_IN : PIPE_TOKEN_OUT;
if (Number >= PIPE_TOTAL_PIPES)
return false;
if (Type == EP_TYPE_CONTROL)
Token = PIPE_TOKEN_SETUP;
USB_Pipe_FIFOPos[Number] = &AVR32_USBB_SLAVE[Number * PIPE_HSB_ADDRESS_SPACE_SIZE];
#if defined(ORDERED_EP_CONFIG)
Pipe_SelectPipe(Number);
Pipe_EnablePipe();
(&AVR32_USBB.upcfg0)[Number] = 0;
(&AVR32_USBB.upcfg0)[Number] = (AVR32_USBB_ALLOC_MASK |
((uint32_t)Type << AVR32_USBB_PTYPE_OFFSET) |
((uint32_t)Token << AVR32_USBB_PTOKEN_OFFSET) |
((Banks > 1) ? AVR32_USBB_PBK_MASK : 0) |
Pipe_BytesToEPSizeMask(Size) |
((uint32_t)Number << AVR32_USBB_PEPNUM_OFFSET));
Pipe_SetInfiniteINRequests();
return Pipe_IsConfigured();
#else
for (uint8_t PNum = Number; PNum < PIPE_TOTAL_PIPES; PNum++)
{
uint32_t UPCFG0Temp;
Pipe_SelectPipe(PNum);
if (PNum == Number)
{
UPCFG0Temp = (AVR32_USBB_ALLOC_MASK |
((uint32_t)Type << AVR32_USBB_PTYPE_OFFSET) |
((uint32_t)Token << AVR32_USBB_PTOKEN_OFFSET) |
((Banks > 1) ? AVR32_USBB_PBK_MASK : 0) |
Pipe_BytesToEPSizeMask(Size) |
((EndpointAddress & PIPE_EPNUM_MASK) << AVR32_USBB_PEPNUM_OFFSET));
}
else
{
UPCFG0Temp = (&AVR32_USBB.upcfg0)[PNum];
}
if (!(UPCFG0Temp & AVR32_USBB_ALLOC_MASK))
continue;
Pipe_DisablePipe();
(&AVR32_USBB.upcfg0)[PNum] &= ~AVR32_USBB_ALLOC_MASK;
Pipe_EnablePipe();
(&AVR32_USBB.upcfg0)[PNum] = UPCFG0Temp;
Pipe_SetInfiniteINRequests();
if (!(Pipe_IsConfigured()))
return false;
}
Pipe_SelectPipe(Number);
return true;
#endif
}
void Pipe_ClearPipes(void)
{
for (uint8_t PNum = 0; PNum < PIPE_TOTAL_PIPES; PNum++)
{
Pipe_SelectPipe(PNum);
(&AVR32_USBB.upcfg0)[PNum] = 0;
(&AVR32_USBB.upcon0clr)[PNum] = -1;
USB_Pipe_FIFOPos[PNum] = &AVR32_USBB_SLAVE[PNum * 0x10000];
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;
if (Pipe_GetBoundEndpointAddress() == EndpointAddress)
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
#endif

View file

@ -0,0 +1,924 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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 Pipe definitions for the AVR32 UC3 microcontrollers.
* \copydetails Group_PipeManagement_UC3
*
* \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_PipeRW
* \defgroup Group_PipeRW_UC3 Pipe Data Reading and Writing (UC3)
* \brief Pipe data read/write definitions for the Atmel AVR32 UC3 architecture.
*
* Functions, macros, variables, enums and types related to data reading and writing from and to pipes.
*/
/** \ingroup Group_PipePrimitiveRW
* \defgroup Group_PipePrimitiveRW_UC3 Read/Write of Primitive Data Types (UC3)
* \brief Pipe primitive data read/write definitions for the Atmel AVR32 UC3 architecture.
*
* Functions, macros, variables, enums and types related to data reading and writing of primitive data types
* from and to pipes.
*/
/** \ingroup Group_PipePacketManagement
* \defgroup Group_PipePacketManagement_UC3 Pipe Packet Management (UC3)
* \brief Pipe packet management definitions for the Atmel AVR32 UC3 architecture.
*
* Functions, macros, variables, enums and types related to packet management of pipes.
*/
/** \ingroup Group_PipeControlReq
* \defgroup Group_PipeControlReq_UC3 Pipe Control Request Management (UC3)
* \brief Pipe control request management definitions for the Atmel AVR32 UC3 architecture.
*
* 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_PipeManagement
* \defgroup Group_PipeManagement_UC3 Pipe Management (UC3)
* \brief Pipe management definitions for the Atmel AVR32 UC3 architecture.
*
* 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_UC3_H__
#define __PIPE_UC3_H__
/* Includes: */
#include "../../../../Common/Common.h"
#include "../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
/* Private Interface - For use in library only: */
#if !defined(__DOXYGEN__)
/* Macros: */
#define PIPE_HSB_ADDRESS_SPACE_SIZE (64 * 1024UL)
/* External Variables: */
extern volatile uint32_t USB_Pipe_SelectedPipe;
extern volatile uint8_t* USB_Pipe_FIFOPos[];
#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 (AVR32_USBB_UPSTA0_OVERFI_MASK << 8)
/** Mask for \ref Pipe_GetErrorFlags(), indicating that a CRC error occurred in the pipe on the received data. */
#define PIPE_ERRORFLAG_CRC16 AVR32_USBB_UPERR0_CRC16_MASK
/** Mask for \ref Pipe_GetErrorFlags(), indicating that a hardware timeout error occurred in the pipe. */
#define PIPE_ERRORFLAG_TIMEOUT AVR32_USBB_UPERR0_TIMEOUT_MASK
/** Mask for \ref Pipe_GetErrorFlags(), indicating that a hardware PID error occurred in the pipe. */
#define PIPE_ERRORFLAG_PID AVR32_USBB_UPERR0_PID_MASK
/** Mask for \ref Pipe_GetErrorFlags(), indicating that a hardware data PID error occurred in the pipe. */
#define PIPE_ERRORFLAG_DATAPID AVR32_USBB_UPERR0_DATAPID_MASK
/** Mask for \ref Pipe_GetErrorFlags(), indicating that a hardware data toggle error occurred in the pipe. */
#define PIPE_ERRORFLAG_DATATGL AVR32_USBB_UPERR0_DATATGL_MASK
//@}
/** \name Pipe Token Masks */
//@{
/** Token mask for \ref Pipe_SetPipeToken() and \ref Pipe_GetPipeToken(). 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 AVR32_USBB_UPCFG0_PTOKEN_SETUP
/** Token mask for \ref Pipe_SetPipeToken() and \ref Pipe_GetPipeToken(). 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 AVR32_USBB_UPCFG0_PTOKEN_IN
/** Token mask for \ref Pipe_SetPipeToken() and \ref Pipe_GetPipeToken(). 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 AVR32_USBB_UPCFG0_PTOKEN_OUT
//@}
/** 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
#if defined(USB_SERIES_UC3A3_AVR32) || defined(USB_SERIES_UC3A4_AVR32) || defined(__DOXYGEN__)
/** Total number of pipes (including the default control pipe at address 0) which may be used in
* the device.
*/
#define PIPE_TOTAL_PIPES 8
#else
#define PIPE_TOTAL_PIPES 7
#endif
/** 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 UC3 AVR model.
*/
#define PIPE_MAX_SIZE 256
/* Enums: */
/** Enum for the possible error return codes of the \ref Pipe_WaitUntilReady() function.
*
* \ingroup Group_PipeRW_UC3
*/
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.
*
* \ingroup Group_PipeRW_UC3
*
* \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 (&AVR32_USBB.UPSTA0)[USB_Pipe_SelectedPipe].pbyct;
}
/** Determines the currently selected pipe's direction.
*
* \return The currently selected pipe's direction, as a \c PIPE_DIR_* mask.
*/
static inline uint8_t Pipe_GetPipeDirection(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline uint8_t Pipe_GetPipeDirection(void)
{
return (((&AVR32_USBB.UPCFG0)[USB_Pipe_SelectedPipe].ptoken == PIPE_TOKEN_OUT) ? PIPE_DIR_OUT : PIPE_DIR_IN);
}
/** 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 (USB_Pipe_SelectedPipe | Pipe_GetPipeDirection());
}
/** Selects the given pipe address. Any pipe operations which do not require the pipe address to be
* indicated will operate on the currently selected pipe.
*
* \param[in] Address Address of the pipe to select.
*/
static inline void Pipe_SelectPipe(const uint8_t Address) ATTR_ALWAYS_INLINE;
static inline void Pipe_SelectPipe(const uint8_t Address)
{
USB_Pipe_SelectedPipe = (Address & PIPE_EPNUM_MASK);
}
/** Resets the desired pipe, including the pipe banks and flags.
*
* \param[in] Address Index of the pipe to reset.
*/
static inline void Pipe_ResetPipe(const uint8_t Address) ATTR_ALWAYS_INLINE;
static inline void Pipe_ResetPipe(const uint8_t Address)
{
uint32_t PipeNumber = (Address & PIPE_EPNUM_MASK);
AVR32_USBB.uprst |= (AVR32_USBB_PRST0_MASK << PipeNumber);
AVR32_USBB.uprst &= ~(AVR32_USBB_PRST0_MASK << PipeNumber);
USB_Pipe_FIFOPos[PipeNumber] = &AVR32_USBB_SLAVE[PipeNumber * PIPE_HSB_ADDRESS_SPACE_SIZE];
}
/** 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)
{
AVR32_USBB.uprst |= (AVR32_USBB_PEN0_MASK << USB_Pipe_SelectedPipe);
}
/** 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)
{
AVR32_USBB.uprst &= ~(AVR32_USBB_PEN0_MASK << USB_Pipe_SelectedPipe);
}
/** Determines if the currently selected pipe is enabled, but not necessarily configured.
*
* \return Boolean \c true if the currently selected pipe is enabled, \c false otherwise.
*/
static inline bool Pipe_IsEnabled(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool Pipe_IsEnabled(void)
{
return ((AVR32_USBB.uprst & (AVR32_USBB_PEN0_MASK << USB_Pipe_SelectedPipe)) ? true : false);
}
/** Gets the current pipe token, indicating the pipe's data direction and type.
*
* \return The current pipe token, as a \c PIPE_TOKEN_* mask.
*/
static inline uint8_t Pipe_GetPipeToken(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline uint8_t Pipe_GetPipeToken(void)
{
return (&AVR32_USBB.UPCFG0)[USB_Pipe_SelectedPipe].ptoken;
}
/** Sets the token for the currently selected pipe to one of the tokens specified by the \c 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 \c PIPE_TOKEN_* mask.
*/
static inline void Pipe_SetPipeToken(const uint8_t Token) ATTR_ALWAYS_INLINE;
static inline void Pipe_SetPipeToken(const uint8_t Token)
{
(&AVR32_USBB.UPCFG0)[USB_Pipe_SelectedPipe].ptoken = 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)
{
(&AVR32_USBB.UPINRQ0)[USB_Pipe_SelectedPipe].inmode = true;
}
/** 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)
{
(&AVR32_USBB.UPINRQ0)[USB_Pipe_SelectedPipe].inmode = false;
(&AVR32_USBB.UPINRQ0)[USB_Pipe_SelectedPipe].inrq = TotalINRequests;
}
/** Determines if the currently selected pipe is configured.
*
* \return Boolean \c true if the selected pipe is configured, \c false otherwise.
*/
static inline bool Pipe_IsConfigured(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool Pipe_IsConfigured(void)
{
return (&AVR32_USBB.UPSTA0)[USB_Pipe_SelectedPipe].cfgok;
}
/** Retrieves the endpoint address of the endpoint within the attached device that the currently selected
* pipe is bound to.
*
* \return Endpoint address the currently selected pipe is bound to.
*/
static inline uint8_t Pipe_GetBoundEndpointAddress(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline uint8_t Pipe_GetBoundEndpointAddress(void)
{
return ((&AVR32_USBB.UPCFG0)[USB_Pipe_SelectedPipe].pepnum |
((Pipe_GetPipeToken() == PIPE_TOKEN_IN) ? PIPE_DIR_IN : PIPE_DIR_OUT));
}
/** 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)
{
(&AVR32_USBB.UPCFG0)[USB_Pipe_SelectedPipe].intfrq = 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 ((AVR32_USBB.uhint & (AVR32_USBB_P6INT_MASK | AVR32_USBB_P5INT_MASK |
AVR32_USBB_P4INT_MASK | AVR32_USBB_P3INT_MASK |
AVR32_USBB_P2INT_MASK | AVR32_USBB_P1INT_MASK |
AVR32_USBB_P0INT_MASK)) >> AVR32_USBB_P0INT_OFFSET);
}
/** Determines if the specified pipe address has interrupted (valid only for INTERRUPT type
* pipes).
*
* \param[in] Address Address of the pipe whose interrupt flag should be tested.
*
* \return Boolean \c true if the specified pipe has interrupted, \c false otherwise.
*/
static inline bool Pipe_HasPipeInterrupted(const uint8_t Address) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool Pipe_HasPipeInterrupted(const uint8_t Address)
{
return ((AVR32_USBB.uhint & (AVR32_USBB_P0INTES_MASK << (Address & PIPE_EPNUM_MASK))) ? 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)
{
(&AVR32_USBB.UPCON0CLR)[USB_Pipe_SelectedPipe].pfreezec = true;
}
/** 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)
{
(&AVR32_USBB.UPCON0SET)[USB_Pipe_SelectedPipe].pfreezes = true;
}
/** Determines if the currently selected pipe is frozen, and not able to accept data.
*
* \return Boolean \c true if the currently selected pipe is frozen, \c false otherwise.
*/
static inline bool Pipe_IsFrozen(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool Pipe_IsFrozen(void)
{
return (((&AVR32_USBB.UPCON0)[USB_Pipe_SelectedPipe].pfreeze) ? true : false);
}
/** Clears the error flags for the currently selected pipe. */
static inline void Pipe_ClearError(void) ATTR_ALWAYS_INLINE;
static inline void Pipe_ClearError(void)
{
(&AVR32_USBB.uperr0)[USB_Pipe_SelectedPipe] = 0;
(&AVR32_USBB.UPSTA0CLR)[USB_Pipe_SelectedPipe].overfic = true;
}
/** 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 \c true if an error has occurred on the selected pipe, \c false otherwise.
*/
static inline bool Pipe_IsError(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool Pipe_IsError(void)
{
return (((&AVR32_USBB.upsta0)[USB_Pipe_SelectedPipe] &
(AVR32_USBB_PERRI_MASK | AVR32_USBB_OVERFI_MASK)) ? true : false);
}
/** Gets a mask of the hardware error flags which have occurred on the currently selected pipe. This
* value can then be masked against the \c PIPE_ERRORFLAG_* masks to determine what error has occurred.
*
* \return Mask comprising of \c 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 (((&AVR32_USBB.uperr0)[USB_Pipe_SelectedPipe] &
(PIPE_ERRORFLAG_CRC16 | PIPE_ERRORFLAG_TIMEOUT |
PIPE_ERRORFLAG_PID | PIPE_ERRORFLAG_DATAPID |
PIPE_ERRORFLAG_DATATGL)) |
(((&AVR32_USBB.upsta0)[USB_Pipe_SelectedPipe] << 8) &
PIPE_ERRORFLAG_OVERFLOW));
}
/** 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_UC3
*
* \return Total number of busy banks in the selected pipe.
*/
static inline uint8_t Pipe_GetBusyBanks(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline uint8_t Pipe_GetBusyBanks(void)
{
return (&AVR32_USBB.UPSTA0)[USB_Pipe_SelectedPipe].nbusybk;
}
/** 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_UC3
*
* \return Boolean \c 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 (&AVR32_USBB.UPSTA0)[USB_Pipe_SelectedPipe].rwall;
}
/** Determines if a packet has been received on the currently selected IN pipe from the attached device.
*
* \ingroup Group_PipePacketManagement_UC3
*
* \return Boolean \c true if the current pipe has received an IN packet, \c false otherwise.
*/
static inline bool Pipe_IsINReceived(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool Pipe_IsINReceived(void)
{
return (&AVR32_USBB.UPSTA0)[USB_Pipe_SelectedPipe].rxini;
}
/** Determines if the currently selected OUT pipe is ready to send an OUT packet to the attached device.
*
* \ingroup Group_PipePacketManagement_UC3
*
* \return Boolean \c true if the current pipe is ready for an OUT packet, \c false otherwise.
*/
static inline bool Pipe_IsOUTReady(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool Pipe_IsOUTReady(void)
{
return (&AVR32_USBB.UPSTA0)[USB_Pipe_SelectedPipe].txouti;
}
/** Determines if no SETUP request is currently being sent to the attached device on the selected
* CONTROL type pipe.
*
* \ingroup Group_PipePacketManagement_UC3
*
* \return Boolean \c true if the current pipe is ready for a SETUP packet, \c false otherwise.
*/
static inline bool Pipe_IsSETUPSent(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool Pipe_IsSETUPSent(void)
{
return (&AVR32_USBB.UPSTA0)[USB_Pipe_SelectedPipe].txstpi;
}
/** Sends the currently selected CONTROL type pipe's contents to the device as a SETUP packet.
*
* \ingroup Group_PipePacketManagement_UC3
*/
static inline void Pipe_ClearSETUP(void) ATTR_ALWAYS_INLINE;
static inline void Pipe_ClearSETUP(void)
{
(&AVR32_USBB.UPSTA0CLR)[USB_Pipe_SelectedPipe].txstpic = true;
(&AVR32_USBB.UPCON0CLR)[USB_Pipe_SelectedPipe].fifoconc = true;
USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe] = &AVR32_USBB_SLAVE[USB_Pipe_SelectedPipe * PIPE_HSB_ADDRESS_SPACE_SIZE];
}
/** 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_UC3
*/
static inline void Pipe_ClearIN(void) ATTR_ALWAYS_INLINE;
static inline void Pipe_ClearIN(void)
{
(&AVR32_USBB.UPSTA0CLR)[USB_Pipe_SelectedPipe].rxinic = true;
(&AVR32_USBB.UPCON0CLR)[USB_Pipe_SelectedPipe].fifoconc = true;
USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe] = &AVR32_USBB_SLAVE[USB_Pipe_SelectedPipe * PIPE_HSB_ADDRESS_SPACE_SIZE];
}
/** 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_UC3
*/
static inline void Pipe_ClearOUT(void) ATTR_ALWAYS_INLINE;
static inline void Pipe_ClearOUT(void)
{
(&AVR32_USBB.UPSTA0CLR)[USB_Pipe_SelectedPipe].txoutic = true;
(&AVR32_USBB.UPCON0CLR)[USB_Pipe_SelectedPipe].fifoconc = true;
USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe] = &AVR32_USBB_SLAVE[USB_Pipe_SelectedPipe * PIPE_HSB_ADDRESS_SPACE_SIZE];
}
/** 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_UC3
*
* \return Boolean \c true if an NAK has been received on the current pipe, \c false otherwise.
*/
static inline bool Pipe_IsNAKReceived(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool Pipe_IsNAKReceived(void)
{
return (&AVR32_USBB.UPSTA0)[USB_Pipe_SelectedPipe].nakedi;
}
/** Clears the NAK condition on the currently selected pipe.
*
* \ingroup Group_PipePacketManagement_UC3
*
* \see \ref Pipe_IsNAKReceived() for more details.
*/
static inline void Pipe_ClearNAKReceived(void) ATTR_ALWAYS_INLINE;
static inline void Pipe_ClearNAKReceived(void)
{
(&AVR32_USBB.UPSTA0CLR)[USB_Pipe_SelectedPipe].nakedic = true;
}
/** Determines if the currently selected pipe has had the STALL condition set by the attached device.
*
* \ingroup Group_PipePacketManagement_UC3
*
* \return Boolean \c true if the current pipe has been stalled by the attached device, \c false otherwise.
*/
static inline bool Pipe_IsStalled(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool Pipe_IsStalled(void)
{
return (&AVR32_USBB.UPSTA0)[USB_Pipe_SelectedPipe].rxstalldi;
}
/** 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_UC3
*/
static inline void Pipe_ClearStall(void) ATTR_ALWAYS_INLINE;
static inline void Pipe_ClearStall(void)
{
(&AVR32_USBB.UPSTA0CLR)[USB_Pipe_SelectedPipe].rxstalldic = true;
USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe] = &AVR32_USBB_SLAVE[USB_Pipe_SelectedPipe * PIPE_HSB_ADDRESS_SPACE_SIZE];
}
/** Reads one byte from the currently selected pipe's bank, for OUT direction pipes.
*
* \ingroup Group_PipePrimitiveRW_UC3
*
* \return Next byte in the currently selected pipe's FIFO buffer.
*/
static inline uint8_t Pipe_Read_8(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline uint8_t Pipe_Read_8(void)
{
return *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++);
}
/** Writes one byte to the currently selected pipe's bank, for IN direction pipes.
*
* \ingroup Group_PipePrimitiveRW_UC3
*
* \param[in] Data Data to write into the the currently selected pipe's FIFO buffer.
*/
static inline void Pipe_Write_8(const uint8_t Data) ATTR_ALWAYS_INLINE;
static inline void Pipe_Write_8(const uint8_t Data)
{
*(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++) = Data;
}
/** Discards one byte from the currently selected pipe's bank, for OUT direction pipes.
*
* \ingroup Group_PipePrimitiveRW_UC3
*/
static inline void Pipe_Discard_8(void) ATTR_ALWAYS_INLINE;
static inline void Pipe_Discard_8(void)
{
uint8_t Dummy;
Dummy = *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++);
(void)Dummy;
}
/** Reads two bytes from the currently selected pipe's bank in little endian format, for OUT
* direction pipes.
*
* \ingroup Group_PipePrimitiveRW_UC3
*
* \return Next two bytes in the currently selected pipe's FIFO buffer.
*/
static inline uint16_t Pipe_Read_16_LE(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline uint16_t Pipe_Read_16_LE(void)
{
uint16_t Byte0 = *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++);
uint16_t Byte1 = *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++);
return ((Byte1 << 8) | Byte0);
}
/** Reads two bytes from the currently selected pipe's bank in big endian format, for OUT
* direction pipes.
*
* \ingroup Group_PipePrimitiveRW_UC3
*
* \return Next two bytes in the currently selected pipe's FIFO buffer.
*/
static inline uint16_t Pipe_Read_16_BE(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline uint16_t Pipe_Read_16_BE(void)
{
uint16_t Byte0 = *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++);
uint16_t Byte1 = *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++);
return ((Byte0 << 8) | Byte1);
}
/** Writes two bytes to the currently selected pipe's bank in little endian format, for IN
* direction pipes.
*
* \ingroup Group_PipePrimitiveRW_UC3
*
* \param[in] Data Data to write to the currently selected pipe's FIFO buffer.
*/
static inline void Pipe_Write_16_LE(const uint16_t Data) ATTR_ALWAYS_INLINE;
static inline void Pipe_Write_16_LE(const uint16_t Data)
{
*(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++) = (Data & 0xFF);
*(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++) = (Data >> 8);
}
/** Writes two bytes to the currently selected pipe's bank in big endian format, for IN
* direction pipes.
*
* \ingroup Group_PipePrimitiveRW_UC3
*
* \param[in] Data Data to write to the currently selected pipe's FIFO buffer.
*/
static inline void Pipe_Write_16_BE(const uint16_t Data) ATTR_ALWAYS_INLINE;
static inline void Pipe_Write_16_BE(const uint16_t Data)
{
*(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++) = (Data >> 8);
*(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++) = (Data & 0xFF);
}
/** Discards two bytes from the currently selected pipe's bank, for OUT direction pipes.
*
* \ingroup Group_PipePrimitiveRW_UC3
*/
static inline void Pipe_Discard_16(void) ATTR_ALWAYS_INLINE;
static inline void Pipe_Discard_16(void)
{
uint8_t Dummy;
Dummy = *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++);
Dummy = *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++);
(void)Dummy;
}
/** Reads four bytes from the currently selected pipe's bank in little endian format, for OUT
* direction pipes.
*
* \ingroup Group_PipePrimitiveRW_UC3
*
* \return Next four bytes in the currently selected pipe's FIFO buffer.
*/
static inline uint32_t Pipe_Read_32_LE(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline uint32_t Pipe_Read_32_LE(void)
{
uint32_t Byte0 = *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++);
uint32_t Byte1 = *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++);
uint32_t Byte2 = *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++);
uint32_t Byte3 = *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++);
return ((Byte3 << 24) | (Byte2 << 16) | (Byte1 << 8) | Byte0);
}
/** Reads four bytes from the currently selected pipe's bank in big endian format, for OUT
* direction pipes.
*
* \ingroup Group_PipePrimitiveRW_UC3
*
* \return Next four bytes in the currently selected pipe's FIFO buffer.
*/
static inline uint32_t Pipe_Read_32_BE(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline uint32_t Pipe_Read_32_BE(void)
{
uint32_t Byte0 = *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++);
uint32_t Byte1 = *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++);
uint32_t Byte2 = *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++);
uint32_t Byte3 = *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++);
return ((Byte0 << 24) | (Byte1 << 16) | (Byte2 << 8) | Byte3);
}
/** Writes four bytes to the currently selected pipe's bank in little endian format, for IN
* direction pipes.
*
* \ingroup Group_PipePrimitiveRW_UC3
*
* \param[in] Data Data to write to the currently selected pipe's FIFO buffer.
*/
static inline void Pipe_Write_32_LE(const uint32_t Data) ATTR_ALWAYS_INLINE;
static inline void Pipe_Write_32_LE(const uint32_t Data)
{
*(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++) = (Data & 0xFF);
*(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++) = (Data >> 8);
*(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++) = (Data >> 16);
*(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++) = (Data >> 24);
}
/** Writes four bytes to the currently selected pipe's bank in big endian format, for IN
* direction pipes.
*
* \ingroup Group_PipePrimitiveRW_UC3
*
* \param[in] Data Data to write to the currently selected pipe's FIFO buffer.
*/
static inline void Pipe_Write_32_BE(const uint32_t Data) ATTR_ALWAYS_INLINE;
static inline void Pipe_Write_32_BE(const uint32_t Data)
{
*(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++) = (Data >> 24);
*(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++) = (Data >> 16);
*(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++) = (Data >> 8);
*(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++) = (Data & 0xFF);
}
/** Discards four bytes from the currently selected pipe's bank, for OUT direction pipes.
*
* \ingroup Group_PipePrimitiveRW_UC3
*/
static inline void Pipe_Discard_32(void) ATTR_ALWAYS_INLINE;
static inline void Pipe_Discard_32(void)
{
uint8_t Dummy;
Dummy = *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++);
Dummy = *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++);
Dummy = *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++);
Dummy = *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++);
(void)Dummy;
}
/* 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.
*
* \attention This variable should be treated as read-only in the user application, and never manually
* changed in value.
*/
extern uint8_t USB_Host_ControlPipeSize;
/* Function Prototypes: */
/** Configures a table of pipe descriptions, in sequence. This function can be used to configure multiple
* pipes at the same time.
*
* \note Pipe with a zero address will be ignored, thus this function cannot be used to configure the
* control pipe.
*
* \param[in] Table Pointer to a table of pipe descriptions.
* \param[in] Entries Number of entries in the pipe table to configure.
*
* \return Boolean \c true if all pipes configured successfully, \c false otherwise.
*/
bool Pipe_ConfigurePipeTable(const USB_Pipe_Table_t* const Table,
const uint8_t Entries);
/** Configures the specified pipe address with the given pipe type, endpoint address within the attached device,
* bank size and number of hardware banks.
*
* 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] Address Pipe address to configure.
*
* \param[in] Type Type of pipe to configure, an \c EP_TYPE_* mask. Not all pipe types are available on Low
* Speed USB devices - refer to the USB 2.0 specification.
*
* \param[in] EndpointAddress Endpoint address 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.
*
* \note When the \c ORDERED_EP_CONFIG compile time option is used, Pipes <b>must</b> be configured in ascending order,
* or bank corruption will occur.
* \n\n
*
* \note Certain microcontroller model's pipes may have different maximum packet sizes based on the pipe's
* index - refer to the chosen microcontroller'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 \c true if the configuration succeeded, \c false otherwise.
*/
bool Pipe_ConfigurePipe(const uint8_t Address,
const uint8_t Type,
const uint8_t EndpointAddress,
const uint16_t Size,
const uint8_t Banks);
/** Spin-loops until the currently selected non-control pipe is ready for the next packet 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_UC3
*
* \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 \c true if a pipe bound to the given endpoint address of the specified direction is found,
* \c false otherwise.
*/
bool Pipe_IsEndpointBound(const uint8_t EndpointAddress) ATTR_WARN_UNUSED_RESULT;
/* 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 << AVR32_USBB_PSIZE_OFFSET);
}
/* Function Prototypes: */
void Pipe_ClearPipes(void);
#endif
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,84 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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.
*/
#if defined(TEMPLATE_FUNC_NAME)
uint8_t TEMPLATE_FUNC_NAME (void* const Buffer,
uint16_t Length)
{
uint8_t* DataStream = ((uint8_t*)Buffer + TEMPLATE_BUFFER_OFFSET(Length));
if (!(Length))
Endpoint_ClearOUT();
while (Length)
{
uint8_t USB_DeviceState_LCL = USB_DeviceState;
if (USB_DeviceState_LCL == DEVICE_STATE_Unattached)
return ENDPOINT_RWCSTREAM_DeviceDisconnected;
else if (USB_DeviceState_LCL == DEVICE_STATE_Suspended)
return ENDPOINT_RWCSTREAM_BusSuspended;
else if (Endpoint_IsSETUPReceived())
return ENDPOINT_RWCSTREAM_HostAborted;
if (Endpoint_IsOUTReceived())
{
while (Length && Endpoint_BytesInEndpoint())
{
TEMPLATE_TRANSFER_BYTE(DataStream);
TEMPLATE_BUFFER_MOVE(DataStream, 1);
Length--;
}
Endpoint_ClearOUT();
}
}
while (!(Endpoint_IsINReady()))
{
uint8_t USB_DeviceState_LCL = USB_DeviceState;
if (USB_DeviceState_LCL == DEVICE_STATE_Unattached)
return ENDPOINT_RWCSTREAM_DeviceDisconnected;
else if (USB_DeviceState_LCL == DEVICE_STATE_Suspended)
return ENDPOINT_RWCSTREAM_BusSuspended;
}
return ENDPOINT_RWCSTREAM_NoError;
}
#undef TEMPLATE_BUFFER_OFFSET
#undef TEMPLATE_BUFFER_MOVE
#undef TEMPLATE_FUNC_NAME
#undef TEMPLATE_TRANSFER_BYTE
#endif

View file

@ -0,0 +1,95 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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.
*/
#if defined(TEMPLATE_FUNC_NAME)
uint8_t TEMPLATE_FUNC_NAME (const void* const Buffer,
uint16_t Length)
{
uint8_t* DataStream = ((uint8_t*)Buffer + TEMPLATE_BUFFER_OFFSET(Length));
bool LastPacketFull = false;
if (Length > USB_ControlRequest.wLength)
Length = USB_ControlRequest.wLength;
else if (!(Length))
Endpoint_ClearIN();
while (Length || LastPacketFull)
{
uint8_t USB_DeviceState_LCL = USB_DeviceState;
if (USB_DeviceState_LCL == DEVICE_STATE_Unattached)
return ENDPOINT_RWCSTREAM_DeviceDisconnected;
else if (USB_DeviceState_LCL == DEVICE_STATE_Suspended)
return ENDPOINT_RWCSTREAM_BusSuspended;
else if (Endpoint_IsSETUPReceived())
return ENDPOINT_RWCSTREAM_HostAborted;
else if (Endpoint_IsOUTReceived())
break;
if (Endpoint_IsINReady())
{
uint16_t BytesInEndpoint = Endpoint_BytesInEndpoint();
while (Length && (BytesInEndpoint < USB_Device_ControlEndpointSize))
{
TEMPLATE_TRANSFER_BYTE(DataStream);
TEMPLATE_BUFFER_MOVE(DataStream, 1);
Length--;
BytesInEndpoint++;
}
LastPacketFull = (BytesInEndpoint == USB_Device_ControlEndpointSize);
Endpoint_ClearIN();
}
}
while (!(Endpoint_IsOUTReceived()))
{
uint8_t USB_DeviceState_LCL = USB_DeviceState;
if (USB_DeviceState_LCL == DEVICE_STATE_Unattached)
return ENDPOINT_RWCSTREAM_DeviceDisconnected;
else if (USB_DeviceState_LCL == DEVICE_STATE_Suspended)
return ENDPOINT_RWCSTREAM_BusSuspended;
else if (Endpoint_IsSETUPReceived())
return ENDPOINT_RWCSTREAM_HostAborted;
}
return ENDPOINT_RWCSTREAM_NoError;
}
#undef TEMPLATE_BUFFER_OFFSET
#undef TEMPLATE_BUFFER_MOVE
#undef TEMPLATE_FUNC_NAME
#undef TEMPLATE_TRANSFER_BYTE
#endif

View file

@ -0,0 +1,89 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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.
*/
#if defined(TEMPLATE_FUNC_NAME)
uint8_t TEMPLATE_FUNC_NAME (TEMPLATE_BUFFER_TYPE const Buffer,
uint16_t Length,
uint16_t* const BytesProcessed)
{
uint8_t* DataStream = ((uint8_t*)Buffer + TEMPLATE_BUFFER_OFFSET(Length));
uint16_t BytesInTransfer = 0;
uint8_t ErrorCode;
if ((ErrorCode = Endpoint_WaitUntilReady()))
return ErrorCode;
if (BytesProcessed != NULL)
{
Length -= *BytesProcessed;
TEMPLATE_BUFFER_MOVE(DataStream, *BytesProcessed);
}
while (Length)
{
if (!(Endpoint_IsReadWriteAllowed()))
{
TEMPLATE_CLEAR_ENDPOINT();
#if !defined(INTERRUPT_CONTROL_ENDPOINT)
USB_USBTask();
#endif
if (BytesProcessed != NULL)
{
*BytesProcessed += BytesInTransfer;
return ENDPOINT_RWSTREAM_IncompleteTransfer;
}
if ((ErrorCode = Endpoint_WaitUntilReady()))
return ErrorCode;
}
else
{
TEMPLATE_TRANSFER_BYTE(DataStream);
TEMPLATE_BUFFER_MOVE(DataStream, 1);
Length--;
BytesInTransfer++;
}
}
return ENDPOINT_RWSTREAM_NoError;
}
#undef TEMPLATE_FUNC_NAME
#undef TEMPLATE_BUFFER_TYPE
#undef TEMPLATE_TRANSFER_BYTE
#undef TEMPLATE_CLEAR_ENDPOINT
#undef TEMPLATE_BUFFER_OFFSET
#undef TEMPLATE_BUFFER_MOVE
#endif

View file

@ -0,0 +1,88 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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.
*/
#if defined(TEMPLATE_FUNC_NAME)
uint8_t TEMPLATE_FUNC_NAME (TEMPLATE_BUFFER_TYPE const Buffer,
uint16_t Length,
uint16_t* const BytesProcessed)
{
uint8_t* DataStream = ((uint8_t*)Buffer + TEMPLATE_BUFFER_OFFSET(Length));
uint16_t BytesInTransfer = 0;
uint8_t ErrorCode;
Pipe_SetPipeToken(TEMPLATE_TOKEN);
if ((ErrorCode = Pipe_WaitUntilReady()))
return ErrorCode;
if (BytesProcessed != NULL)
{
Length -= *BytesProcessed;
TEMPLATE_BUFFER_MOVE(DataStream, *BytesProcessed);
}
while (Length)
{
if (!(Pipe_IsReadWriteAllowed()))
{
TEMPLATE_CLEAR_PIPE();
if (BytesProcessed != NULL)
{
*BytesProcessed += BytesInTransfer;
return PIPE_RWSTREAM_IncompleteTransfer;
}
if ((ErrorCode = Pipe_WaitUntilReady()))
return ErrorCode;
}
else
{
TEMPLATE_TRANSFER_BYTE(DataStream);
TEMPLATE_BUFFER_MOVE(DataStream, 1);
Length--;
BytesInTransfer++;
}
}
return PIPE_RWSTREAM_NoError;
}
#undef TEMPLATE_FUNC_NAME
#undef TEMPLATE_BUFFER_TYPE
#undef TEMPLATE_TOKEN
#undef TEMPLATE_TRANSFER_BYTE
#undef TEMPLATE_CLEAR_PIPE
#undef TEMPLATE_BUFFER_OFFSET
#undef TEMPLATE_BUFFER_MOVE
#endif

View file

@ -0,0 +1,222 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
#include "../../../../Common/Common.h"
#if (ARCH == ARCH_UC3)
#define __INCLUDE_FROM_USB_DRIVER
#define __INCLUDE_FROM_USB_CONTROLLER_C
#include "../USBController.h"
#if defined(USB_CAN_BE_BOTH)
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 defined(USB_CAN_BE_BOTH)
if (Mode == USB_MODE_UID)
{
AVR32_USBB.USBCON.uide = true;
USB_INT_Enable(USB_INT_IDTI);
USB_CurrentMode = USB_GetUSBModeFromUID();
}
else
{
AVR32_USBB.USBCON.uide = false;
USB_CurrentMode = Mode;
}
#else
AVR32_USBB.USBCON.uide = false;
#endif
USB_IsInitialized = true;
USB_ResetInterface();
}
void USB_Disable(void)
{
USB_INT_DisableAllInterrupts();
USB_INT_ClearAllInterrupts();
USB_Detach();
USB_Controller_Disable();
USB_OTGPAD_Off();
#if defined(USB_CAN_BE_BOTH)
USB_CurrentMode = USB_MODE_None;
#endif
AVR32_PM.GCCTRL[3].cen = false;
USB_IsInitialized = false;
}
void USB_ResetInterface(void)
{
#if defined(USB_CAN_BE_BOTH)
bool UIDModeSelectEnabled = AVR32_USBB.USBCON.uide;
#endif
AVR32_PM.GCCTRL[AVR32_PM_GCLK_USBB].pllsel = !(USB_Options & USB_OPT_GCLK_SRC_OSC);
AVR32_PM.GCCTRL[AVR32_PM_GCLK_USBB].oscsel = !(USB_Options & USB_OPT_GCLK_CHANNEL_0);
AVR32_PM.GCCTRL[AVR32_PM_GCLK_USBB].diven = (F_USB != USB_CLOCK_REQUIRED_FREQ);
AVR32_PM.GCCTRL[AVR32_PM_GCLK_USBB].div = (F_USB == USB_CLOCK_REQUIRED_FREQ) ? 0 : (uint32_t)((F_USB / USB_CLOCK_REQUIRED_FREQ / 2) - 1);
AVR32_PM.GCCTRL[AVR32_PM_GCLK_USBB].cen = true;
USB_INT_DisableAllInterrupts();
USB_INT_ClearAllInterrupts();
USB_Controller_Reset();
#if defined(USB_CAN_BE_BOTH)
if (UIDModeSelectEnabled)
USB_INT_Enable(USB_INT_IDTI);
#endif
USB_CLK_Unfreeze();
if (USB_CurrentMode == USB_MODE_Device)
{
#if defined(USB_CAN_BE_DEVICE)
AVR32_USBB.USBCON.uimod = true;
USB_Init_Device();
#endif
}
else if (USB_CurrentMode == USB_MODE_Host)
{
#if defined(INVERTED_VBUS_ENABLE_LINE)
AVR32_USBB.USBCON.vbuspo = true;
#endif
#if defined(USB_CAN_BE_HOST)
AVR32_USBB.USBCON.uimod = false;
USB_Init_Host();
#endif
}
USB_OTGPAD_On();
}
#if defined(USB_CAN_BE_DEVICE)
static void USB_Init_Device(void)
{
USB_DeviceState = DEVICE_STATE_Unattached;
USB_Device_ConfigurationNumber = 0;
#if !defined(NO_DEVICE_REMOTE_WAKEUP)
USB_Device_RemoteWakeupEnabled = false;
#endif
#if !defined(NO_DEVICE_SELF_POWER)
USB_Device_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)
USB_Device_ControlEndpointSize = DeviceDescriptorPtr->Endpoint0Size;
#endif
if (USB_Options & USB_DEVICE_OPT_LOWSPEED)
{
USB_Device_SetLowSpeed();
}
else
{
#if defined(USB_DEVICE_OPT_HIGHSPEED)
if (USB_Options & USB_DEVICE_OPT_HIGHSPEED)
USB_Device_SetHighSpeed();
else
USB_Device_SetFullSpeed();
#else
USB_Device_SetFullSpeed();
#endif
}
USB_INT_Enable(USB_INT_VBUSTI);
Endpoint_ConfigureEndpoint(ENDPOINT_CONTROLEP, EP_TYPE_CONTROL,
USB_Device_ControlEndpointSize, 1);
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_Host_ConfigurationNumber = 0;
USB_Host_ControlPipeSize = PIPE_CONTROLPIPE_DEFAULT_SIZE;
USB_Host_HostMode_On();
USB_Host_VBUS_Auto_On();
USB_INT_Enable(USB_INT_DCONNI);
USB_INT_Enable(USB_INT_BCERRI);
USB_Attach();
}
#endif
#endif

View file

@ -0,0 +1,353 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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 definitions for the AVR32 UC3 microcontrollers.
* \copydetails Group_USBManagement_UC3
*
* \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_USBManagement
* \defgroup Group_USBManagement_UC3 USB Interface Management (UC3)
* \brief USB Controller definitions for the AVR32 UC3 microcontrollers.
*
* Functions, macros, variables, enums and types related to the setup and management of the USB interface.
*
* @{
*/
#ifndef __USBCONTROLLER_UC3_H__
#define __USBCONTROLLER_UC3_H__
/* Includes: */
#include "../../../../Common/Common.h"
#include "../USBMode.h"
#include "../Events.h"
#include "../USBTask.h"
#include "../USBInterrupt.h"
#if defined(USB_CAN_BE_HOST) || defined(__DOXYGEN__)
#include "../Host.h"
#include "../OTG.h"
#include "../Pipe.h"
#include "../HostStandardReq.h"
#include "../PipeStream.h"
#endif
#if defined(USB_CAN_BE_DEVICE) || defined(__DOXYGEN__)
#include "../Device.h"
#include "../Endpoint.h"
#include "../DeviceStandardReq.h"
#include "../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_USB)
#error F_USB is not defined. You must define F_USB to the frequency of the clock input to the USB module.
#endif
#if (defined(USB_SERIES_UC3A3_AVR) || defined(USB_SERIES_UC3A4_AVR))
#if ((F_USB < 12000000) || (F_USB % 12000000))
#error Invalid F_USB specified. F_USB must be a multiple of 12MHz for UC3A3 and UC3A4 devices.
#endif
#else
#if ((F_USB < 48000000) || (F_USB % 48000000))
#error Invalid F_USB specified. F_USB must be a multiple of 48MHz for UC3A and UC3B devices.
#endif
#endif
/* Public Interface - May be used in end-application: */
/* Macros: */
/** \name USB Controller Option Masks */
//@{
/** Selects one of the system's main clock oscillators as the input clock to the USB Generic Clock source
* generation module. This indicates that an external oscillator should be used directly instead of an
* internal PLL clock source.
*/
#define USB_OPT_GCLK_SRC_OSC (1 << 2)
/** Selects one of the system's PLL oscillators as the input clock to the USB Generic Clock source
* generation module. This indicates that one of the device's PLL outputs should be used instead of an
* external oscillator source.
*/
#define USB_OPT_GCLK_SRC_PLL (0 << 2)
/** Selects PLL or External Oscillator 0 as the USB Generic Clock source module input clock. */
#define USB_OPT_GCLK_CHANNEL_0 (1 << 3)
/** Selects PLL or External Oscillator 1 as the USB Generic Clock source module input clock. */
#define USB_OPT_GCLK_CHANNEL_1 (0 << 3)
//@}
#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: */
/** Determines if the VBUS line is currently high (i.e. the USB host is supplying power).
*
* \return Boolean \c true if the VBUS line is currently detecting power from a host, \c false otherwise.
*/
static inline bool USB_VBUS_GetStatus(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool USB_VBUS_GetStatus(void)
{
return AVR32_USBB.USBSTA.vbus;
}
/** 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)
{
AVR32_USBB.UDCON.detach = true;
}
/** 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)
{
AVR32_USBB.UDCON.detach = false;
}
/* 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 Mask indicating what mode the USB interface is to be initialized to, a value
* from the \ref USB_Modes_t enum.
* \note This parameter does not exist on devices with only one supported USB
* mode (device or host).
*
* \param[in] Options Mask indicating the options which should be used when initializing the USB
* interface to control the USB interface's behavior. This should be comprised of
* a \c USB_OPT_REG_* mask to control the regulator, a \c USB_OPT_*_PLL mask to control the
* PLL, and a \c 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 \c USB_DEVICE_ONLY
* (for device mode) or \c 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 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 \c 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.
*
* \see \ref Group_Device for the \c 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_Disable(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_CAN_BE_BOTH) || defined(__DOXYGEN__)
/** Indicates the mode that the USB interface is currently initialized to, a value from the
* \ref USB_Modes_t enum.
*
* \attention This variable should be treated as read-only in the user application, and never manually
* changed in value.
*
* \note When the controller is initialized into UID auto-detection 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 \c USB_DEVICE_ONLY or \c 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_CAN_BE_HOST)
#define USB_CurrentMode USB_MODE_Host
#elif defined(USB_CAN_BE_DEVICE)
#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 \c USB_MODE_* masks defined elsewhere in this module.
*
* \attention 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
/* Private Interface - For use in library only: */
#if !defined(__DOXYGEN__)
/* Macros: */
#if defined(USB_SERIES_UC3A3_AVR32) || defined(USB_SERIES_UC3A4_AVR32)
#define USB_CLOCK_REQUIRED_FREQ 12000000UL
#else
#define USB_CLOCK_REQUIRED_FREQ 48000000UL
#endif
/* 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_OTGPAD_On(void) ATTR_ALWAYS_INLINE;
static inline void USB_OTGPAD_On(void)
{
AVR32_USBB.USBCON.otgpade = true;
}
static inline void USB_OTGPAD_Off(void) ATTR_ALWAYS_INLINE;
static inline void USB_OTGPAD_Off(void)
{
AVR32_USBB.USBCON.otgpade = false;
}
static inline void USB_CLK_Freeze(void) ATTR_ALWAYS_INLINE;
static inline void USB_CLK_Freeze(void)
{
AVR32_USBB.USBCON.frzclk = true;
}
static inline void USB_CLK_Unfreeze(void) ATTR_ALWAYS_INLINE;
static inline void USB_CLK_Unfreeze(void)
{
AVR32_USBB.USBCON.frzclk = false;
}
static inline void USB_Controller_Enable(void) ATTR_ALWAYS_INLINE;
static inline void USB_Controller_Enable(void)
{
AVR32_USBB.USBCON.usbe = true;
}
static inline void USB_Controller_Disable(void) ATTR_ALWAYS_INLINE;
static inline void USB_Controller_Disable(void)
{
AVR32_USBB.USBCON.usbe = false;
}
static inline void USB_Controller_Reset(void) ATTR_ALWAYS_INLINE;
static inline void USB_Controller_Reset(void)
{
AVR32_USBB.USBCON.usbe = false;
AVR32_USBB.USBCON.usbe = true;
}
#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 (AVR32_USBB.USBSTA.id)
return USB_MODE_Device;
else
return USB_MODE_Host;
}
#endif
#endif
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,228 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
#include "../../../../Common/Common.h"
#if (ARCH == ARCH_UC3)
#define __INCLUDE_FROM_USB_DRIVER
#include "../USBInterrupt.h"
void USB_INT_DisableAllInterrupts(void)
{
AVR32_USBB.USBCON.vbuste = false;
AVR32_USBB.USBCON.idte = false;
AVR32_USBB.uhinteclr = -1;
AVR32_USBB.udinteclr = -1;
}
void USB_INT_ClearAllInterrupts(void)
{
AVR32_USBB.USBSTACLR.vbustic = true;
AVR32_USBB.USBSTACLR.idtic = true;
AVR32_USBB.uhintclr = -1;
AVR32_USBB.udintclr = -1;
}
ISR(USB_GEN_vect)
{
#if defined(USB_CAN_BE_DEVICE)
#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
if (USB_INT_HasOccurred(USB_INT_VBUSTI) && USB_INT_IsEnabled(USB_INT_VBUSTI))
{
USB_INT_Clear(USB_INT_VBUSTI);
if (USB_VBUS_GetStatus())
{
USB_DeviceState = DEVICE_STATE_Powered;
EVENT_USB_Device_Connect();
}
else
{
USB_DeviceState = DEVICE_STATE_Unattached;
EVENT_USB_Device_Disconnect();
}
}
if (USB_INT_HasOccurred(USB_INT_SUSPI) && USB_INT_IsEnabled(USB_INT_SUSPI))
{
USB_INT_Disable(USB_INT_SUSPI);
USB_INT_Enable(USB_INT_WAKEUPI);
USB_CLK_Freeze();
USB_DeviceState = DEVICE_STATE_Suspended;
EVENT_USB_Device_Suspend();
}
if (USB_INT_HasOccurred(USB_INT_WAKEUPI) && USB_INT_IsEnabled(USB_INT_WAKEUPI))
{
USB_CLK_Unfreeze();
USB_INT_Clear(USB_INT_WAKEUPI);
USB_INT_Disable(USB_INT_WAKEUPI);
USB_INT_Enable(USB_INT_SUSPI);
if (USB_Device_ConfigurationNumber)
USB_DeviceState = DEVICE_STATE_Configured;
else
USB_DeviceState = (USB_Device_IsAddressSet()) ? DEVICE_STATE_Addressed : DEVICE_STATE_Powered;
EVENT_USB_Device_WakeUp();
}
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_Device_ConfigurationNumber = 0;
USB_INT_Clear(USB_INT_SUSPI);
USB_INT_Disable(USB_INT_SUSPI);
USB_INT_Enable(USB_INT_WAKEUPI);
USB_Device_SetDeviceAddress(0);
Endpoint_ConfigureEndpoint(ENDPOINT_CONTROLEP, EP_TYPE_CONTROL,
USB_Device_ControlEndpointSize, 1);
#if defined(INTERRUPT_CONTROL_ENDPOINT)
USB_INT_Enable(USB_INT_RXSTPI);
#endif
EVENT_USB_Device_Reset();
}
#endif
#if defined(USB_CAN_BE_HOST)
#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
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_DCONNI) && USB_INT_IsEnabled(USB_INT_DCONNI))
{
USB_INT_Clear(USB_INT_DCONNI);
USB_INT_Disable(USB_INT_DCONNI);
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();
}
#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)
{
uint8_t PrevSelectedEndpoint = Endpoint_GetCurrentEndpoint();
Endpoint_SelectEndpoint(ENDPOINT_CONTROLEP);
USB_INT_Disable(USB_INT_RXSTPI);
GlobalInterruptEnable();
USB_Device_ProcessControlRequest();
Endpoint_SelectEndpoint(ENDPOINT_CONTROLEP);
USB_INT_Enable(USB_INT_RXSTPI);
Endpoint_SelectEndpoint(PrevSelectedEndpoint);
}
#endif
#endif

View file

@ -0,0 +1,376 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 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 disclaims 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 definitions for the AVR32 UC3 microcontrollers.
*
* 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_UC3_H__
#define __USBINTERRUPT_UC3_H__
/* Includes: */
#include "../../../../Common/Common.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__)
/* External Variables: */
extern volatile uint32_t USB_Endpoint_SelectedEndpoint;
/* Enums: */
enum USB_Interrupts_t
{
USB_INT_VBUSTI = 0,
#if (defined(USB_CAN_BE_BOTH) || defined(__DOXYGEN__))
USB_INT_IDTI = 1,
#endif
#if (defined(USB_CAN_BE_DEVICE) || defined(__DOXYGEN__))
USB_INT_WAKEUPI = 2,
USB_INT_SUSPI = 3,
USB_INT_EORSTI = 4,
USB_INT_SOFI = 5,
USB_INT_RXSTPI = 6,
#endif
#if (defined(USB_CAN_BE_HOST) || defined(__DOXYGEN__))
USB_INT_HSOFI = 7,
USB_INT_DCONNI = 8,
USB_INT_DDISCI = 9,
USB_INT_RSTI = 10,
USB_INT_BCERRI = 11,
USB_INT_VBERRI = 12,
#endif
};
/* Inline Functions: */
static inline void USB_INT_Enable(const uint8_t Interrupt) ATTR_ALWAYS_INLINE;
static inline void USB_INT_Enable(const uint8_t Interrupt)
{
switch (Interrupt)
{
case USB_INT_VBUSTI:
AVR32_USBB.USBCON.vbuste = true;
break;
#if defined(USB_CAN_BE_BOTH)
case USB_INT_IDTI:
AVR32_USBB.USBCON.idte = true;
break;
#endif
#if defined(USB_CAN_BE_DEVICE)
case USB_INT_WAKEUPI:
AVR32_USBB.UDINTESET.wakeupes = true;
break;
case USB_INT_SUSPI:
AVR32_USBB.UDINTESET.suspes = true;
break;
case USB_INT_EORSTI:
AVR32_USBB.UDINTESET.eorstes = true;
break;
case USB_INT_SOFI:
AVR32_USBB.UDINTESET.sofes = true;
break;
case USB_INT_RXSTPI:
(&AVR32_USBB.UECON0SET)[USB_Endpoint_SelectedEndpoint].rxstpes = true;
break;
#endif
#if defined(USB_CAN_BE_HOST)
case USB_INT_HSOFI:
AVR32_USBB.UHINTESET.hsofies = true;
break;
case USB_INT_DCONNI:
AVR32_USBB.UHINTESET.dconnies = true;
break;
case USB_INT_DDISCI:
AVR32_USBB.UHINTESET.ddiscies = true;
break;
case USB_INT_RSTI:
AVR32_USBB.UHINTESET.rsties = true;
break;
case USB_INT_BCERRI:
AVR32_USBB.USBCON.bcerre = true;
break;
case USB_INT_VBERRI:
AVR32_USBB.USBCON.vberre = true;
break;
#endif
default:
break;
}
}
static inline void USB_INT_Disable(const uint8_t Interrupt) ATTR_ALWAYS_INLINE;
static inline void USB_INT_Disable(const uint8_t Interrupt)
{
switch (Interrupt)
{
case USB_INT_VBUSTI:
AVR32_USBB.USBCON.vbuste = false;
break;
#if defined(USB_CAN_BE_BOTH)
case USB_INT_IDTI:
AVR32_USBB.USBCON.idte = false;
break;
#endif
#if defined(USB_CAN_BE_DEVICE)
case USB_INT_WAKEUPI:
AVR32_USBB.UDINTECLR.wakeupec = true;
break;
case USB_INT_SUSPI:
AVR32_USBB.UDINTECLR.suspec = true;
break;
case USB_INT_EORSTI:
AVR32_USBB.UDINTECLR.eorstec = true;
break;
case USB_INT_SOFI:
AVR32_USBB.UDINTECLR.sofec = true;
break;
case USB_INT_RXSTPI:
(&AVR32_USBB.UECON0CLR)[USB_Endpoint_SelectedEndpoint].rxstpec = true;
break;
#endif
#if defined(USB_CAN_BE_HOST)
case USB_INT_HSOFI:
AVR32_USBB.UHINTECLR.hsofiec = true;
break;
case USB_INT_DCONNI:
AVR32_USBB.UHINTECLR.dconniec = true;
break;
case USB_INT_DDISCI:
AVR32_USBB.UHINTECLR.ddisciec = true;
break;
case USB_INT_RSTI:
AVR32_USBB.UHINTECLR.rstiec = true;
break;
case USB_INT_BCERRI:
AVR32_USBB.USBCON.bcerre = false;
break;
case USB_INT_VBERRI:
AVR32_USBB.USBCON.vberre = false;
break;
#endif
default:
break;
}
}
static inline void USB_INT_Clear(const uint8_t Interrupt) ATTR_ALWAYS_INLINE;
static inline void USB_INT_Clear(const uint8_t Interrupt)
{
switch (Interrupt)
{
case USB_INT_VBUSTI:
AVR32_USBB.USBSTACLR.vbustic = true;
(void)AVR32_USBB.USBSTACLR;
break;
#if defined(USB_CAN_BE_BOTH)
case USB_INT_IDTI:
AVR32_USBB.USBSTACLR.idtic = true;
(void)AVR32_USBB.USBSTACLR;
break;
#endif
#if defined(USB_CAN_BE_DEVICE)
case USB_INT_WAKEUPI:
AVR32_USBB.UDINTCLR.wakeupc = true;
(void)AVR32_USBB.UDINTCLR;
break;
case USB_INT_SUSPI:
AVR32_USBB.UDINTCLR.suspc = true;
(void)AVR32_USBB.UDINTCLR;
break;
case USB_INT_EORSTI:
AVR32_USBB.UDINTCLR.eorstc = true;
(void)AVR32_USBB.UDINTCLR;
break;
case USB_INT_SOFI:
AVR32_USBB.UDINTCLR.sofc = true;
(void)AVR32_USBB.UDINTCLR;
break;
case USB_INT_RXSTPI:
(&AVR32_USBB.UESTA0CLR)[USB_Endpoint_SelectedEndpoint].rxstpic = true;
break;
#endif
#if defined(USB_CAN_BE_HOST)
case USB_INT_HSOFI:
AVR32_USBB.UHINTCLR.hsofic = true;
(void)AVR32_USBB.UHINTCLR;
break;
case USB_INT_DCONNI:
AVR32_USBB.UHINTCLR.dconnic = true;
(void)AVR32_USBB.UHINTCLR;
break;
case USB_INT_DDISCI:
AVR32_USBB.UHINTCLR.ddiscic = true;
(void)AVR32_USBB.UHINTCLR;
break;
case USB_INT_RSTI:
AVR32_USBB.UHINTCLR.rstic = true;
(void)AVR32_USBB.UHINTCLR;
break;
case USB_INT_BCERRI:
AVR32_USBB.USBSTACLR.bcerric = true;
(void)AVR32_USBB.USBSTACLR;
break;
case USB_INT_VBERRI:
AVR32_USBB.USBSTACLR.vberric = true;
(void)AVR32_USBB.USBSTACLR;
break;
#endif
default:
break;
}
}
static inline bool USB_INT_IsEnabled(const uint8_t Interrupt) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
static inline bool USB_INT_IsEnabled(const uint8_t Interrupt)
{
switch (Interrupt)
{
case USB_INT_VBUSTI:
return AVR32_USBB.USBCON.vbuste;
#if defined(USB_CAN_BE_BOTH)
case USB_INT_IDTI:
return AVR32_USBB.USBCON.idte;
#endif
#if defined(USB_CAN_BE_DEVICE)
case USB_INT_WAKEUPI:
return AVR32_USBB.UDINTE.wakeupe;
case USB_INT_SUSPI:
return AVR32_USBB.UDINTE.suspe;
case USB_INT_EORSTI:
return AVR32_USBB.UDINTE.eorste;
case USB_INT_SOFI:
return AVR32_USBB.UDINTE.sofe;
case USB_INT_RXSTPI:
return (&AVR32_USBB.UECON0)[USB_Endpoint_SelectedEndpoint].rxstpe;
#endif
#if defined(USB_CAN_BE_HOST)
case USB_INT_HSOFI:
return AVR32_USBB.UHINTE.hsofie;
case USB_INT_DCONNI:
return AVR32_USBB.UHINTE.dconnie;
case USB_INT_DDISCI:
return AVR32_USBB.UHINTE.ddiscie;
case USB_INT_RSTI:
return AVR32_USBB.UHINTE.rstie;
case USB_INT_BCERRI:
return AVR32_USBB.USBCON.bcerre;
case USB_INT_VBERRI:
return AVR32_USBB.USBCON.vberre;
#endif
default:
return false;
}
}
static inline bool USB_INT_HasOccurred(const uint8_t Interrupt) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
static inline bool USB_INT_HasOccurred(const uint8_t Interrupt)
{
switch (Interrupt)
{
case USB_INT_VBUSTI:
return AVR32_USBB.USBSTA.vbusti;
#if defined(USB_CAN_BE_BOTH)
case USB_INT_IDTI:
return AVR32_USBB.USBSTA.idti;
#endif
#if defined(USB_CAN_BE_DEVICE)
case USB_INT_WAKEUPI:
return AVR32_USBB.UDINT.wakeup;
case USB_INT_SUSPI:
return AVR32_USBB.UDINT.susp;
case USB_INT_EORSTI:
return AVR32_USBB.UDINT.eorst;
case USB_INT_SOFI:
return AVR32_USBB.UDINT.sof;
case USB_INT_RXSTPI:
return (&AVR32_USBB.UESTA0)[USB_Endpoint_SelectedEndpoint].rxstpi;
#endif
#if defined(USB_CAN_BE_HOST)
case USB_INT_HSOFI:
return AVR32_USBB.UHINT.hsofi;
case USB_INT_DCONNI:
return AVR32_USBB.UHINT.dconni;
case USB_INT_DDISCI:
return AVR32_USBB.UHINT.ddisci;
case USB_INT_RSTI:
return AVR32_USBB.UHINT.rsti;
case USB_INT_BCERRI:
return AVR32_USBB.USBSTA.bcerri;
case USB_INT_VBERRI:
return AVR32_USBB.USBSTA.vberri;
#endif
default:
return false;
}
}
/* Includes: */
#include "../USBMode.h"
#include "../Events.h"
#include "../USBController.h"
/* Function Prototypes: */
void USB_INT_ClearAllInterrupts(void);
void USB_INT_DisableAllInterrupts(void);
#endif
/* Public Interface - May be used in end-application: */
/* Function Prototypes: */
#if defined(__DOXYGEN__)
/** Interrupt service routine handler for the USB controller ISR group. This interrupt routine <b>must</b> be
* linked to the entire USB controller ISR vector group inside the AVR32's interrupt controller peripheral,
* using the user application's preferred USB controller driver.
*/
void USB_GEN_vect(void);
#else
ISR(USB_GEN_vect);
#endif
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif