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,57 @@
/*
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_AVR8)
#define __INCLUDE_FROM_USB_DRIVER
#include "../USBMode.h"
#if defined(USB_CAN_BE_DEVICE)
#include "../Device.h"
void USB_Device_SendRemoteWakeup(void)
{
if (!(USB_Options & USB_OPT_MANUAL_PLL))
{
USB_PLL_On();
while (!(USB_PLL_IsReady()));
}
USB_CLK_Unfreeze();
UDCON |= (1 << RMWKUP);
while (UDCON & (1 << RMWKUP));
}
#endif
#endif

View file

@ -0,0 +1,269 @@
/*
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 AVR8 microcontrollers.
* \copydetails Group_Device_AVR8
*
* \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_AVR8 Device Management (AVR8)
* \brief USB Device definitions for the AVR8 microcontrollers.
*
* Architecture specific USB Device definitions for the Atmel 8-bit AVR microcontrollers.
*
* @{
*/
#ifndef __USBDEVICE_AVR8_H__
#define __USBDEVICE_AVR8_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
#if (defined(USE_RAM_DESCRIPTORS) && defined(USE_EEPROM_DESCRIPTORS))
#error USE_RAM_DESCRIPTORS and USE_EEPROM_DESCRIPTORS are mutually exclusive.
#endif
#if (defined(USE_FLASH_DESCRIPTORS) && defined(USE_EEPROM_DESCRIPTORS))
#error USE_FLASH_DESCRIPTORS and USE_EEPROM_DESCRIPTORS are mutually exclusive.
#endif
#if (defined(USE_FLASH_DESCRIPTORS) && defined(USE_RAM_DESCRIPTORS))
#error USE_FLASH_DESCRIPTORS and USE_RAM_DESCRIPTORS are mutually exclusive.
#endif
/* Public Interface - May be used in end-application: */
/* Macros: */
/** \name USB Device Mode Option Masks */
//@{
#if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR) || defined(__DOXYGEN__)
/** Mask for the Options parameter of the \ref USB_Init() function. This indicates that the
* USB interface should be initialized in low speed (1.5Mb/s) mode.
*
* \note Low Speed mode is not available on all USB AVR models.
* \n
*
* \note Restrictions apply on the number, size and type of endpoints which can be used
* when running in low speed mode - please refer to the USB 2.0 specification.
*/
#define USB_DEVICE_OPT_LOWSPEED (1 << 0)
#endif
/** Mask for the Options parameter of the \ref USB_Init() function. This indicates that the
* USB interface should be initialized in full speed (12Mb/s) mode.
*/
#define USB_DEVICE_OPT_FULLSPEED (0 << 0)
//@}
#if (!defined(NO_INTERNAL_SERIAL) && \
(defined(USB_SERIES_7_AVR) || defined(USB_SERIES_6_AVR) || \
defined(USB_SERIES_4_AVR) || defined(USB_SERIES_2_AVR) || \
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 80
/** Start address of the internal serial number, in the appropriate address space, if present on the selected microcontroller
* model.
*/
#define INTERNAL_SERIAL_START_ADDRESS 0x0E
#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.
*
* \attention 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.
* \n\n
*
* \attention 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 UDFNUM;
}
#if !defined(NO_SOF_EVENTS)
/** Enables the device mode Start Of Frame events. When enabled, this causes the
* \ref EVENT_USB_Device_StartOfFrame() event to fire once per millisecond, synchronized to the USB bus,
* at the start of each USB frame when enumerated in device mode.
*
* \note This function is 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 This function is 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: */
#if defined(USB_DEVICE_OPT_LOWSPEED)
static inline void USB_Device_SetLowSpeed(void) ATTR_ALWAYS_INLINE;
static inline void USB_Device_SetLowSpeed(void)
{
UDCON |= (1 << LSM);
}
static inline void USB_Device_SetFullSpeed(void) ATTR_ALWAYS_INLINE;
static inline void USB_Device_SetFullSpeed(void)
{
UDCON &= ~(1 << LSM);
}
#endif
static inline void USB_Device_SetDeviceAddress(const uint8_t Address) ATTR_ALWAYS_INLINE;
static inline void USB_Device_SetDeviceAddress(const uint8_t Address)
{
UDADDR = (UDADDR & (1 << ADDEN)) | (Address & 0x7F);
}
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;
UDADDR |= (1 << ADDEN);
}
static inline bool USB_Device_IsAddressSet(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
static inline bool USB_Device_IsAddressSet(void)
{
return (UDADDR & (1 << 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 = INTERNAL_SERIAL_START_ADDRESS;
for (uint8_t SerialCharNum = 0; SerialCharNum < (INTERNAL_SERIAL_LENGTH_BITS / 4); SerialCharNum++)
{
uint8_t SerialByte = boot_signature_byte_get(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,275 @@
/*
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_AVR8)
#define __INCLUDE_FROM_USB_DRIVER
#include "../USBMode.h"
#if defined(USB_CAN_BE_DEVICE)
#include "EndpointStream_AVR8.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"
#if defined(ARCH_HAS_FLASH_ADDRESS_SPACE)
#define TEMPLATE_FUNC_NAME Endpoint_Write_Control_PStream_LE
#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_Control_W.c"
#define TEMPLATE_FUNC_NAME Endpoint_Write_Control_PStream_BE
#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_Control_W.c"
#endif
#if defined(ARCH_HAS_EEPROM_ADDRESS_SPACE)
#define TEMPLATE_FUNC_NAME Endpoint_Write_Control_EStream_LE
#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_Control_W.c"
#define TEMPLATE_FUNC_NAME Endpoint_Write_Control_EStream_BE
#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_Control_W.c"
#define TEMPLATE_FUNC_NAME Endpoint_Read_Control_EStream_LE
#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_Control_R.c"
#define TEMPLATE_FUNC_NAME Endpoint_Read_Control_EStream_BE
#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_Control_R.c"
#endif
#endif
#endif

View file

@ -0,0 +1,658 @@
/*
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 AVR8 microcontrollers.
* \copydetails Group_EndpointStreamRW_AVR8
*
* \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_AVR8 Read/Write of Multi-Byte Streams (AVR8)
* \brief Endpoint data stream transmission and reception management for the Atmel AVR8 architecture.
*
* Functions, macros, variables, enums and types related to data reading and writing of data streams from
* and to endpoints.
*
* @{
*/
#ifndef __ENDPOINT_STREAM_AVR8_H__
#define __ENDPOINT_STREAM_AVR8_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);
//@}
/** \name Stream functions for EEPROM source/destination data */
//@{
/** EEPROM buffer source version of \ref Endpoint_Write_Stream_LE().
*
* \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_EStream_LE(const void* const Buffer,
uint16_t Length,
uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
/** EEPROM buffer source version of \ref Endpoint_Write_Stream_BE().
*
* \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_EStream_BE(const void* const Buffer,
uint16_t Length,
uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
/** EEPROM buffer destination version of \ref Endpoint_Read_Stream_LE().
*
* \param[out] Buffer Pointer to the destination data buffer to write to, located in EEPROM memory space.
* \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_EStream_LE(void* const Buffer,
uint16_t Length,
uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
/** EEPROM buffer destination version of \ref Endpoint_Read_Stream_BE().
*
* \param[out] Buffer Pointer to the destination data buffer to write to, located in EEPROM memory space.
* \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_EStream_BE(void* const Buffer,
uint16_t Length,
uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
/** EEPROM buffer source version of Endpoint_Write_Control_Stream_LE.
*
* \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.
* \n\n
*
* \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_EStream_LE(const void* const Buffer,
uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
/** EEPROM buffer source version of \ref Endpoint_Write_Control_Stream_BE().
*
* \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.
* \n\n
*
* \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_EStream_BE(const void* const Buffer,
uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
/** EEPROM buffer source version of \ref Endpoint_Read_Control_Stream_LE().
*
* \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.
* \n\n
*
* \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_EStream_LE(void* const Buffer,
uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
/** EEPROM buffer source version of \ref Endpoint_Read_Control_Stream_BE().
*
* \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.
* \n\n
*
* \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_EStream_BE(void* const Buffer,
uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
//@}
/** \name Stream functions for PROGMEM source/destination data */
//@{
/** FLASH buffer source version of \ref Endpoint_Write_Stream_LE().
*
* \pre The FLASH data must be located in the first 64KB of FLASH for this function to work correctly.
*
* \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_PStream_LE(const void* const Buffer,
uint16_t Length,
uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
/** FLASH buffer source version of \ref Endpoint_Write_Stream_BE().
*
* \pre The FLASH data must be located in the first 64KB of FLASH for this function to work correctly.
*
* \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_PStream_BE(const void* const Buffer,
uint16_t Length,
uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
/** FLASH buffer source version of \ref Endpoint_Write_Control_Stream_LE().
*
* \pre The FLASH data must be located in the first 64KB of FLASH for this function to work correctly.
*
* \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.
* \n\n
*
* \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_PStream_LE(const void* const Buffer,
uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
/** FLASH buffer source version of \ref Endpoint_Write_Control_Stream_BE().
*
* \pre The FLASH data must be located in the first 64KB of FLASH for this function to work correctly.
*
* \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.
* \n\n
*
* \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_PStream_BE(const 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,201 @@
/*
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_AVR8)
#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
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 uint8_t UECFG0XData,
const uint8_t UECFG1XData)
{
#if defined(CONTROL_ONLY_DEVICE) || defined(ORDERED_EP_CONFIG)
Endpoint_SelectEndpoint(Number);
Endpoint_EnableEndpoint();
UECFG1X = 0;
UECFG0X = UECFG0XData;
UECFG1X = UECFG1XData;
return Endpoint_IsConfigured();
#else
for (uint8_t EPNum = Number; EPNum < ENDPOINT_TOTAL_ENDPOINTS; EPNum++)
{
uint8_t UECFG0XTemp;
uint8_t UECFG1XTemp;
uint8_t UEIENXTemp;
Endpoint_SelectEndpoint(EPNum);
if (EPNum == Number)
{
UECFG0XTemp = UECFG0XData;
UECFG1XTemp = UECFG1XData;
UEIENXTemp = 0;
}
else
{
UECFG0XTemp = UECFG0X;
UECFG1XTemp = UECFG1X;
UEIENXTemp = UEIENX;
}
if (!(UECFG1XTemp & (1 << ALLOC)))
continue;
Endpoint_DisableEndpoint();
UECFG1X &= ~(1 << ALLOC);
Endpoint_EnableEndpoint();
UECFG0X = UECFG0XTemp;
UECFG1X = UECFG1XTemp;
UEIENX = UEIENXTemp;
if (!(Endpoint_IsConfigured()))
return false;
}
Endpoint_SelectEndpoint(Number);
return true;
#endif
}
void Endpoint_ClearEndpoints(void)
{
UEINT = 0;
for (uint8_t EPNum = 0; EPNum < ENDPOINT_TOTAL_ENDPOINTS; EPNum++)
{
Endpoint_SelectEndpoint(EPNum);
UEIENX = 0;
UEINTX = 0;
UECFG1X = 0;
Endpoint_DisableEndpoint();
}
}
void Endpoint_ClearStatusStage(void)
{
if (USB_ControlRequest.bmRequestType & REQDIR_DEVICETOHOST)
{
while (!(Endpoint_IsOUTReceived()))
{
if (USB_DeviceState == DEVICE_STATE_Unattached)
return;
}
Endpoint_ClearOUT();
}
else
{
while (!(Endpoint_IsINReady()))
{
if (USB_DeviceState == DEVICE_STATE_Unattached)
return;
}
Endpoint_ClearIN();
}
}
#if !defined(CONTROL_ONLY_DEVICE)
uint8_t Endpoint_WaitUntilReady(void)
{
#if (USB_STREAM_TIMEOUT_MS < 0xFF)
uint8_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS;
#else
uint16_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS;
#endif
uint16_t PreviousFrameNumber = USB_Device_GetFrameNumber();
for (;;)
{
if (Endpoint_GetEndpointDirection() == ENDPOINT_DIR_IN)
{
if (Endpoint_IsINReady())
return ENDPOINT_READYWAIT_NoError;
}
else
{
if (Endpoint_IsOUTReceived())
return ENDPOINT_READYWAIT_NoError;
}
uint8_t USB_DeviceState_LCL = USB_DeviceState;
if (USB_DeviceState_LCL == DEVICE_STATE_Unattached)
return ENDPOINT_READYWAIT_DeviceDisconnected;
else if (USB_DeviceState_LCL == DEVICE_STATE_Suspended)
return ENDPOINT_READYWAIT_BusSuspended;
else if (Endpoint_IsStalled())
return ENDPOINT_READYWAIT_EndpointStalled;
uint16_t CurrentFrameNumber = USB_Device_GetFrameNumber();
if (CurrentFrameNumber != PreviousFrameNumber)
{
PreviousFrameNumber = CurrentFrameNumber;
if (!(TimeoutMSRem--))
return ENDPOINT_READYWAIT_Timeout;
}
}
}
#endif
#endif
#endif

View file

@ -0,0 +1,819 @@
/*
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 AVR8 microcontrollers.
* \copydetails Group_EndpointManagement_AVR8
*
* \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_AVR8 Endpoint Data Reading and Writing (AVR8)
* \brief Endpoint data read/write definitions for the Atmel AVR8 architecture.
*
* Functions, macros, variables, enums and types related to data reading and writing from and to endpoints.
*/
/** \ingroup Group_EndpointPrimitiveRW
* \defgroup Group_EndpointPrimitiveRW_AVR8 Read/Write of Primitive Data Types (AVR8)
* \brief Endpoint primitive read/write definitions for the Atmel AVR8 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_AVR8 Endpoint Packet Management (AVR8)
* \brief Endpoint packet management definitions for the Atmel AVR8 architecture.
*
* Functions, macros, variables, enums and types related to packet management of endpoints.
*/
/** \ingroup Group_EndpointManagement
* \defgroup Group_EndpointManagement_AVR8 Endpoint Management (AVR8)
* \brief Endpoint management definitions for the Atmel AVR8 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_AVR8_H__
#define __ENDPOINT_AVR8_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__)
/* Inline Functions: */
static inline uint8_t Endpoint_BytesToEPSizeMask(const uint16_t Bytes) ATTR_WARN_UNUSED_RESULT ATTR_CONST
ATTR_ALWAYS_INLINE;
static inline uint8_t Endpoint_BytesToEPSizeMask(const uint16_t Bytes)
{
uint8_t MaskVal = 0;
uint16_t CheckBytes = 8;
while (CheckBytes < Bytes)
{
MaskVal++;
CheckBytes <<= 1;
}
return (MaskVal << EPSIZE0);
}
/* Function Prototypes: */
void Endpoint_ClearEndpoints(void);
bool Endpoint_ConfigureEndpoint_Prv(const uint8_t Number,
const uint8_t UECFG0XData,
const uint8_t UECFG1XData);
#endif
/* Public Interface - May be used in end-application: */
/* Macros: */
#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_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR) || defined(__DOXYGEN__)
/** Total number of endpoints (including the default control endpoint at address 0) which may
* be used in the device. Different USB AVR models support different amounts of endpoints,
* this value reflects the maximum number of endpoints for the currently selected AVR model.
*/
#define ENDPOINT_TOTAL_ENDPOINTS 7
#else
#define ENDPOINT_TOTAL_ENDPOINTS 5
#endif
#else
#define ENDPOINT_TOTAL_ENDPOINTS 1
#endif
/* Enums: */
/** Enum for the possible error return codes of the \ref Endpoint_WaitUntilReady() function.
*
* \ingroup Group_EndpointRW_AVR8
*/
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 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 - please
* 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,
((Type << EPTYPE0) | ((Address & ENDPOINT_DIR_IN) ? (1 << EPDIR) : 0)),
((1 << ALLOC) | ((Banks > 1) ? (1 << EPBK0) : 0) | Endpoint_BytesToEPSizeMask(Size)));
}
/** Indicates the number of bytes currently stored in the current endpoint's selected bank.
*
* \ingroup Group_EndpointRW_AVR8
*
* \return Total number of bytes in the currently selected Endpoint's FIFO buffer.
*/
static inline uint16_t Endpoint_BytesInEndpoint(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline uint16_t Endpoint_BytesInEndpoint(void)
{
#if (defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR))
return UEBCX;
#elif defined(USB_SERIES_4_AVR)
return (((uint16_t)UEBCHX << 8) | UEBCLX);
#elif defined(USB_SERIES_2_AVR)
return UEBCLX;
#endif
}
/** Determines the currently selected endpoint's direction.
*
* \return The currently selected endpoint's direction, as a \c ENDPOINT_DIR_* mask.
*/
static inline uint8_t Endpoint_GetEndpointDirection(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline uint8_t Endpoint_GetEndpointDirection(void)
{
return (UECFG0X & (1 << 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)
{
#if !defined(CONTROL_ONLY_DEVICE)
return ((UENUM & ENDPOINT_EPNUM_MASK) | Endpoint_GetEndpointDirection());
#else
return ENDPOINT_CONTROLEP;
#endif
}
/** 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)
{
#if !defined(CONTROL_ONLY_DEVICE)
UENUM = (Address & ENDPOINT_EPNUM_MASK);
#endif
}
/** 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 address 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)
{
UERST = (1 << (Address & ENDPOINT_EPNUM_MASK));
UERST = 0;
}
/** Enables the currently selected endpoint so that data can be sent and received through it to
* and from a host.
*
* \note Endpoints must first be configured properly via \ref Endpoint_ConfigureEndpoint().
*/
static inline void Endpoint_EnableEndpoint(void) ATTR_ALWAYS_INLINE;
static inline void Endpoint_EnableEndpoint(void)
{
UECONX |= (1 << EPEN);
}
/** Disables the currently selected endpoint so that data cannot be sent and received through it
* to and from a host.
*/
static inline void Endpoint_DisableEndpoint(void) ATTR_ALWAYS_INLINE;
static inline void Endpoint_DisableEndpoint(void)
{
UECONX &= ~(1 << EPEN);
}
/** Determines if the currently selected endpoint is enabled, but not necessarily configured.
*
* \return Boolean \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 ((UECONX & (1 << EPEN)) ? 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 acknowledgment via the
* \ref Endpoint_ClearOUT() command.
*
* \ingroup Group_EndpointPacketManagement_AVR8
*
* \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 (UESTA0X & (0x03 << NBUSYBK0));
}
/** 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_AVR8
*/
static inline void Endpoint_AbortPendingIN(void)
{
while (Endpoint_GetBusyBanks() != 0)
{
UEINTX |= (1 << RXOUTI);
while (UEINTX & (1 << RXOUTI));
}
}
/** 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_AVR8
*
* \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 ((UEINTX & (1 << RWAL)) ? true : false);
}
/** 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 ((UESTA0X & (1 << CFGOK)) ? true : false);
}
/** Returns a mask indicating which INTERRUPT type endpoints have interrupted - i.e. their
* interrupt duration has elapsed. Which endpoints have interrupted can be determined by
* masking the return value against <tt>(1 << <i>{Endpoint Number}</i>)</tt>.
*
* \return Mask whose bits indicate which endpoints have interrupted.
*/
static inline uint8_t Endpoint_GetEndpointInterrupts(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline uint8_t Endpoint_GetEndpointInterrupts(void)
{
return UEINT;
}
/** Determines if the specified endpoint number has interrupted (valid only for INTERRUPT type
* endpoints).
*
* \param[in] 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() & (1 << (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_AVR8
*
* \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 ((UEINTX & (1 << TXINI)) ? true : false);
}
/** Determines if the selected OUT endpoint has received new packet from the host.
*
* \ingroup Group_EndpointPacketManagement_AVR8
*
* \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 ((UEINTX & (1 << RXOUTI)) ? true : false);
}
/** Determines if the current CONTROL type endpoint has received a SETUP packet.
*
* \ingroup Group_EndpointPacketManagement_AVR8
*
* \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 ((UEINTX & (1 << RXSTPI)) ? true : false);
}
/** Clears a received SETUP packet on the currently selected CONTROL type endpoint, freeing up the
* endpoint for the next packet.
*
* \ingroup Group_EndpointPacketManagement_AVR8
*
* \note This is not applicable for non CONTROL type endpoints.
*/
static inline void Endpoint_ClearSETUP(void) ATTR_ALWAYS_INLINE;
static inline void Endpoint_ClearSETUP(void)
{
UEINTX &= ~(1 << RXSTPI);
}
/** Sends an IN packet to the host on the currently selected endpoint, freeing up the endpoint for the
* next packet and switching to the alternative endpoint bank if double banked.
*
* \ingroup Group_EndpointPacketManagement_AVR8
*/
static inline void Endpoint_ClearIN(void) ATTR_ALWAYS_INLINE;
static inline void Endpoint_ClearIN(void)
{
#if !defined(CONTROL_ONLY_DEVICE)
UEINTX &= ~((1 << TXINI) | (1 << FIFOCON));
#else
UEINTX &= ~(1 << TXINI);
#endif
}
/** Acknowledges an OUT packet to the host on the currently selected endpoint, freeing up the endpoint
* for the next packet and switching to the alternative endpoint bank if double banked.
*
* \ingroup Group_EndpointPacketManagement_AVR8
*/
static inline void Endpoint_ClearOUT(void) ATTR_ALWAYS_INLINE;
static inline void Endpoint_ClearOUT(void)
{
#if !defined(CONTROL_ONLY_DEVICE)
UEINTX &= ~((1 << RXOUTI) | (1 << FIFOCON));
#else
UEINTX &= ~(1 << RXOUTI);
#endif
}
/** Stalls the current endpoint, indicating to the host that a logical problem occurred with the
* indicated endpoint and that the current transfer sequence should be aborted. This provides a
* way for devices to indicate invalid commands to the host so that the current transfer can be
* aborted and the host can begin its own recovery sequence.
*
* The currently selected endpoint remains stalled until either the \ref Endpoint_ClearStall() macro
* is called, or the host issues a CLEAR FEATURE request to the device for the currently selected
* endpoint.
*
* \ingroup Group_EndpointPacketManagement_AVR8
*/
static inline void Endpoint_StallTransaction(void) ATTR_ALWAYS_INLINE;
static inline void Endpoint_StallTransaction(void)
{
UECONX |= (1 << STALLRQ);
}
/** Clears the STALL condition on the currently selected endpoint.
*
* \ingroup Group_EndpointPacketManagement_AVR8
*/
static inline void Endpoint_ClearStall(void) ATTR_ALWAYS_INLINE;
static inline void Endpoint_ClearStall(void)
{
UECONX |= (1 << STALLRQC);
}
/** Determines if the currently selected endpoint is stalled, \c false otherwise.
*
* \ingroup Group_EndpointPacketManagement_AVR8
*
* \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 ((UECONX & (1 << STALLRQ)) ? true : false);
}
/** Resets the data toggle of the currently selected endpoint. */
static inline void Endpoint_ResetDataToggle(void) ATTR_ALWAYS_INLINE;
static inline void Endpoint_ResetDataToggle(void)
{
UECONX |= (1 << RSTDT);
}
/** 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 uint8_t DirectionMask) ATTR_ALWAYS_INLINE;
static inline void Endpoint_SetEndpointDirection(const uint8_t DirectionMask)
{
UECFG0X = ((UECFG0X & ~(1 << EPDIR)) | (DirectionMask ? (1 << EPDIR) : 0));
}
/** Reads one byte from the currently selected endpoint's bank, for OUT direction endpoints.
*
* \ingroup Group_EndpointPrimitiveRW_AVR8
*
* \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 UEDATX;
}
/** Writes one byte to the currently selected endpoint's bank, for IN direction endpoints.
*
* \ingroup Group_EndpointPrimitiveRW_AVR8
*
* \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)
{
UEDATX = Data;
}
/** Discards one byte from the currently selected endpoint's bank, for OUT direction endpoints.
*
* \ingroup Group_EndpointPrimitiveRW_AVR8
*/
static inline void Endpoint_Discard_8(void) ATTR_ALWAYS_INLINE;
static inline void Endpoint_Discard_8(void)
{
uint8_t Dummy;
Dummy = UEDATX;
(void)Dummy;
}
/** Reads two bytes from the currently selected endpoint's bank in little endian format, for OUT
* direction endpoints.
*
* \ingroup Group_EndpointPrimitiveRW_AVR8
*
* \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)
{
union
{
uint16_t Value;
uint8_t Bytes[2];
} Data;
Data.Bytes[0] = UEDATX;
Data.Bytes[1] = UEDATX;
return Data.Value;
}
/** Reads two bytes from the currently selected endpoint's bank in big endian format, for OUT
* direction endpoints.
*
* \ingroup Group_EndpointPrimitiveRW_AVR8
*
* \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)
{
union
{
uint16_t Value;
uint8_t Bytes[2];
} Data;
Data.Bytes[1] = UEDATX;
Data.Bytes[0] = UEDATX;
return Data.Value;
}
/** Writes two bytes to the currently selected endpoint's bank in little endian format, for IN
* direction endpoints.
*
* \ingroup Group_EndpointPrimitiveRW_AVR8
*
* \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)
{
UEDATX = (Data & 0xFF);
UEDATX = (Data >> 8);
}
/** Writes two bytes to the currently selected endpoint's bank in big endian format, for IN
* direction endpoints.
*
* \ingroup Group_EndpointPrimitiveRW_AVR8
*
* \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)
{
UEDATX = (Data >> 8);
UEDATX = (Data & 0xFF);
}
/** Discards two bytes from the currently selected endpoint's bank, for OUT direction endpoints.
*
* \ingroup Group_EndpointPrimitiveRW_AVR8
*/
static inline void Endpoint_Discard_16(void) ATTR_ALWAYS_INLINE;
static inline void Endpoint_Discard_16(void)
{
uint8_t Dummy;
Dummy = UEDATX;
Dummy = UEDATX;
(void)Dummy;
}
/** Reads four bytes from the currently selected endpoint's bank in little endian format, for OUT
* direction endpoints.
*
* \ingroup Group_EndpointPrimitiveRW_AVR8
*
* \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)
{
union
{
uint32_t Value;
uint8_t Bytes[4];
} Data;
Data.Bytes[0] = UEDATX;
Data.Bytes[1] = UEDATX;
Data.Bytes[2] = UEDATX;
Data.Bytes[3] = UEDATX;
return Data.Value;
}
/** Reads four bytes from the currently selected endpoint's bank in big endian format, for OUT
* direction endpoints.
*
* \ingroup Group_EndpointPrimitiveRW_AVR8
*
* \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)
{
union
{
uint32_t Value;
uint8_t Bytes[4];
} Data;
Data.Bytes[3] = UEDATX;
Data.Bytes[2] = UEDATX;
Data.Bytes[1] = UEDATX;
Data.Bytes[0] = UEDATX;
return Data.Value;
}
/** Writes four bytes to the currently selected endpoint's bank in little endian format, for IN
* direction endpoints.
*
* \ingroup Group_EndpointPrimitiveRW_AVR8
*
* \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)
{
UEDATX = (Data & 0xFF);
UEDATX = (Data >> 8);
UEDATX = (Data >> 16);
UEDATX = (Data >> 24);
}
/** Writes four bytes to the currently selected endpoint's bank in big endian format, for IN
* direction endpoints.
*
* \ingroup Group_EndpointPrimitiveRW_AVR8
*
* \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)
{
UEDATX = (Data >> 24);
UEDATX = (Data >> 16);
UEDATX = (Data >> 8);
UEDATX = (Data & 0xFF);
}
/** Discards four bytes from the currently selected endpoint's bank, for OUT direction endpoints.
*
* \ingroup Group_EndpointPrimitiveRW_AVR8
*/
static inline void Endpoint_Discard_32(void) ATTR_ALWAYS_INLINE;
static inline void Endpoint_Discard_32(void)
{
uint8_t Dummy;
Dummy = UEDATX;
Dummy = UEDATX;
Dummy = UEDATX;
Dummy = UEDATX;
(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_AVR8
*
* \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_AVR8)
#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,372 @@
/*
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 AVR8 microcontrollers.
* \copydetails Group_Host_AVR8
*
* \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_AVR8 Host Management (AVR8)
* \brief USB Host definitions for the AVR8 microcontrollers.
*
* Architecture specific USB Host definitions for the Atmel 8-bit AVR microcontrollers.
*
* @{
*/
#ifndef __USBHOST_AVR8_H__
#define __USBHOST_AVR8_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
#if defined(INVERTED_VBUS_ENABLE_LINE) && !defined(NO_AUTO_VBUS_MANAGEMENT)
#error The INVERTED_VBUS_ENABLE_LINE compile option requires NO_AUTO_VBUS_MANAGEMENT for the AVR8 architecture.
#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
/** 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 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)
{
UHCON |= (1 << RESET);
}
/** 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 ((UHCON & (1 << RESET)) ? false : true);
}
/** Resumes USB communications with an attached and enumerated device, by resuming the transmission
* of the 1MS Start Of Frame messages to the device. When resumed, USB communications between the
* host and attached device may occur.
*/
static inline void USB_Host_ResumeBus(void) ATTR_ALWAYS_INLINE;
static inline void USB_Host_ResumeBus(void)
{
UHCON |= (1 << SOFEN);
}
/** Suspends the USB bus, preventing any communications from occurring between the host and attached
* device until the bus has been resumed. This stops the transmission of the 1MS Start Of Frame
* messages to the device.
*
* \attention 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)
{
UHCON &= ~(1 << SOFEN);
}
/** Determines if the USB bus has been suspended via the use of the \ref USB_Host_SuspendBus() macro,
* false otherwise. While suspended, no USB communications can occur until the bus is resumed,
* except for the Remote Wakeup event from the device if supported.
*
* \return Boolean \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 ((UHCON & (1 << SOFEN)) ? false : true);
}
/** Determines if the attached device is currently enumerated in Full Speed mode (12Mb/s), or
* false if the attached device is enumerated in Low Speed mode (1.5Mb/s).
*
* \return Boolean \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 ((USBSTA & (1 << SPEED)) ? true : false);
}
/** Determines if the attached device is currently issuing a Remote Wakeup request, requesting
* that the host resume the USB bus and wake up the device, \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 ((UHINT & (1 << RXRSMI)) ? true : false);
}
/** Clears the flag indicating that a Remote Wakeup request has been issued by an attached device. */
static inline void USB_Host_ClearRemoteWakeupSent(void) ATTR_ALWAYS_INLINE;
static inline void USB_Host_ClearRemoteWakeupSent(void)
{
UHINT &= ~(1 << RXRSMI);
}
/** Accepts a Remote Wakeup request from an attached device. This must be issued in response to
* a device's Remote Wakeup request within 2ms for the request to be accepted and the bus to
* be resumed.
*/
static inline void USB_Host_ResumeFromWakeupRequest(void) ATTR_ALWAYS_INLINE;
static inline void USB_Host_ResumeFromWakeupRequest(void)
{
UHCON |= (1 << RESUME);
}
/** Determines if a resume from Remote Wakeup request is currently being sent to an attached
* device.
*
* \return Boolean \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 ((UHCON & (1 << RESUME)) ? false : true);
}
/* Private Interface - For use in library only: */
#if !defined(__DOXYGEN__)
/* Macros: */
static inline void USB_Host_HostMode_On(void) ATTR_ALWAYS_INLINE;
static inline void USB_Host_HostMode_On(void)
{
USBCON |= (1 << HOST);
}
static inline void USB_Host_HostMode_Off(void) ATTR_ALWAYS_INLINE;
static inline void USB_Host_HostMode_Off(void)
{
USBCON &= ~(1 << HOST);
}
static inline void USB_Host_VBUS_Auto_Enable(void) ATTR_ALWAYS_INLINE;
static inline void USB_Host_VBUS_Auto_Enable(void)
{
OTGCON &= ~(1 << VBUSHWC);
UHWCON |= (1 << UVCONE);
}
static inline void USB_Host_VBUS_Manual_Enable(void) ATTR_ALWAYS_INLINE;
static inline void USB_Host_VBUS_Manual_Enable(void)
{
OTGCON |= (1 << VBUSHWC);
UHWCON &= ~(1 << UVCONE);
DDRE |= (1 << 7);
}
static inline void USB_Host_VBUS_Auto_On(void) ATTR_ALWAYS_INLINE;
static inline void USB_Host_VBUS_Auto_On(void)
{
OTGCON |= (1 << VBUSREQ);
}
static inline void USB_Host_VBUS_Manual_On(void) ATTR_ALWAYS_INLINE;
static inline void USB_Host_VBUS_Manual_On(void)
{
#if defined(INVERTED_VBUS_ENABLE_LINE)
PORTE &= ~(1 << 7);
#else
PORTE |= (1 << 7);
#endif
}
static inline void USB_Host_VBUS_Auto_Off(void) ATTR_ALWAYS_INLINE;
static inline void USB_Host_VBUS_Auto_Off(void)
{
OTGCON |= (1 << VBUSRQC);
}
static inline void USB_Host_VBUS_Manual_Off(void) ATTR_ALWAYS_INLINE;
static inline void USB_Host_VBUS_Manual_Off(void)
{
#if defined(INVERTED_VBUS_ENABLE_LINE)
PORTE |= (1 << 7);
#else
PORTE &= ~(1 << 7);
#endif
}
static inline void USB_Host_SetDeviceAddress(const uint8_t Address) ATTR_ALWAYS_INLINE;
static inline void USB_Host_SetDeviceAddress(const uint8_t Address)
{
UHADDR = (Address & 0x7F);
}
/* Enums: */
enum USB_Host_WaitMSErrorCodes_t
{
HOST_WAITERROR_Successful = 0,
HOST_WAITERROR_DeviceDisconnect = 1,
HOST_WAITERROR_PipeError = 2,
HOST_WAITERROR_SetupStalled = 3,
};
/* Function Prototypes: */
void USB_Host_ProcessNextHostState(void);
uint8_t USB_Host_WaitMS(uint8_t MS);
#if defined(__INCLUDE_FROM_HOST_C)
static void USB_Host_ResetDevice(void);
#endif
#endif
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,159 @@
/*
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 OTG definitions for the AVR8 microcontrollers.
* \copydetails Group_OTG_AVR8
*
* \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_OTG
* \defgroup Group_OTG_AVR8 USB On The Go (OTG) Management (AVR8)
* \brief USB OTG definitions for the AVR8 microcontrollers.
*
* Architecture specific USB OTG definitions for the Atmel 8-bit AVR microcontrollers.
*
* @{
*/
#ifndef __USBOTG_AVR8_H__
#define __USBOTG_AVR8_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
/* Public Interface - May be used in end-application: */
/* Macros: */
/** Mask for the VBUS pulsing method of SRP, supported by some OTG devices.
*
* \see \ref USB_OTG_Device_InitiateSRP().
*/
#define USB_OTG_SRP_VBUS (1 << SRPSEL)
/** Mask for the Data + pulsing method of SRP, supported by some OTG devices.
*
* \see \ref USB_OTG_Device_InitiateSRP().
*/
#define USB_OTG_STP_DATA 0
/* Inline Functions: */
/** Initiate a Host Negotiation Protocol request. This indicates to the other connected device
* that the device wishes to change device/host roles.
*/
static inline void USB_OTG_Device_RequestHNP(void) ATTR_ALWAYS_INLINE;
static inline void USB_OTG_Device_RequestHNP(void)
{
OTGCON |= (1 << HNPREQ);
}
/** Cancel a Host Negotiation Protocol request. This stops a pending HNP request to the other
* connected device.
*/
static inline void USB_OTG_Device_CancelHNPRequest(void) ATTR_ALWAYS_INLINE;
static inline void USB_OTG_Device_CancelHNPRequest(void)
{
OTGCON &= ~(1 << HNPREQ);
}
/** Determines if the device is currently sending a HNP to an attached host.
*
* \return Boolean \c true if currently sending a HNP to the other connected device, \c false otherwise
*/
static inline bool USB_OTG_Device_IsSendingHNP(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool USB_OTG_Device_IsSendingHNP(void)
{
return ((OTGCON & (1 << HNPREQ)) ? true : false);
}
/** Initiates a Session Request Protocol request. Most OTG devices turn off VBUS when the USB
* interface is not in use, to conserve power. Sending a SRP to a USB OTG device running in
* host mode indicates that VBUS should be applied and a session started.
*
* There are two different methods of sending a SRP - either pulses on the VBUS line, or by
* pulsing the Data + line via the internal pull-up resistor.
*
* \param[in] SRPTypeMask Mask indicating the type of SRP to use, either \ref USB_OTG_SRP_VBUS or
* \ref USB_OTG_STP_DATA.
*/
static inline void USB_OTG_Device_InitiateSRP(const uint8_t SRPTypeMask) ATTR_ALWAYS_INLINE;
static inline void USB_OTG_Device_InitiateSRP(const uint8_t SRPTypeMask)
{
OTGCON = ((OTGCON & ~(1 << SRPSEL)) | (SRPTypeMask | (1 << SRPREQ)));
}
/** Accepts a HNP from a connected device, indicating that both devices should exchange
* device/host roles.
*/
static inline void USB_OTG_Host_AcceptHNP(void) ATTR_ALWAYS_INLINE;
static inline void USB_OTG_Host_AcceptHNP(void)
{
OTGCON |= (1 << HNPREQ);
}
/** Rejects a HNP from a connected device, indicating that both devices should remain in their
* current device/host roles.
*/
static inline void USB_OTG_Host_RejectHNP(void) ATTR_ALWAYS_INLINE;
static inline void USB_OTG_Host_RejectHNP(void)
{
OTGCON &= ~(1 << HNPREQ);
}
/** Indicates if the connected device is currently sending a HNP request.
*
* \return Boolean \c true if a HNP is currently being issued by the connected device, \c false otherwise.
*/
static inline bool USB_OTG_Host_IsHNPReceived(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool USB_OTG_Host_IsHNPReceived(void)
{
return ((OTGCON & (1 << HNPREQ)) ? true : false);
}
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,221 @@
/*
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_AVR8)
#define __INCLUDE_FROM_USB_DRIVER
#include "../USBMode.h"
#if defined(USB_CAN_BE_HOST)
#include "PipeStream_AVR8.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"
#define TEMPLATE_FUNC_NAME Pipe_Write_PStream_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(pgm_read_byte(BufferPtr))
#include "Template/Template_Pipe_RW.c"
#define TEMPLATE_FUNC_NAME Pipe_Write_PStream_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(pgm_read_byte(BufferPtr))
#include "Template/Template_Pipe_RW.c"
#define TEMPLATE_FUNC_NAME Pipe_Write_EStream_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(eeprom_read_byte(BufferPtr))
#include "Template/Template_Pipe_RW.c"
#define TEMPLATE_FUNC_NAME Pipe_Write_EStream_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(eeprom_read_byte(BufferPtr))
#include "Template/Template_Pipe_RW.c"
#define TEMPLATE_FUNC_NAME Pipe_Read_EStream_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) eeprom_update_byte(BufferPtr, Pipe_Read_8())
#include "Template/Template_Pipe_RW.c"
#define TEMPLATE_FUNC_NAME Pipe_Read_EStream_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) eeprom_update_byte(BufferPtr, Pipe_Read_8())
#include "Template/Template_Pipe_RW.c"
#endif
#endif

View file

@ -0,0 +1,442 @@
/*
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 AVR8 microcontrollers
* \copydetails Group_PipeStreamRW_AVR8
*
* \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_AVR8 Read/Write of Multi-Byte Streams (AVR8)
* \brief Pipe data stream transmission and reception management for the Atmel AVR8 architecture.
*
* Functions, macros, variables, enums and types related to data reading and writing of data streams from
* and to pipes.
*
* @{
*/
#ifndef __PIPE_STREAM_AVR8_H__
#define __PIPE_STREAM_AVR8_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);
//@}
/** \name Stream functions for EEPROM source/destination data */
//@{
/** EEPROM buffer source version of \ref Pipe_Write_Stream_LE().
*
* \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_EStream_LE(const void* const Buffer,
uint16_t Length,
uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
/** EEPROM buffer source version of \ref Pipe_Write_Stream_BE().
*
* \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_EStream_BE(const void* const Buffer,
uint16_t Length,
uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
/** EEPROM buffer source version of \ref Pipe_Read_Stream_LE().
*
* \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_EStream_LE(void* const Buffer,
uint16_t Length,
uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
/** EEPROM buffer source version of \ref Pipe_Read_Stream_BE().
*
* \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_EStream_BE(void* const Buffer,
uint16_t Length,
uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
//@}
/** \name Stream functions for PROGMEM source/destination data */
//@{
/** FLASH buffer source version of \ref Pipe_Write_Stream_LE().
*
* \pre The FLASH data must be located in the first 64KB of FLASH for this function to work correctly.
*
* \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_PStream_LE(const void* const Buffer,
uint16_t Length,
uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
/** FLASH buffer source version of \ref Pipe_Write_Stream_BE().
*
* \pre The FLASH data must be located in the first 64KB of FLASH for this function to work correctly.
*
* \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_PStream_BE(const 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,210 @@
/*
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_AVR8)
#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;
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;
#if defined(ORDERED_EP_CONFIG)
Pipe_SelectPipe(Number);
Pipe_EnablePipe();
UPCFG1X = 0;
UPCFG0X = ((Type << EPTYPE0) | Token | ((EndpointAddress & PIPE_EPNUM_MASK) << PEPNUM0));
UPCFG1X = ((1 << ALLOC) | ((Banks > 1) ? (1 << EPBK0) : 0) | Pipe_BytesToEPSizeMask(Size));
Pipe_SetInfiniteINRequests();
return Pipe_IsConfigured();
#else
for (uint8_t PNum = Number; PNum < PIPE_TOTAL_PIPES; PNum++)
{
uint8_t UPCFG0XTemp;
uint8_t UPCFG1XTemp;
uint8_t UPCFG2XTemp;
uint8_t UPIENXTemp;
Pipe_SelectPipe(PNum);
if (PNum == Number)
{
UPCFG0XTemp = ((Type << EPTYPE0) | Token | ((EndpointAddress & PIPE_EPNUM_MASK) << PEPNUM0));
UPCFG1XTemp = ((1 << ALLOC) | ((Banks > 1) ? (1 << EPBK0) : 0) | Pipe_BytesToEPSizeMask(Size));
UPCFG2XTemp = 0;
UPIENXTemp = 0;
}
else
{
UPCFG0XTemp = UPCFG0X;
UPCFG1XTemp = UPCFG1X;
UPCFG2XTemp = UPCFG2X;
UPIENXTemp = UPIENX;
}
if (!(UPCFG1XTemp & (1 << ALLOC)))
continue;
Pipe_DisablePipe();
UPCFG1X &= ~(1 << ALLOC);
Pipe_EnablePipe();
UPCFG0X = UPCFG0XTemp;
UPCFG1X = UPCFG1XTemp;
UPCFG2X = UPCFG2XTemp;
UPIENX = UPIENXTemp;
Pipe_SetInfiniteINRequests();
if (!(Pipe_IsConfigured()))
return false;
}
Pipe_SelectPipe(Number);
return true;
#endif
}
void Pipe_ClearPipes(void)
{
UPINT = 0;
for (uint8_t PNum = 0; PNum < PIPE_TOTAL_PIPES; PNum++)
{
Pipe_SelectPipe(PNum);
UPIENX = 0;
UPINTX = 0;
UPCFG1X = 0;
Pipe_DisablePipe();
}
}
bool Pipe_IsEndpointBound(const uint8_t EndpointAddress)
{
uint8_t PrevPipeNumber = Pipe_GetCurrentPipe();
for (uint8_t PNum = 0; PNum < PIPE_TOTAL_PIPES; PNum++)
{
Pipe_SelectPipe(PNum);
if (!(Pipe_IsConfigured()))
continue;
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,922 @@
/*
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 AVR8 microcontrollers.
* \copydetails Group_PipeManagement_AVR8
*
* \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_AVR8 Pipe Data Reading and Writing (AVR8)
* \brief Pipe data read/write definitions for the Atmel AVR8 architecture.
*
* Functions, macros, variables, enums and types related to data reading and writing from and to pipes.
*/
/** \ingroup Group_PipePrimitiveRW
* \defgroup Group_PipePrimitiveRW_AVR8 Read/Write of Primitive Data Types (AVR8)
* \brief Pipe primitive data read/write definitions for the Atmel AVR8 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_AVR8 Pipe Packet Management (AVR8)
* \brief Pipe packet management definitions for the Atmel AVR8 architecture.
*
* Functions, macros, variables, enums and types related to packet management of pipes.
*/
/** \ingroup Group_PipeControlReq
* \defgroup Group_PipeControlReq_AVR8 Pipe Control Request Management (AVR8)
* \brief Pipe control request management definitions for the Atmel AVR8 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_AVR8 Pipe Management (AVR8)
* \brief Pipe management definitions for the Atmel AVR8 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_AVR8_H__
#define __PIPE_AVR8_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
/* Public Interface - May be used in end-application: */
/* Macros: */
/** \name Pipe Error Flag Masks */
//@{
/** Mask for \ref Pipe_GetErrorFlags(), indicating that an overflow error occurred in the pipe on the received data. */
#define PIPE_ERRORFLAG_OVERFLOW (1 << 6)
/** Mask for \ref Pipe_GetErrorFlags(), indicating that an underflow error occurred in the pipe on the received data. */
#define PIPE_ERRORFLAG_UNDERFLOW (1 << 5)
/** Mask for \ref Pipe_GetErrorFlags(), indicating that a CRC error occurred in the pipe on the received data. */
#define PIPE_ERRORFLAG_CRC16 (1 << 4)
/** Mask for \ref Pipe_GetErrorFlags(), indicating that a hardware timeout error occurred in the pipe. */
#define PIPE_ERRORFLAG_TIMEOUT (1 << 3)
/** Mask for \ref Pipe_GetErrorFlags(), indicating that a hardware PID error occurred in the pipe. */
#define PIPE_ERRORFLAG_PID (1 << 2)
/** Mask for \ref Pipe_GetErrorFlags(), indicating that a hardware data PID error occurred in the pipe. */
#define PIPE_ERRORFLAG_DATAPID (1 << 1)
/** Mask for \ref Pipe_GetErrorFlags(), indicating that a hardware data toggle error occurred in the pipe. */
#define PIPE_ERRORFLAG_DATATGL (1 << 0)
//@}
/** \name Pipe Token Masks */
//@{
/** Token mask for \ref Pipe_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 (0 << PTOKEN0)
/** 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 (1 << PTOKEN0)
/** 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 (2 << PTOKEN0)
//@}
/** 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
/** Total number of pipes (including the default control pipe at address 0) which may be used in
* the device. Different USB AVR models support different amounts of pipes, this value reflects
* the maximum number of pipes for the currently selected AVR model.
*/
#define PIPE_TOTAL_PIPES 7
/** Size in bytes of the largest pipe bank size possible in the device. Not all banks on each AVR
* model supports the largest bank size possible on the device; different pipe numbers support
* different maximum bank sizes. This value reflects the largest possible bank of any pipe on the
* currently selected USB AVR model.
*/
#define PIPE_MAX_SIZE 256
/* Enums: */
/** Enum for the possible error return codes of the \ref Pipe_WaitUntilReady() function.
*
* \ingroup Group_PipeRW_AVR8
*/
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_AVR8
*
* \return Total number of bytes in the currently selected pipe's FIFO buffer.
*/
static inline uint16_t Pipe_BytesInPipe(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline uint16_t Pipe_BytesInPipe(void)
{
return UPBCX;
}
/** 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 (UPCFG0X & (1 << EPDIR)) ? PIPE_DIR_IN : PIPE_DIR_OUT;
}
/** Returns the pipe address of the currently selected pipe. This is typically used to save the
* currently selected pipe address so that it can be restored after another pipe has been manipulated.
*
* \return Index of the currently selected pipe.
*/
static inline uint8_t Pipe_GetCurrentPipe(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline uint8_t Pipe_GetCurrentPipe(void)
{
return ((UPNUM & PIPE_PIPENUM_MASK) | 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)
{
UPNUM = (Address & PIPE_PIPENUM_MASK);
}
/** Resets the desired pipe, including the pipe banks and flags.
*
* \param[in] Address Address 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)
{
UPRST = (1 << (Address & PIPE_PIPENUM_MASK));
UPRST = 0;
}
/** Enables the currently selected pipe so that data can be sent and received through it to and from
* an attached device.
*
* \pre The currently selected pipe must first be configured properly via \ref Pipe_ConfigurePipe().
*/
static inline void Pipe_EnablePipe(void) ATTR_ALWAYS_INLINE;
static inline void Pipe_EnablePipe(void)
{
UPCONX |= (1 << PEN);
}
/** Disables the currently selected pipe so that data cannot be sent and received through it to and
* from an attached device.
*/
static inline void Pipe_DisablePipe(void) ATTR_ALWAYS_INLINE;
static inline void Pipe_DisablePipe(void)
{
UPCONX &= ~(1 << PEN);
}
/** Determines if the currently selected pipe is enabled, but not necessarily configured.
*
* \return Boolean \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 ((UPCONX & (1 << PEN)) ? true : false);
}
/** Gets the current pipe token, indicating the pipe's data direction and type.
*
* \return The current pipe token, as a \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 (UPCFG0X & (0x03 << PTOKEN0));
}
/** 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)
{
UPCFG0X = ((UPCFG0X & ~(0x03 << PTOKEN0)) | Token);
}
/** Configures the currently selected pipe to allow for an unlimited number of IN requests. */
static inline void Pipe_SetInfiniteINRequests(void) ATTR_ALWAYS_INLINE;
static inline void Pipe_SetInfiniteINRequests(void)
{
UPCONX |= (1 << INMODE);
}
/** Configures the currently selected pipe to only allow the specified number of IN requests to be
* accepted by the pipe before it is automatically frozen.
*
* \param[in] TotalINRequests Total number of IN requests that the pipe may receive before freezing.
*/
static inline void Pipe_SetFiniteINRequests(const uint8_t TotalINRequests) ATTR_ALWAYS_INLINE;
static inline void Pipe_SetFiniteINRequests(const uint8_t TotalINRequests)
{
UPCONX &= ~(1 << INMODE);
UPINRQX = TotalINRequests;
}
/** Determines if the currently selected pipe is configured.
*
* \return Boolean \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 ((UPSTAX & (1 << CFGOK)) ? true : false);
}
/** 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)
{
uint8_t UPCFG0X_Temp = UPCFG0X;
return (((UPCFG0X_Temp >> PEPNUM0) & PIPE_EPNUM_MASK) |
((UPCFG0X_Temp & (1 << PTOKEN1)) ? ENDPOINT_DIR_IN : ENDPOINT_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)
{
UPCFG2X = Milliseconds;
}
/** Returns a mask indicating which pipe's interrupt periods have elapsed, indicating that the pipe should
* be serviced.
*
* \return Mask whose bits indicate which pipes have interrupted.
*/
static inline uint8_t Pipe_GetPipeInterrupts(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline uint8_t Pipe_GetPipeInterrupts(void)
{
return UPINT;
}
/** Determines if the specified pipe 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 ((UPINT & (1 << (Address & PIPE_PIPENUM_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)
{
UPCONX &= ~(1 << PFREEZE);
}
/** Freezes the selected pipe, preventing it from communicating with an attached device. */
static inline void Pipe_Freeze(void) ATTR_ALWAYS_INLINE;
static inline void Pipe_Freeze(void)
{
UPCONX |= (1 << PFREEZE);
}
/** Determines if the currently selected pipe is frozen, and not able to accept data.
*
* \return Boolean \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 ((UPCONX & (1 << 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)
{
UPERRX = 0;
UPINTX &= ~(1 << PERRI);
}
/** Determines if the master pipe error flag is set for the currently selected pipe, indicating that
* some sort of hardware error has occurred on the pipe.
*
* \see \ref Pipe_GetErrorFlags() macro for information on retrieving the exact error flag.
*
* \return Boolean \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 ((UPINTX & (1 << PERRI)) ? 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 ((UPERRX & (PIPE_ERRORFLAG_CRC16 | PIPE_ERRORFLAG_TIMEOUT |
PIPE_ERRORFLAG_PID | PIPE_ERRORFLAG_DATAPID |
PIPE_ERRORFLAG_DATATGL)) |
(UPSTAX & (PIPE_ERRORFLAG_OVERFLOW | PIPE_ERRORFLAG_UNDERFLOW)));
}
/** Retrieves the number of busy banks in the currently selected pipe, which have been queued for
* transmission via the \ref Pipe_ClearOUT() command, or are awaiting acknowledgement via the
* \ref Pipe_ClearIN() command.
*
* \ingroup Group_PipePacketManagement_AVR8
*
* \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 (UPSTAX & (0x03 << NBUSYBK0));
}
/** Determines if the currently selected pipe may be read from (if data is waiting in the pipe
* bank and the pipe is an IN direction, or if the bank is not yet full if the pipe is an OUT
* direction). This function will return false if an error has occurred in the pipe, or if the pipe
* is an IN direction and no packet (or an empty packet) has been received, or if the pipe is an OUT
* direction and the pipe bank is full.
*
* \note This function is not valid on CONTROL type pipes.
*
* \ingroup Group_PipePacketManagement_AVR8
*
* \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 ((UPINTX & (1 << RWAL)) ? true : false);
}
/** Determines if a packet has been received on the currently selected IN pipe from the attached device.
*
* \ingroup Group_PipePacketManagement_AVR8
*
* \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 ((UPINTX & (1 << RXINI)) ? true : false);
}
/** Determines if the currently selected OUT pipe is ready to send an OUT packet to the attached device.
*
* \ingroup Group_PipePacketManagement_AVR8
*
* \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 ((UPINTX & (1 << TXOUTI)) ? true : false);
}
/** Determines if no SETUP request is currently being sent to the attached device on the selected
* CONTROL type pipe.
*
* \ingroup Group_PipePacketManagement_AVR8
*
* \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 ((UPINTX & (1 << TXSTPI)) ? true : false);
}
/** Sends the currently selected CONTROL type pipe's contents to the device as a SETUP packet.
*
* \ingroup Group_PipePacketManagement_AVR8
*/
static inline void Pipe_ClearSETUP(void) ATTR_ALWAYS_INLINE;
static inline void Pipe_ClearSETUP(void)
{
UPINTX &= ~((1 << TXSTPI) | (1 << FIFOCON));
}
/** Acknowledges the reception of a setup IN request from the attached device on the currently selected
* pipe, freeing the bank ready for the next packet.
*
* \ingroup Group_PipePacketManagement_AVR8
*/
static inline void Pipe_ClearIN(void) ATTR_ALWAYS_INLINE;
static inline void Pipe_ClearIN(void)
{
UPINTX &= ~((1 << RXINI) | (1 << FIFOCON));
}
/** Sends the currently selected pipe's contents to the device as an OUT packet on the selected pipe, freeing
* the bank ready for the next packet.
*
* \ingroup Group_PipePacketManagement_AVR8
*/
static inline void Pipe_ClearOUT(void) ATTR_ALWAYS_INLINE;
static inline void Pipe_ClearOUT(void)
{
UPINTX &= ~((1 << TXOUTI) | (1 << FIFOCON));
}
/** Determines if the device sent a NAK (Negative Acknowledge) in response to the last sent packet on
* the currently selected pipe. This occurs when the host sends a packet to the device, but the device
* is not currently ready to handle the packet (i.e. its endpoint banks are full). Once a NAK has been
* received, it must be cleared using \ref Pipe_ClearNAKReceived() before the previous (or any other) packet
* can be re-sent.
*
* \ingroup Group_PipePacketManagement_AVR8
*
* \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 ((UPINTX & (1 << NAKEDI)) ? true : false);
}
/** Clears the NAK condition on the currently selected pipe.
*
* \ingroup Group_PipePacketManagement_AVR8
*
* \see \ref Pipe_IsNAKReceived() for more details.
*/
static inline void Pipe_ClearNAKReceived(void) ATTR_ALWAYS_INLINE;
static inline void Pipe_ClearNAKReceived(void)
{
UPINTX &= ~(1 << NAKEDI);
}
/** Determines if the currently selected pipe has had the STALL condition set by the attached device.
*
* \ingroup Group_PipePacketManagement_AVR8
*
* \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 ((UPINTX & (1 << RXSTALLI)) ? true : false);
}
/** Clears the STALL condition detection flag on the currently selected pipe, but does not clear the
* STALL condition itself (this must be done via a ClearFeature control request to the device).
*
* \ingroup Group_PipePacketManagement_AVR8
*/
static inline void Pipe_ClearStall(void) ATTR_ALWAYS_INLINE;
static inline void Pipe_ClearStall(void)
{
UPINTX &= ~(1 << RXSTALLI);
}
/** Reads one byte from the currently selected pipe's bank, for OUT direction pipes.
*
* \ingroup Group_PipePrimitiveRW_AVR8
*
* \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 UPDATX;
}
/** Writes one byte to the currently selected pipe's bank, for IN direction pipes.
*
* \ingroup Group_PipePrimitiveRW_AVR8
*
* \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)
{
UPDATX = Data;
}
/** Discards one byte from the currently selected pipe's bank, for OUT direction pipes.
*
* \ingroup Group_PipePrimitiveRW_AVR8
*/
static inline void Pipe_Discard_8(void) ATTR_ALWAYS_INLINE;
static inline void Pipe_Discard_8(void)
{
uint8_t Dummy;
Dummy = UPDATX;
(void)Dummy;
}
/** Reads two bytes from the currently selected pipe's bank in little endian format, for OUT
* direction pipes.
*
* \ingroup Group_PipePrimitiveRW_AVR8
*
* \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)
{
union
{
uint16_t Value;
uint8_t Bytes[2];
} Data;
Data.Bytes[0] = UPDATX;
Data.Bytes[1] = UPDATX;
return Data.Value;
}
/** Reads two bytes from the currently selected pipe's bank in big endian format, for OUT
* direction pipes.
*
* \ingroup Group_PipePrimitiveRW_AVR8
*
* \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)
{
union
{
uint16_t Value;
uint8_t Bytes[2];
} Data;
Data.Bytes[1] = UPDATX;
Data.Bytes[0] = UPDATX;
return Data.Value;
}
/** Writes two bytes to the currently selected pipe's bank in little endian format, for IN
* direction pipes.
*
* \ingroup Group_PipePrimitiveRW_AVR8
*
* \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)
{
UPDATX = (Data & 0xFF);
UPDATX = (Data >> 8);
}
/** Writes two bytes to the currently selected pipe's bank in big endian format, for IN
* direction pipes.
*
* \ingroup Group_PipePrimitiveRW_AVR8
*
* \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)
{
UPDATX = (Data >> 8);
UPDATX = (Data & 0xFF);
}
/** Discards two bytes from the currently selected pipe's bank, for OUT direction pipes.
*
* \ingroup Group_PipePrimitiveRW_AVR8
*/
static inline void Pipe_Discard_16(void) ATTR_ALWAYS_INLINE;
static inline void Pipe_Discard_16(void)
{
uint8_t Dummy;
Dummy = UPDATX;
Dummy = UPDATX;
(void)Dummy;
}
/** Reads four bytes from the currently selected pipe's bank in little endian format, for OUT
* direction pipes.
*
* \ingroup Group_PipePrimitiveRW_AVR8
*
* \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)
{
union
{
uint32_t Value;
uint8_t Bytes[4];
} Data;
Data.Bytes[0] = UPDATX;
Data.Bytes[1] = UPDATX;
Data.Bytes[2] = UPDATX;
Data.Bytes[3] = UPDATX;
return Data.Value;
}
/** Reads four bytes from the currently selected pipe's bank in big endian format, for OUT
* direction pipes.
*
* \ingroup Group_PipePrimitiveRW_AVR8
*
* \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)
{
union
{
uint32_t DWord;
uint8_t Bytes[4];
} Data;
Data.Bytes[3] = UPDATX;
Data.Bytes[2] = UPDATX;
Data.Bytes[1] = UPDATX;
Data.Bytes[0] = UPDATX;
return Data.DWord;
}
/** Writes four bytes to the currently selected pipe's bank in little endian format, for IN
* direction pipes.
*
* \ingroup Group_PipePrimitiveRW_AVR8
*
* \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)
{
UPDATX = (Data & 0xFF);
UPDATX = (Data >> 8);
UPDATX = (Data >> 16);
UPDATX = (Data >> 24);
}
/** Writes four bytes to the currently selected pipe's bank in big endian format, for IN
* direction pipes.
*
* \ingroup Group_PipePrimitiveRW_AVR8
*
* \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)
{
UPDATX = (Data >> 24);
UPDATX = (Data >> 16);
UPDATX = (Data >> 8);
UPDATX = (Data & 0xFF);
}
/** Discards four bytes from the currently selected pipe's bank, for OUT direction pipes.
*
* \ingroup Group_PipePrimitiveRW_AVR8
*/
static inline void Pipe_Discard_32(void) ATTR_ALWAYS_INLINE;
static inline void Pipe_Discard_32(void)
{
uint8_t Dummy;
Dummy = UPDATX;
Dummy = UPDATX;
Dummy = UPDATX;
Dummy = UPDATX;
(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.
*
* \attention 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.
*
* \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_AVR8
*
* \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 << EPSIZE0);
}
/* 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,273 @@
/*
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_AVR8)
#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_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR)
/* Workaround for AVR8 bootloaders that fail to turn off the OTG pad before running
* the loaded application. This causes VBUS detection to fail unless we first force
* it off to reset it. */
USB_OTGPAD_Off();
#endif
if (!(USB_Options & USB_OPT_REG_DISABLED))
USB_REG_On();
else
USB_REG_Off();
if (!(USB_Options & USB_OPT_MANUAL_PLL))
{
#if defined(USB_SERIES_4_AVR)
PLLFRQ = (1 << PDIV2);
#endif
}
#if defined(USB_CAN_BE_BOTH)
if (Mode == USB_MODE_UID)
{
UHWCON |= (1 << UIDE);
USB_INT_Enable(USB_INT_IDTI);
USB_CurrentMode = USB_GetUSBModeFromUID();
}
else
{
UHWCON &= ~(1 << UIDE);
USB_CurrentMode = Mode;
}
#endif
USB_IsInitialized = true;
USB_ResetInterface();
}
void USB_Disable(void)
{
USB_INT_DisableAllInterrupts();
USB_INT_ClearAllInterrupts();
USB_Detach();
USB_Controller_Disable();
if (!(USB_Options & USB_OPT_MANUAL_PLL))
USB_PLL_Off();
if (!(USB_Options & USB_OPT_REG_KEEP_ENABLED))
USB_REG_Off();
#if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR)
USB_OTGPAD_Off();
#endif
#if defined(USB_CAN_BE_BOTH)
USB_CurrentMode = USB_MODE_None;
#endif
USB_IsInitialized = false;
}
void USB_ResetInterface(void)
{
#if defined(USB_CAN_BE_BOTH)
bool UIDModeSelectEnabled = ((UHWCON & (1 << UIDE)) != 0);
#endif
USB_INT_DisableAllInterrupts();
USB_INT_ClearAllInterrupts();
USB_Controller_Reset();
#if 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)
#if (defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR))
UHWCON |= (1 << UIMOD);
#endif
if (!(USB_Options & USB_OPT_MANUAL_PLL))
{
#if defined(USB_SERIES_2_AVR)
USB_PLL_On();
while (!(USB_PLL_IsReady()));
#else
USB_PLL_Off();
#endif
}
USB_Init_Device();
#endif
}
else if (USB_CurrentMode == USB_MODE_Host)
{
#if defined(USB_CAN_BE_HOST)
UHWCON &= ~(1 << UIMOD);
if (!(USB_Options & USB_OPT_MANUAL_PLL))
{
#if defined(USB_CAN_BE_HOST)
USB_PLL_On();
while (!(USB_PLL_IsReady()));
#endif
}
USB_Init_Host();
#endif
}
#if (defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR))
USB_OTGPAD_On();
#endif
}
#if defined(USB_CAN_BE_DEVICE)
static void USB_Init_Device(void)
{
USB_DeviceState = DEVICE_STATE_Unattached;
USB_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 defined(ARCH_HAS_MULTI_ADDRESS_SPACE) && \
!(defined(USE_FLASH_DESCRIPTORS) || defined(USE_EEPROM_DESCRIPTORS) || defined(USE_RAM_DESCRIPTORS))
uint8_t DescriptorAddressSpace;
if (CALLBACK_USB_GetDescriptor((DTYPE_Device << 8), 0, (void*)&DeviceDescriptorPtr, &DescriptorAddressSpace) != NO_DESCRIPTOR)
{
if (DescriptorAddressSpace == MEMSPACE_FLASH)
USB_Device_ControlEndpointSize = pgm_read_byte(&DeviceDescriptorPtr->Endpoint0Size);
else if (DescriptorAddressSpace == MEMSPACE_EEPROM)
USB_Device_ControlEndpointSize = eeprom_read_byte(&DeviceDescriptorPtr->Endpoint0Size);
else
USB_Device_ControlEndpointSize = DeviceDescriptorPtr->Endpoint0Size;
}
#else
if (CALLBACK_USB_GetDescriptor((DTYPE_Device << 8), 0, (void*)&DeviceDescriptorPtr) != NO_DESCRIPTOR)
{
#if defined(USE_RAM_DESCRIPTORS)
USB_Device_ControlEndpointSize = DeviceDescriptorPtr->Endpoint0Size;
#elif defined(USE_EEPROM_DESCRIPTORS)
USB_Device_ControlEndpointSize = eeprom_read_byte(&DeviceDescriptorPtr->Endpoint0Size);
#else
USB_Device_ControlEndpointSize = pgm_read_byte(&DeviceDescriptorPtr->Endpoint0Size);
#endif
}
#endif
#endif
#if (defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR))
if (USB_Options & USB_DEVICE_OPT_LOWSPEED)
USB_Device_SetLowSpeed();
else
USB_Device_SetFullSpeed();
USB_INT_Enable(USB_INT_VBUSTI);
#endif
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_Off();
USB_Host_VBUS_Manual_Enable();
USB_Host_VBUS_Manual_On();
USB_INT_Enable(USB_INT_SRPI);
USB_INT_Enable(USB_INT_BCERRI);
USB_Attach();
}
#endif
#endif

View file

@ -0,0 +1,432 @@
/*
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 AVR8 microcontrollers.
* \copydetails Group_USBManagement_AVR8
*
* \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_AVR8 USB Interface Management (AVR8)
* \brief USB Controller definitions for the AVR8 microcontrollers.
*
* Functions, macros, variables, enums and types related to the setup and management of the USB interface.
*
* @{
*/
#ifndef __USBCONTROLLER_AVR8_H__
#define __USBCONTROLLER_AVR8_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 unprescaled USB controller clock in your project makefile.
#endif
#if (F_USB == 8000000)
#if (defined(__AVR_AT90USB82__) || defined(__AVR_AT90USB162__) || \
defined(__AVR_ATmega8U2__) || defined(__AVR_ATmega16U2__) || \
defined(__AVR_ATmega32U2__))
#define USB_PLL_PSC 0
#elif (defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__))
#define USB_PLL_PSC 0
#elif (defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__))
#define USB_PLL_PSC ((1 << PLLP1) | (1 << PLLP0))
#elif (defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1287__))
#define USB_PLL_PSC ((1 << PLLP1) | (1 << PLLP0))
#endif
#elif (F_USB == 16000000)
#if (defined(__AVR_AT90USB82__) || defined(__AVR_AT90USB162__) || \
defined(__AVR_ATmega8U2__) || defined(__AVR_ATmega16U2__) || \
defined(__AVR_ATmega32U2__))
#define USB_PLL_PSC (1 << PLLP0)
#elif (defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__))
#define USB_PLL_PSC (1 << PINDIV)
#elif (defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__))
#define USB_PLL_PSC ((1 << PLLP2) | (1 << PLLP1))
#elif (defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__))
#define USB_PLL_PSC ((1 << PLLP2) | (1 << PLLP0))
#endif
#endif
#if !defined(USB_PLL_PSC)
#error No PLL prescale value available for chosen F_USB value and AVR model.
#endif
/* Public Interface - May be used in end-application: */
/* Macros: */
/** \name USB Controller Option Masks */
//@{
/** Regulator disable option mask for \ref USB_Init(). This indicates that the internal 3.3V USB data pad
* regulator should be disabled and the AVR's VCC level used for the data pads.
*
* \note See USB AVR data sheet for more information on the internal pad regulator.
*/
#define USB_OPT_REG_DISABLED (1 << 1)
/** Regulator enable option mask for \ref USB_Init(). This indicates that the internal 3.3V USB data pad
* regulator should be enabled to regulate the data pin voltages from the VBUS level down to a level within
* the range allowable by the USB standard.
*
* \note See USB AVR data sheet for more information on the internal pad regulator.
*/
#define USB_OPT_REG_ENABLED (0 << 1)
/** Option mask for \ref USB_Init() to keep regulator enabled at all times. Indicates that \ref USB_Disable()
* should not disable the regulator as it would otherwise. Has no effect if regulator is disabled using
* \ref USB_OPT_REG_DISABLED.
*
* \note See USB AVR data sheet for more information on the internal pad regulator.
*/
#define USB_OPT_REG_KEEP_ENABLED (1 << 3)
/** Manual PLL control option mask for \ref USB_Init(). This indicates to the library that the user application
* will take full responsibility for controlling the AVR's PLL (used to generate the high frequency clock
* that the USB controller requires) and ensuring that it is locked at the correct frequency for USB operations.
*/
#define USB_OPT_MANUAL_PLL (1 << 2)
/** Automatic PLL control option mask for \ref USB_Init(). This indicates to the library that the library should
* take full responsibility for controlling the AVR's PLL (used to generate the high frequency clock
* that the USB controller requires) and ensuring that it is locked at the correct frequency for USB operations.
*/
#define USB_OPT_AUTO_PLL (0 << 2)
//@}
#if !defined(USB_STREAM_TIMEOUT_MS) || defined(__DOXYGEN__)
/** Constant for the maximum software timeout period of the USB data stream transfer functions
* (both control and standard) when in either device or host mode. If the next packet of a stream
* is not received or acknowledged within this time period, the stream function will fail.
*
* This value may be overridden in the user project makefile as the value of the
* \ref USB_STREAM_TIMEOUT_MS token, and passed to the compiler using the -D switch.
*/
#define USB_STREAM_TIMEOUT_MS 100
#endif
/* Inline Functions: */
#if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR) || defined(__DOXYGEN__)
/** Determines if the VBUS line is currently high (i.e. the USB host is supplying power).
*
* \note This function is not available on some AVR models which do not support hardware VBUS monitoring.
*
* \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 ((USBSTA & (1 << VBUS)) ? true : false);
}
#endif
/** Detaches the device from the USB bus. This has the effect of removing the device from any
* attached host, ceasing USB communications. If no host is present, this prevents any host from
* enumerating the device once attached until \ref USB_Attach() is called.
*/
static inline void USB_Detach(void) ATTR_ALWAYS_INLINE;
static inline void USB_Detach(void)
{
UDCON |= (1 << DETACH);
}
/** Attaches the device to the USB bus. This announces the device's presence to any attached
* USB host, starting the enumeration process. If no host is present, attaching the device
* will allow for enumeration once a host is connected to the device.
*
* This is inexplicably also required for proper operation while in host mode, to enable the
* attachment of a device to the host. This is despite the bit being located in the device-mode
* register and despite the datasheet making no mention of its requirement in host mode.
*/
static inline void USB_Attach(void) ATTR_ALWAYS_INLINE;
static inline void USB_Attach(void)
{
UDCON &= ~(1 << DETACH);
}
/* Function Prototypes: */
/** Main function to initialize and start the USB interface. Once active, the USB interface will
* allow for device connection to a host when in device mode, or for device enumeration while in
* host mode.
*
* As the USB library relies on interrupts for the device and host mode enumeration processes,
* the user must enable global interrupts before or shortly after this function is called. In
* device mode, interrupts must be enabled within 500ms of this function being called to ensure
* that the host does not time out whilst enumerating the device. In host mode, interrupts may be
* enabled at the application's leisure however enumeration will not begin of an attached device
* until after this has occurred.
*
* Calling this function when the USB interface is already initialized will cause a complete USB
* interface reset and re-enumeration.
*
* \param[in] Mode 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.
* \n\n
*
* \note The mode parameter does not exist on devices where only one mode is possible, such as USB
* AVR models which only implement the USB device mode in hardware.
*
* \see \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__)
/* Function Prototypes: */
#if defined(__INCLUDE_FROM_USB_CONTROLLER_C)
#if defined(USB_CAN_BE_DEVICE)
static void USB_Init_Device(void);
#endif
#if defined(USB_CAN_BE_HOST)
static void USB_Init_Host(void);
#endif
#endif
/* Inline Functions: */
static inline void USB_PLL_On(void) ATTR_ALWAYS_INLINE;
static inline void USB_PLL_On(void)
{
PLLCSR = USB_PLL_PSC;
PLLCSR = (USB_PLL_PSC | (1 << PLLE));
}
static inline void USB_PLL_Off(void) ATTR_ALWAYS_INLINE;
static inline void USB_PLL_Off(void)
{
PLLCSR = 0;
}
static inline bool USB_PLL_IsReady(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool USB_PLL_IsReady(void)
{
return ((PLLCSR & (1 << PLOCK)) ? true : false);
}
static inline void USB_REG_On(void) ATTR_ALWAYS_INLINE;
static inline void USB_REG_On(void)
{
#if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR)
UHWCON |= (1 << UVREGE);
#else
REGCR &= ~(1 << REGDIS);
#endif
}
static inline void USB_REG_Off(void) ATTR_ALWAYS_INLINE;
static inline void USB_REG_Off(void)
{
#if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR)
UHWCON &= ~(1 << UVREGE);
#else
REGCR |= (1 << REGDIS);
#endif
}
#if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR)
static inline void USB_OTGPAD_On(void) ATTR_ALWAYS_INLINE;
static inline void USB_OTGPAD_On(void)
{
USBCON |= (1 << OTGPADE);
}
static inline void USB_OTGPAD_Off(void) ATTR_ALWAYS_INLINE;
static inline void USB_OTGPAD_Off(void)
{
USBCON &= ~(1 << OTGPADE);
}
#endif
static inline void USB_CLK_Freeze(void) ATTR_ALWAYS_INLINE;
static inline void USB_CLK_Freeze(void)
{
USBCON |= (1 << FRZCLK);
}
static inline void USB_CLK_Unfreeze(void) ATTR_ALWAYS_INLINE;
static inline void USB_CLK_Unfreeze(void)
{
USBCON &= ~(1 << FRZCLK);
}
static inline void USB_Controller_Enable(void) ATTR_ALWAYS_INLINE;
static inline void USB_Controller_Enable(void)
{
USBCON |= (1 << USBE);
}
static inline void USB_Controller_Disable(void) ATTR_ALWAYS_INLINE;
static inline void USB_Controller_Disable(void)
{
USBCON &= ~(1 << USBE);
}
static inline void USB_Controller_Reset(void) ATTR_ALWAYS_INLINE;
static inline void USB_Controller_Reset(void)
{
USBCON &= ~(1 << USBE);
USBCON |= (1 << USBE);
}
#if defined(USB_CAN_BE_BOTH)
static inline uint8_t USB_GetUSBModeFromUID(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline uint8_t USB_GetUSBModeFromUID(void)
{
if (USBSTA & (1 << ID))
return USB_MODE_Device;
else
return USB_MODE_Host;
}
#endif
#endif
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,279 @@
/*
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_AVR8)
#define __INCLUDE_FROM_USB_DRIVER
#include "../USBInterrupt.h"
void USB_INT_DisableAllInterrupts(void)
{
#if defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR)
USBCON &= ~((1 << VBUSTE) | (1 << IDTE));
#elif defined(USB_SERIES_4_AVR)
USBCON &= ~(1 << VBUSTE);
#endif
#if defined(USB_CAN_BE_BOTH)
OTGIEN = 0;
#endif
#if defined(USB_CAN_BE_HOST)
UHIEN = 0;
#endif
#if defined(USB_CAN_BE_DEVICE)
UDIEN = 0;
#endif
}
void USB_INT_ClearAllInterrupts(void)
{
#if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR)
USBINT = 0;
#endif
#if defined(USB_CAN_BE_BOTH)
OTGINT = 0;
#endif
#if defined(USB_CAN_BE_HOST)
UHINT = 0;
#endif
#if defined(USB_CAN_BE_DEVICE)
UDINT = 0;
#endif
}
ISR(USB_GEN_vect, ISR_BLOCK)
{
#if defined(USB_CAN_BE_DEVICE)
#if !defined(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 defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR)
if (USB_INT_HasOccurred(USB_INT_VBUSTI) && USB_INT_IsEnabled(USB_INT_VBUSTI))
{
USB_INT_Clear(USB_INT_VBUSTI);
if (USB_VBUS_GetStatus())
{
if (!(USB_Options & USB_OPT_MANUAL_PLL))
{
USB_PLL_On();
while (!(USB_PLL_IsReady()));
}
USB_DeviceState = DEVICE_STATE_Powered;
EVENT_USB_Device_Connect();
}
else
{
if (!(USB_Options & USB_OPT_MANUAL_PLL))
USB_PLL_Off();
USB_DeviceState = DEVICE_STATE_Unattached;
EVENT_USB_Device_Disconnect();
}
}
#endif
if (USB_INT_HasOccurred(USB_INT_SUSPI) && USB_INT_IsEnabled(USB_INT_SUSPI))
{
USB_INT_Disable(USB_INT_SUSPI);
USB_INT_Enable(USB_INT_WAKEUPI);
USB_CLK_Freeze();
if (!(USB_Options & USB_OPT_MANUAL_PLL))
USB_PLL_Off();
#if defined(USB_SERIES_2_AVR) && !defined(NO_LIMITED_CONTROLLER_CONNECT)
USB_DeviceState = DEVICE_STATE_Unattached;
EVENT_USB_Device_Disconnect();
#else
USB_DeviceState = DEVICE_STATE_Suspended;
EVENT_USB_Device_Suspend();
#endif
}
if (USB_INT_HasOccurred(USB_INT_WAKEUPI) && USB_INT_IsEnabled(USB_INT_WAKEUPI))
{
if (!(USB_Options & USB_OPT_MANUAL_PLL))
{
USB_PLL_On();
while (!(USB_PLL_IsReady()));
}
USB_CLK_Unfreeze();
USB_INT_Clear(USB_INT_WAKEUPI);
USB_INT_Disable(USB_INT_WAKEUPI);
USB_INT_Enable(USB_INT_SUSPI);
if (USB_Device_ConfigurationNumber)
USB_DeviceState = DEVICE_STATE_Configured;
else
USB_DeviceState = (USB_Device_IsAddressSet()) ? DEVICE_STATE_Addressed : DEVICE_STATE_Powered;
#if defined(USB_SERIES_2_AVR) && !defined(NO_LIMITED_CONTROLLER_CONNECT)
EVENT_USB_Device_Connect();
#else
EVENT_USB_Device_WakeUp();
#endif
}
if (USB_INT_HasOccurred(USB_INT_EORSTI) && USB_INT_IsEnabled(USB_INT_EORSTI))
{
USB_INT_Clear(USB_INT_EORSTI);
USB_DeviceState = DEVICE_STATE_Default;
USB_Device_ConfigurationNumber = 0;
USB_INT_Clear(USB_INT_SUSPI);
USB_INT_Disable(USB_INT_SUSPI);
USB_INT_Enable(USB_INT_WAKEUPI);
Endpoint_ConfigureEndpoint(ENDPOINT_CONTROLEP, EP_TYPE_CONTROL,
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_SRPI) && USB_INT_IsEnabled(USB_INT_SRPI))
{
USB_INT_Clear(USB_INT_SRPI);
USB_INT_Disable(USB_INT_SRPI);
EVENT_USB_Host_DeviceAttached();
USB_INT_Enable(USB_INT_DDISCI);
USB_HostState = HOST_STATE_Powered;
}
if (USB_INT_HasOccurred(USB_INT_BCERRI) && USB_INT_IsEnabled(USB_INT_BCERRI))
{
USB_INT_Clear(USB_INT_BCERRI);
EVENT_USB_Host_DeviceEnumerationFailed(HOST_ENUMERROR_NoDeviceDetected, 0);
EVENT_USB_Host_DeviceUnattached();
USB_ResetInterface();
}
#endif
#if defined(USB_CAN_BE_BOTH)
if (USB_INT_HasOccurred(USB_INT_IDTI) && USB_INT_IsEnabled(USB_INT_IDTI))
{
USB_INT_Clear(USB_INT_IDTI);
if (USB_DeviceState != DEVICE_STATE_Unattached)
EVENT_USB_Device_Disconnect();
if (USB_HostState != HOST_STATE_Unattached)
EVENT_USB_Host_DeviceUnattached();
USB_CurrentMode = USB_GetUSBModeFromUID();
USB_ResetInterface();
EVENT_USB_UIDChange();
}
#endif
}
#if defined(INTERRUPT_CONTROL_ENDPOINT) && defined(USB_CAN_BE_DEVICE)
ISR(USB_COM_vect, ISR_BLOCK)
{
uint8_t PrevSelectedEndpoint = Endpoint_GetCurrentEndpoint();
Endpoint_SelectEndpoint(ENDPOINT_CONTROLEP);
USB_INT_Disable(USB_INT_RXSTPI);
GlobalInterruptEnable();
USB_Device_ProcessControlRequest();
Endpoint_SelectEndpoint(ENDPOINT_CONTROLEP);
USB_INT_Enable(USB_INT_RXSTPI);
Endpoint_SelectEndpoint(PrevSelectedEndpoint);
}
#endif
#endif

View file

@ -0,0 +1,375 @@
/*
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 AVR8 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_AVR8_H__
#define __USBINTERRUPT_AVR8_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__)
/* Enums: */
enum USB_Interrupts_t
{
#if (defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR) || defined(__DOXYGEN__))
USB_INT_VBUSTI = 0,
#endif
#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,
USB_INT_SRPI = 13,
#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)
{
#if (defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR))
case USB_INT_VBUSTI:
USBCON |= (1 << VBUSTE);
break;
#endif
#if defined(USB_CAN_BE_BOTH)
case USB_INT_IDTI:
USBCON |= (1 << IDTE);
break;
#endif
#if defined(USB_CAN_BE_DEVICE)
case USB_INT_WAKEUPI:
UDIEN |= (1 << WAKEUPE);
break;
case USB_INT_SUSPI:
UDIEN |= (1 << SUSPE);
break;
case USB_INT_EORSTI:
UDIEN |= (1 << EORSTE);
break;
case USB_INT_SOFI:
UDIEN |= (1 << SOFE);
break;
case USB_INT_RXSTPI:
UEIENX |= (1 << RXSTPE);
break;
#endif
#if defined(USB_CAN_BE_HOST)
case USB_INT_HSOFI:
UHIEN |= (1 << HSOFE);
break;
case USB_INT_DCONNI:
UHIEN |= (1 << DCONNE);
break;
case USB_INT_DDISCI:
UHIEN |= (1 << DDISCE);
break;
case USB_INT_RSTI:
UHIEN |= (1 << RSTE);
break;
case USB_INT_BCERRI:
OTGIEN |= (1 << BCERRE);
break;
case USB_INT_VBERRI:
OTGIEN |= (1 << VBERRE);
break;
case USB_INT_SRPI:
OTGIEN |= (1 << SRPE);
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)
{
#if (defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR))
case USB_INT_VBUSTI:
USBCON &= ~(1 << VBUSTE);
break;
#endif
#if defined(USB_CAN_BE_BOTH)
case USB_INT_IDTI:
USBCON &= ~(1 << IDTE);
break;
#endif
#if defined(USB_CAN_BE_DEVICE)
case USB_INT_WAKEUPI:
UDIEN &= ~(1 << WAKEUPE);
break;
case USB_INT_SUSPI:
UDIEN &= ~(1 << SUSPE);
break;
case USB_INT_EORSTI:
UDIEN &= ~(1 << EORSTE);
break;
case USB_INT_SOFI:
UDIEN &= ~(1 << SOFE);
break;
case USB_INT_RXSTPI:
UEIENX &= ~(1 << RXSTPE);
break;
#endif
#if defined(USB_CAN_BE_HOST)
case USB_INT_HSOFI:
UHIEN &= ~(1 << HSOFE);
break;
case USB_INT_DCONNI:
UHIEN &= ~(1 << DCONNE);
break;
case USB_INT_DDISCI:
UHIEN &= ~(1 << DDISCE);
break;
case USB_INT_RSTI:
UHIEN &= ~(1 << RSTE);
break;
case USB_INT_BCERRI:
OTGIEN &= ~(1 << BCERRE);
break;
case USB_INT_VBERRI:
OTGIEN &= ~(1 << VBERRE);
break;
case USB_INT_SRPI:
OTGIEN &= ~(1 << SRPE);
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)
{
#if (defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR))
case USB_INT_VBUSTI:
USBINT &= ~(1 << VBUSTI);
break;
#endif
#if defined(USB_CAN_BE_BOTH)
case USB_INT_IDTI:
USBINT &= ~(1 << IDTI);
break;
#endif
#if defined(USB_CAN_BE_DEVICE)
case USB_INT_WAKEUPI:
UDINT &= ~(1 << WAKEUPI);
break;
case USB_INT_SUSPI:
UDINT &= ~(1 << SUSPI);
break;
case USB_INT_EORSTI:
UDINT &= ~(1 << EORSTI);
break;
case USB_INT_SOFI:
UDINT &= ~(1 << SOFI);
break;
case USB_INT_RXSTPI:
UEINTX &= ~(1 << RXSTPI);
break;
#endif
#if defined(USB_CAN_BE_HOST)
case USB_INT_HSOFI:
UHINT &= ~(1 << HSOFI);
break;
case USB_INT_DCONNI:
UHINT &= ~(1 << DCONNI);
break;
case USB_INT_DDISCI:
UHINT &= ~(1 << DDISCI);
break;
case USB_INT_RSTI:
UHINT &= ~(1 << RSTI);
break;
case USB_INT_BCERRI:
OTGINT &= ~(1 << BCERRI);
break;
case USB_INT_VBERRI:
OTGINT &= ~(1 << VBERRI);
break;
case USB_INT_SRPI:
OTGINT &= ~(1 << SRPI);
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)
{
#if (defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR))
case USB_INT_VBUSTI:
return (USBCON & (1 << VBUSTE));
#endif
#if defined(USB_CAN_BE_BOTH)
case USB_INT_IDTI:
return (USBCON & (1 << IDTE));
#endif
#if defined(USB_CAN_BE_DEVICE)
case USB_INT_WAKEUPI:
return (UDIEN & (1 << WAKEUPE));
case USB_INT_SUSPI:
return (UDIEN & (1 << SUSPE));
case USB_INT_EORSTI:
return (UDIEN & (1 << EORSTE));
case USB_INT_SOFI:
return (UDIEN & (1 << SOFE));
case USB_INT_RXSTPI:
return (UEIENX & (1 << RXSTPE));
#endif
#if defined(USB_CAN_BE_HOST)
case USB_INT_HSOFI:
return (UHIEN & (1 << HSOFE));
case USB_INT_DCONNI:
return (UHIEN & (1 << DCONNE));
case USB_INT_DDISCI:
return (UHIEN & (1 << DDISCE));
case USB_INT_RSTI:
return (UHIEN & (1 << RSTE));
case USB_INT_BCERRI:
return (OTGIEN & (1 << BCERRE));
case USB_INT_VBERRI:
return (OTGIEN & (1 << VBERRE));
case USB_INT_SRPI:
return (OTGIEN & (1 << SRPE));
#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)
{
#if (defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR))
case USB_INT_VBUSTI:
return (USBINT & (1 << VBUSTI));
#endif
#if defined(USB_CAN_BE_BOTH)
case USB_INT_IDTI:
return (USBINT & (1 << IDTI));
#endif
#if defined(USB_CAN_BE_DEVICE)
case USB_INT_WAKEUPI:
return (UDINT & (1 << WAKEUPI));
case USB_INT_SUSPI:
return (UDINT & (1 << SUSPI));
case USB_INT_EORSTI:
return (UDINT & (1 << EORSTI));
case USB_INT_SOFI:
return (UDINT & (1 << SOFI));
case USB_INT_RXSTPI:
return (UEINTX & (1 << RXSTPI));
#endif
#if defined(USB_CAN_BE_HOST)
case USB_INT_HSOFI:
return (UHINT & (1 << HSOFI));
case USB_INT_DCONNI:
return (UHINT & (1 << DCONNI));
case USB_INT_DDISCI:
return (UHINT & (1 << DDISCI));
case USB_INT_RSTI:
return (UHINT & (1 << RSTI));
case USB_INT_BCERRI:
return (OTGINT & (1 << BCERRI));
case USB_INT_VBERRI:
return (OTGINT & (1 << VBERRI));
case USB_INT_SRPI:
return (OTGINT & (1 << SRPI));
#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
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif

View file

@ -0,0 +1,146 @@
/*
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.
*/
#define __INCLUDE_FROM_USB_DRIVER
#include "ConfigDescriptors.h"
#if defined(USB_CAN_BE_HOST)
uint8_t USB_Host_GetDeviceConfigDescriptor(const uint8_t ConfigNumber,
uint16_t* const ConfigSizePtr,
void* const BufferPtr,
const uint16_t BufferSize)
{
uint8_t ErrorCode;
uint8_t ConfigHeader[sizeof(USB_Descriptor_Configuration_Header_t)];
USB_ControlRequest = (USB_Request_Header_t)
{
.bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE),
.bRequest = REQ_GetDescriptor,
.wValue = ((DTYPE_Configuration << 8) | (ConfigNumber - 1)),
.wIndex = 0,
.wLength = sizeof(USB_Descriptor_Configuration_Header_t),
};
Pipe_SelectPipe(PIPE_CONTROLPIPE);
if ((ErrorCode = USB_Host_SendControlRequest(ConfigHeader)) != HOST_SENDCONTROL_Successful)
return ErrorCode;
*ConfigSizePtr = le16_to_cpu(DESCRIPTOR_PCAST(ConfigHeader, USB_Descriptor_Configuration_Header_t)->TotalConfigurationSize);
if (*ConfigSizePtr > BufferSize)
return HOST_GETCONFIG_BuffOverflow;
USB_ControlRequest.wLength = *ConfigSizePtr;
if ((ErrorCode = USB_Host_SendControlRequest(BufferPtr)) != HOST_SENDCONTROL_Successful)
return ErrorCode;
if (DESCRIPTOR_TYPE(BufferPtr) != DTYPE_Configuration)
return HOST_GETCONFIG_InvalidData;
return HOST_GETCONFIG_Successful;
}
#endif
void USB_GetNextDescriptorOfType(uint16_t* const BytesRem,
void** const CurrConfigLoc,
const uint8_t Type)
{
while (*BytesRem)
{
USB_GetNextDescriptor(BytesRem, CurrConfigLoc);
if (DESCRIPTOR_TYPE(*CurrConfigLoc) == Type)
return;
}
}
void USB_GetNextDescriptorOfTypeBefore(uint16_t* const BytesRem,
void** const CurrConfigLoc,
const uint8_t Type,
const uint8_t BeforeType)
{
while (*BytesRem)
{
USB_GetNextDescriptor(BytesRem, CurrConfigLoc);
if (DESCRIPTOR_TYPE(*CurrConfigLoc) == Type)
{
return;
}
else if (DESCRIPTOR_TYPE(*CurrConfigLoc) == BeforeType)
{
*BytesRem = 0;
return;
}
}
}
void USB_GetNextDescriptorOfTypeAfter(uint16_t* const BytesRem,
void** const CurrConfigLoc,
const uint8_t Type,
const uint8_t AfterType)
{
USB_GetNextDescriptorOfType(BytesRem, CurrConfigLoc, AfterType);
if (*BytesRem)
USB_GetNextDescriptorOfType(BytesRem, CurrConfigLoc, Type);
}
uint8_t USB_GetNextDescriptorComp(uint16_t* const BytesRem,
void** const CurrConfigLoc,
ConfigComparatorPtr_t const ComparatorRoutine)
{
uint8_t ErrorCode;
while (*BytesRem)
{
uint8_t* PrevDescLoc = *CurrConfigLoc;
uint16_t PrevBytesRem = *BytesRem;
USB_GetNextDescriptor(BytesRem, CurrConfigLoc);
if ((ErrorCode = ComparatorRoutine(*CurrConfigLoc)) != DESCRIPTOR_SEARCH_NotFound)
{
if (ErrorCode == DESCRIPTOR_SEARCH_Fail)
{
*CurrConfigLoc = PrevDescLoc;
*BytesRem = PrevBytesRem;
}
return ErrorCode;
}
}
return DESCRIPTOR_SEARCH_COMP_EndOfDescriptor;
}

View file

@ -0,0 +1,287 @@
/*
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 Configuration Descriptor definitions.
* \copydetails Group_ConfigDescriptorParser
*
* \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_StdDescriptors
* \defgroup Group_ConfigDescriptorParser Configuration Descriptor Parser
* \brief USB Configuration Descriptor definitions.
*
* This section of the library gives a friendly API which can be used in host applications to easily
* parse an attached device's configuration descriptor so that endpoint, interface and other descriptor
* data can be extracted and used as needed.
*
* @{
*/
#ifndef __CONFIGDESCRIPTORS_H__
#define __CONFIGDESCRIPTORS_H__
/* Includes: */
#include "../../../Common/Common.h"
#include "USBMode.h"
#include "HostStandardReq.h"
#include "StdDescriptors.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: */
/** Casts a pointer to a descriptor inside the configuration descriptor into a pointer to the given
* descriptor type.
*
* Usage Example:
* \code
* uint8_t* CurrDescriptor = &ConfigDescriptor[0]; // Pointing to the configuration header
* USB_Descriptor_Configuration_Header_t* ConfigHeaderPtr = DESCRIPTOR_PCAST(CurrDescriptor,
* USB_Descriptor_Configuration_Header_t);
*
* // Can now access elements of the configuration header struct using the -> indirection operator
* \endcode
*/
#define DESCRIPTOR_PCAST(DescriptorPtr, Type) ((Type*)(DescriptorPtr))
/** Casts a pointer to a descriptor inside the configuration descriptor into the given descriptor
* type (as an actual struct instance rather than a pointer to a struct).
*
* Usage Example:
* \code
* uint8_t* CurrDescriptor = &ConfigDescriptor[0]; // Pointing to the configuration header
* USB_Descriptor_Configuration_Header_t ConfigHeader = DESCRIPTOR_CAST(CurrDescriptor,
* USB_Descriptor_Configuration_Header_t);
*
* // Can now access elements of the configuration header struct using the . operator
* \endcode
*/
#define DESCRIPTOR_CAST(DescriptorPtr, Type) (*DESCRIPTOR_PCAST(DescriptorPtr, Type))
/** Returns the descriptor's type, expressed as the 8-bit type value in the header of the descriptor.
* This value's meaning depends on the descriptor's placement in the descriptor, but standard type
* values can be accessed in the \ref USB_DescriptorTypes_t enum.
*/
#define DESCRIPTOR_TYPE(DescriptorPtr) DESCRIPTOR_PCAST(DescriptorPtr, USB_Descriptor_Header_t)->Type
/** Returns the descriptor's size, expressed as the 8-bit value indicating the number of bytes. */
#define DESCRIPTOR_SIZE(DescriptorPtr) DESCRIPTOR_PCAST(DescriptorPtr, USB_Descriptor_Header_t)->Size
/* Type Defines: */
/** Type define for a Configuration Descriptor comparator function (function taking a pointer to an array
* of type void, returning a uint8_t value).
*
* \see \ref USB_GetNextDescriptorComp function for more details.
*/
typedef uint8_t (* ConfigComparatorPtr_t)(void*);
/* Enums: */
/** Enum for the possible return codes of the \ref USB_Host_GetDeviceConfigDescriptor() function. */
enum USB_Host_GetConfigDescriptor_ErrorCodes_t
{
HOST_GETCONFIG_Successful = 0, /**< No error occurred while retrieving the configuration descriptor. */
HOST_GETCONFIG_DeviceDisconnect = 1, /**< The attached device was disconnected while retrieving the configuration
* descriptor.
*/
HOST_GETCONFIG_PipeError = 2, /**< An error occurred in the pipe while sending the request. */
HOST_GETCONFIG_SetupStalled = 3, /**< The attached device stalled the request to retrieve the configuration
* descriptor.
*/
HOST_GETCONFIG_SoftwareTimeOut = 4, /**< The request or data transfer timed out. */
HOST_GETCONFIG_BuffOverflow = 5, /**< The device's configuration descriptor is too large to fit into the allocated
* buffer.
*/
HOST_GETCONFIG_InvalidData = 6, /**< The device returned invalid configuration descriptor data. */
};
/** Enum for return values of a descriptor comparator function. */
enum DSearch_Return_ErrorCodes_t
{
DESCRIPTOR_SEARCH_Found = 0, /**< Current descriptor matches comparator criteria. */
DESCRIPTOR_SEARCH_Fail = 1, /**< No further descriptor could possibly match criteria, fail the search. */
DESCRIPTOR_SEARCH_NotFound = 2, /**< Current descriptor does not match comparator criteria. */
};
/** Enum for return values of \ref USB_GetNextDescriptorComp(). */
enum DSearch_Comp_Return_ErrorCodes_t
{
DESCRIPTOR_SEARCH_COMP_Found = 0, /**< Configuration descriptor now points to descriptor which matches
* search criteria of the given comparator function. */
DESCRIPTOR_SEARCH_COMP_Fail = 1, /**< Comparator function returned \ref DESCRIPTOR_SEARCH_Fail. */
DESCRIPTOR_SEARCH_COMP_EndOfDescriptor = 2, /**< End of configuration descriptor reached before match found. */
};
/* Function Prototypes: */
/** Retrieves the configuration descriptor data from an attached device via a standard request into a buffer,
* including validity and size checking to prevent a buffer overflow.
*
* \param[in] ConfigNumber Device configuration descriptor number to fetch from the device (usually set to 1 for
* single configuration devices).
* \param[in,out] ConfigSizePtr Pointer to a location for storing the retrieved configuration descriptor size.
* \param[out] BufferPtr Pointer to the buffer for storing the configuration descriptor data.
* \param[out] BufferSize Size of the allocated buffer where the configuration descriptor is to be stored.
*
* \return A value from the \ref USB_Host_GetConfigDescriptor_ErrorCodes_t enum.
*/
uint8_t USB_Host_GetDeviceConfigDescriptor(const uint8_t ConfigNumber,
uint16_t* const ConfigSizePtr,
void* const BufferPtr,
const uint16_t BufferSize) ATTR_NON_NULL_PTR_ARG(2) ATTR_NON_NULL_PTR_ARG(3);
/** Skips to the next sub-descriptor inside the configuration descriptor of the specified type value.
* The bytes remaining value is automatically decremented.
*
* \param[in,out] BytesRem Pointer to the number of bytes remaining of the configuration descriptor.
* \param[in,out] CurrConfigLoc Pointer to the current descriptor inside the configuration descriptor.
* \param[in] Type Descriptor type value to search for.
*/
void USB_GetNextDescriptorOfType(uint16_t* const BytesRem,
void** const CurrConfigLoc,
const uint8_t Type)
ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
/** Skips to the next sub-descriptor inside the configuration descriptor of the specified type value,
* which must come before a descriptor of the second given type value. If the BeforeType type
* descriptor is reached first, the number of bytes remaining to process is set to zero and the
* function exits. The bytes remaining value is automatically decremented.
*
* \param[in,out] BytesRem Pointer to the number of bytes remaining of the configuration descriptor.
* \param[in,out] CurrConfigLoc Pointer to the current descriptor inside the configuration descriptor.
* \param[in] Type Descriptor type value to search for.
* \param[in] BeforeType Descriptor type value which must not be reached before the given Type descriptor.
*/
void USB_GetNextDescriptorOfTypeBefore(uint16_t* const BytesRem,
void** const CurrConfigLoc,
const uint8_t Type,
const uint8_t BeforeType)
ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
/** Skips to the next sub-descriptor inside the configuration descriptor of the specified type value,
* which must come after a descriptor of the second given type value. The bytes remaining value is
* automatically decremented.
*
* \param[in,out] BytesRem Pointer to the number of bytes remaining of the configuration descriptor.
* \param[in,out] CurrConfigLoc Pointer to the current descriptor inside the configuration descriptor.
* \param[in] Type Descriptor type value to search for.
* \param[in] AfterType Descriptor type value which must be reached before the given Type descriptor.
*/
void USB_GetNextDescriptorOfTypeAfter(uint16_t* const BytesRem,
void** const CurrConfigLoc,
const uint8_t Type,
const uint8_t AfterType)
ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
/** Searches for the next descriptor in the given configuration descriptor using a pre-made comparator
* function. The routine updates the position and remaining configuration descriptor bytes values
* automatically. If a comparator routine fails a search, the descriptor pointer is retreated back
* so that the next descriptor search invocation will start from the descriptor which first caused the
* original search to fail. This behavior allows for one comparator to be used immediately after another
* has failed, starting the second search from the descriptor which failed the first.
*
* Comparator functions should be standard functions which accept a pointer to the header of the current
* descriptor inside the configuration descriptor which is being compared, and should return a value from
* the \ref DSearch_Return_ErrorCodes_t enum as a uint8_t value.
*
* \note This function is available in USB Host mode only.
*
* \param[in,out] BytesRem Pointer to an int storing the remaining bytes in the configuration descriptor.
* \param[in,out] CurrConfigLoc Pointer to the current position in the configuration descriptor.
* \param[in] ComparatorRoutine Name of the comparator search function to use on the configuration descriptor.
*
* \return Value of one of the members of the \ref DSearch_Comp_Return_ErrorCodes_t enum.
*
* Usage Example:
* \code
* uint8_t EndpointSearcher(void* CurrentDescriptor); // Comparator Prototype
*
* uint8_t EndpointSearcher(void* CurrentDescriptor)
* {
* if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Endpoint)
* return DESCRIPTOR_SEARCH_Found;
* else
* return DESCRIPTOR_SEARCH_NotFound;
* }
*
* //...
*
* // After retrieving configuration descriptor:
* if (USB_Host_GetNextDescriptorComp(&BytesRemaining, &CurrentConfigLoc, EndpointSearcher) ==
* Descriptor_Search_Comp_Found)
* {
* // Do something with the endpoint descriptor
* }
* \endcode
*/
uint8_t USB_GetNextDescriptorComp(uint16_t* const BytesRem,
void** const CurrConfigLoc,
ConfigComparatorPtr_t const ComparatorRoutine) ATTR_NON_NULL_PTR_ARG(1)
ATTR_NON_NULL_PTR_ARG(2) ATTR_NON_NULL_PTR_ARG(3);
/* Inline Functions: */
/** Skips over the current sub-descriptor inside the configuration descriptor, so that the pointer then
points to the next sub-descriptor. The bytes remaining value is automatically decremented.
*
* \param[in,out] BytesRem Pointer to the number of bytes remaining of the configuration descriptor.
* \param[in,out] CurrConfigLoc Pointer to the current descriptor inside the configuration descriptor.
*/
static inline void USB_GetNextDescriptor(uint16_t* const BytesRem,
void** CurrConfigLoc) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
static inline void USB_GetNextDescriptor(uint16_t* const BytesRem,
void** CurrConfigLoc)
{
uint16_t CurrDescriptorSize = DESCRIPTOR_CAST(*CurrConfigLoc, USB_Descriptor_Header_t).Size;
if (*BytesRem < CurrDescriptorSize)
CurrDescriptorSize = *BytesRem;
*CurrConfigLoc = (void*)((uintptr_t)*CurrConfigLoc + CurrDescriptorSize);
*BytesRem -= CurrDescriptorSize;
}
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,159 @@
/*
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 Common USB Device definitions for all architectures.
* \copydetails Group_Device
*
* \note This file should not be included directly. It is automatically included as needed by the USB driver
* dispatch header located in LUFA/Drivers/USB/USB.h.
*/
/** \ingroup Group_USB
* \defgroup Group_Device Device Management
* \brief USB Device management definitions for USB device mode.
*
* USB Device mode related definitions common to all architectures. This module contains definitions which
* are used when the USB controller is initialized in device mode.
*
* @{
*/
#ifndef __USBDEVICE_H__
#define __USBDEVICE_H__
/* Includes: */
#include "../../../Common/Common.h"
#include "USBMode.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: */
/* Enums: */
/** Enum for the various states of the USB Device state machine. Only some states are
* implemented in the LUFA library - other states are left to the user to implement.
*
* For information on each possible USB device state, refer to the USB 2.0 specification.
*
* \see \ref USB_DeviceState, which stores the current device state machine state.
*/
enum USB_Device_States_t
{
DEVICE_STATE_Unattached = 0, /**< Internally implemented by the library. This state indicates
* that the device is not currently connected to a host.
*/
DEVICE_STATE_Powered = 1, /**< Internally implemented by the library. This state indicates
* that the device is connected to a host, but enumeration has not
* yet begun.
*/
DEVICE_STATE_Default = 2, /**< Internally implemented by the library. This state indicates
* that the device's USB bus has been reset by the host and it is
* now waiting for the host to begin the enumeration process.
*/
DEVICE_STATE_Addressed = 3, /**< Internally implemented by the library. This state indicates
* that the device has been addressed by the USB Host, but is not
* yet configured.
*/
DEVICE_STATE_Configured = 4, /**< May be implemented by the user project. This state indicates
* that the device has been enumerated by the host and is ready
* for USB communications to begin.
*/
DEVICE_STATE_Suspended = 5, /**< May be implemented by the user project. This state indicates
* that the USB bus has been suspended by the host, and the device
* should power down to a minimal power level until the bus is
* resumed.
*/
};
/* Function Prototypes: */
/** Function to retrieve a given descriptor's size and memory location from the given descriptor type value,
* index and language ID. This function MUST be overridden in the user application (added with full, identical
* prototype and name so that the library can call it to retrieve descriptor data.
*
* \param[in] wValue The type of the descriptor to retrieve in the upper byte, and the index in the
* lower byte (when more than one descriptor of the given type exists, such as the
* case of string descriptors). The type may be one of the standard types defined
* in the DescriptorTypes_t enum, or may be a class-specific descriptor type value.
* \param[in] wIndex The language ID of the string to return if the \c wValue type indicates
* \ref DTYPE_String, otherwise zero for standard descriptors, or as defined in a
* class-specific standards.
* \param[out] DescriptorAddress Pointer to the descriptor in memory. This should be set by the routine to
* the address of the descriptor.
* \param[out] DescriptorMemorySpace A value from the \ref USB_DescriptorMemorySpaces_t enum to indicate the memory
* space in which the descriptor is stored. This parameter does not exist when one
* of the \c USE_*_DESCRIPTORS compile time options is used, or on architectures which
* use a unified address space.
*
* \note By default, the library expects all descriptors to be located in flash memory via the \c PROGMEM attribute.
* If descriptors should be located in RAM or EEPROM instead (to speed up access in the case of RAM, or to
* allow the descriptors to be changed dynamically at runtime) either the \c USE_RAM_DESCRIPTORS or the
* \c USE_EEPROM_DESCRIPTORS tokens may be defined in the project makefile and passed to the compiler by the -D
* switch.
*
* \return Size in bytes of the descriptor if it exists, zero or \ref NO_DESCRIPTOR otherwise.
*/
uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
const uint16_t wIndex,
const void** const DescriptorAddress
#if (defined(ARCH_HAS_MULTI_ADDRESS_SPACE) || defined(__DOXYGEN__)) && \
!(defined(USE_FLASH_DESCRIPTORS) || defined(USE_EEPROM_DESCRIPTORS) || defined(USE_RAM_DESCRIPTORS))
, uint8_t* const DescriptorMemorySpace
#endif
) ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);
/* Architecture Includes: */
#if (ARCH == ARCH_AVR8)
#include "AVR8/Device_AVR8.h"
#elif (ARCH == ARCH_UC3)
#include "UC3/Device_UC3.h"
#elif (ARCH == ARCH_XMEGA)
#include "XMEGA/Device_XMEGA.h"
#endif
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,393 @@
/*
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.
*/
#define __INCLUDE_FROM_USB_DRIVER
#include "USBMode.h"
#if defined(USB_CAN_BE_DEVICE)
#define __INCLUDE_FROM_DEVICESTDREQ_C
#include "DeviceStandardReq.h"
uint8_t USB_Device_ConfigurationNumber;
#if !defined(NO_DEVICE_SELF_POWER)
bool USB_Device_CurrentlySelfPowered;
#endif
#if !defined(NO_DEVICE_REMOTE_WAKEUP)
bool USB_Device_RemoteWakeupEnabled;
#endif
void USB_Device_ProcessControlRequest(void)
{
#if defined(ARCH_BIG_ENDIAN)
USB_ControlRequest.bmRequestType = Endpoint_Read_8();
USB_ControlRequest.bRequest = Endpoint_Read_8();
USB_ControlRequest.wValue = Endpoint_Read_16_LE();
USB_ControlRequest.wIndex = Endpoint_Read_16_LE();
USB_ControlRequest.wLength = Endpoint_Read_16_LE();
#else
uint8_t* RequestHeader = (uint8_t*)&USB_ControlRequest;
for (uint8_t RequestHeaderByte = 0; RequestHeaderByte < sizeof(USB_Request_Header_t); RequestHeaderByte++)
*(RequestHeader++) = Endpoint_Read_8();
#endif
EVENT_USB_Device_ControlRequest();
if (Endpoint_IsSETUPReceived())
{
uint8_t bmRequestType = USB_ControlRequest.bmRequestType;
switch (USB_ControlRequest.bRequest)
{
case REQ_GetStatus:
if ((bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE)) ||
(bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_ENDPOINT)))
{
USB_Device_GetStatus();
}
break;
case REQ_ClearFeature:
case REQ_SetFeature:
if ((bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_DEVICE)) ||
(bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_ENDPOINT)))
{
USB_Device_ClearSetFeature();
}
break;
case REQ_SetAddress:
if (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_DEVICE))
USB_Device_SetAddress();
break;
case REQ_GetDescriptor:
if ((bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE)) ||
(bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_INTERFACE)))
{
USB_Device_GetDescriptor();
}
break;
case REQ_GetConfiguration:
if (bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE))
USB_Device_GetConfiguration();
break;
case REQ_SetConfiguration:
if (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_DEVICE))
USB_Device_SetConfiguration();
break;
default:
break;
}
}
if (Endpoint_IsSETUPReceived())
{
Endpoint_ClearSETUP();
Endpoint_StallTransaction();
}
}
static void USB_Device_SetAddress(void)
{
uint8_t DeviceAddress = (USB_ControlRequest.wValue & 0x7F);
USB_Device_SetDeviceAddress(DeviceAddress);
Endpoint_ClearSETUP();
Endpoint_ClearStatusStage();
while (!(Endpoint_IsINReady()));
USB_Device_EnableDeviceAddress(DeviceAddress);
USB_DeviceState = (DeviceAddress) ? DEVICE_STATE_Addressed : DEVICE_STATE_Default;
}
static void USB_Device_SetConfiguration(void)
{
#if defined(FIXED_NUM_CONFIGURATIONS)
if ((uint8_t)USB_ControlRequest.wValue > FIXED_NUM_CONFIGURATIONS)
return;
#else
USB_Descriptor_Device_t* DevDescriptorPtr;
#if defined(ARCH_HAS_MULTI_ADDRESS_SPACE)
#if defined(USE_FLASH_DESCRIPTORS)
#define MemoryAddressSpace MEMSPACE_FLASH
#elif defined(USE_EEPROM_DESCRIPTORS)
#define MemoryAddressSpace MEMSPACE_EEPROM
#elif defined(USE_RAM_DESCRIPTORS)
#define MemoryAddressSpace MEMSPACE_RAM
#else
uint8_t MemoryAddressSpace;
#endif
#endif
if (CALLBACK_USB_GetDescriptor((DTYPE_Device << 8), 0, (void*)&DevDescriptorPtr
#if defined(ARCH_HAS_MULTI_ADDRESS_SPACE) && \
!(defined(USE_FLASH_DESCRIPTORS) || defined(USE_EEPROM_DESCRIPTORS) || defined(USE_RAM_DESCRIPTORS))
, &MemoryAddressSpace
#endif
) == NO_DESCRIPTOR)
{
return;
}
#if defined(ARCH_HAS_MULTI_ADDRESS_SPACE)
if (MemoryAddressSpace == MEMSPACE_FLASH)
{
if (((uint8_t)USB_ControlRequest.wValue > pgm_read_byte(&DevDescriptorPtr->NumberOfConfigurations)))
return;
}
else if (MemoryAddressSpace == MEMSPACE_EEPROM)
{
if (((uint8_t)USB_ControlRequest.wValue > eeprom_read_byte(&DevDescriptorPtr->NumberOfConfigurations)))
return;
}
else
{
if ((uint8_t)USB_ControlRequest.wValue > DevDescriptorPtr->NumberOfConfigurations)
return;
}
#else
if ((uint8_t)USB_ControlRequest.wValue > DevDescriptorPtr->NumberOfConfigurations)
return;
#endif
#endif
Endpoint_ClearSETUP();
USB_Device_ConfigurationNumber = (uint8_t)USB_ControlRequest.wValue;
Endpoint_ClearStatusStage();
if (USB_Device_ConfigurationNumber)
USB_DeviceState = DEVICE_STATE_Configured;
else
USB_DeviceState = (USB_Device_IsAddressSet()) ? DEVICE_STATE_Configured : DEVICE_STATE_Powered;
EVENT_USB_Device_ConfigurationChanged();
}
static void USB_Device_GetConfiguration(void)
{
Endpoint_ClearSETUP();
Endpoint_Write_8(USB_Device_ConfigurationNumber);
Endpoint_ClearIN();
Endpoint_ClearStatusStage();
}
#if !defined(NO_INTERNAL_SERIAL) && (USE_INTERNAL_SERIAL != NO_DESCRIPTOR)
static void USB_Device_GetInternalSerialDescriptor(void)
{
struct
{
USB_Descriptor_Header_t Header;
uint16_t UnicodeString[INTERNAL_SERIAL_LENGTH_BITS / 4];
} SignatureDescriptor;
SignatureDescriptor.Header.Type = DTYPE_String;
SignatureDescriptor.Header.Size = USB_STRING_LEN(INTERNAL_SERIAL_LENGTH_BITS / 4);
USB_Device_GetSerialString(SignatureDescriptor.UnicodeString);
Endpoint_ClearSETUP();
Endpoint_Write_Control_Stream_LE(&SignatureDescriptor, sizeof(SignatureDescriptor));
Endpoint_ClearOUT();
}
#endif
static void USB_Device_GetDescriptor(void)
{
const void* DescriptorPointer;
uint16_t DescriptorSize;
#if defined(ARCH_HAS_MULTI_ADDRESS_SPACE) && \
!(defined(USE_FLASH_DESCRIPTORS) || defined(USE_EEPROM_DESCRIPTORS) || defined(USE_RAM_DESCRIPTORS))
uint8_t DescriptorAddressSpace;
#endif
#if !defined(NO_INTERNAL_SERIAL) && (USE_INTERNAL_SERIAL != NO_DESCRIPTOR)
if (USB_ControlRequest.wValue == ((DTYPE_String << 8) | USE_INTERNAL_SERIAL))
{
USB_Device_GetInternalSerialDescriptor();
return;
}
#endif
if ((DescriptorSize = CALLBACK_USB_GetDescriptor(USB_ControlRequest.wValue, USB_ControlRequest.wIndex,
&DescriptorPointer
#if defined(ARCH_HAS_MULTI_ADDRESS_SPACE) && \
!(defined(USE_FLASH_DESCRIPTORS) || defined(USE_EEPROM_DESCRIPTORS) || defined(USE_RAM_DESCRIPTORS))
, &DescriptorAddressSpace
#endif
)) == NO_DESCRIPTOR)
{
return;
}
Endpoint_ClearSETUP();
#if defined(USE_RAM_DESCRIPTORS) || !defined(ARCH_HAS_MULTI_ADDRESS_SPACE)
Endpoint_Write_Control_Stream_LE(DescriptorPointer, DescriptorSize);
#elif defined(USE_EEPROM_DESCRIPTORS)
Endpoint_Write_Control_EStream_LE(DescriptorPointer, DescriptorSize);
#elif defined(USE_FLASH_DESCRIPTORS)
Endpoint_Write_Control_PStream_LE(DescriptorPointer, DescriptorSize);
#else
if (DescriptorAddressSpace == MEMSPACE_FLASH)
Endpoint_Write_Control_PStream_LE(DescriptorPointer, DescriptorSize);
else if (DescriptorAddressSpace == MEMSPACE_EEPROM)
Endpoint_Write_Control_EStream_LE(DescriptorPointer, DescriptorSize);
else
Endpoint_Write_Control_Stream_LE(DescriptorPointer, DescriptorSize);
#endif
Endpoint_ClearOUT();
}
static void USB_Device_GetStatus(void)
{
uint8_t CurrentStatus = 0;
switch (USB_ControlRequest.bmRequestType)
{
case (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE):
{
#if !defined(NO_DEVICE_SELF_POWER)
if (USB_Device_CurrentlySelfPowered)
CurrentStatus |= FEATURE_SELFPOWERED_ENABLED;
#endif
#if !defined(NO_DEVICE_REMOTE_WAKEUP)
if (USB_Device_RemoteWakeupEnabled)
CurrentStatus |= FEATURE_REMOTE_WAKEUP_ENABLED;
#endif
break;
}
case (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_ENDPOINT):
{
#if !defined(CONTROL_ONLY_DEVICE)
uint8_t EndpointIndex = ((uint8_t)USB_ControlRequest.wIndex & ENDPOINT_EPNUM_MASK);
if (EndpointIndex >= ENDPOINT_TOTAL_ENDPOINTS)
return;
Endpoint_SelectEndpoint(EndpointIndex);
CurrentStatus = Endpoint_IsStalled();
Endpoint_SelectEndpoint(ENDPOINT_CONTROLEP);
#endif
break;
}
default:
return;
}
Endpoint_ClearSETUP();
Endpoint_Write_16_LE(CurrentStatus);
Endpoint_ClearIN();
Endpoint_ClearStatusStage();
}
static void USB_Device_ClearSetFeature(void)
{
switch (USB_ControlRequest.bmRequestType & CONTROL_REQTYPE_RECIPIENT)
{
#if !defined(NO_DEVICE_REMOTE_WAKEUP)
case REQREC_DEVICE:
{
if ((uint8_t)USB_ControlRequest.wValue == FEATURE_SEL_DeviceRemoteWakeup)
USB_Device_RemoteWakeupEnabled = (USB_ControlRequest.bRequest == REQ_SetFeature);
else
return;
break;
}
#endif
#if !defined(CONTROL_ONLY_DEVICE)
case REQREC_ENDPOINT:
{
if ((uint8_t)USB_ControlRequest.wValue == FEATURE_SEL_EndpointHalt)
{
uint8_t EndpointIndex = ((uint8_t)USB_ControlRequest.wIndex & ENDPOINT_EPNUM_MASK);
if (EndpointIndex == ENDPOINT_CONTROLEP || EndpointIndex >= ENDPOINT_TOTAL_ENDPOINTS)
return;
Endpoint_SelectEndpoint(EndpointIndex);
if (Endpoint_IsEnabled())
{
if (USB_ControlRequest.bRequest == REQ_SetFeature)
{
Endpoint_StallTransaction();
}
else
{
Endpoint_ClearStall();
Endpoint_ResetEndpoint(EndpointIndex);
Endpoint_ResetDataToggle();
}
}
}
break;
}
#endif
default:
return;
}
Endpoint_SelectEndpoint(ENDPOINT_CONTROLEP);
Endpoint_ClearSETUP();
Endpoint_ClearStatusStage();
}
#endif

View file

@ -0,0 +1,158 @@
/*
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 standard request management.
*
* This file contains the function prototypes necessary for the processing of incoming standard control requests
* when the library is in USB device mode.
*
* \note This file should not be included directly. It is automatically included as needed by the USB driver
* dispatch header located in LUFA/Drivers/USB/USB.h.
*/
#ifndef __DEVICESTDREQ_H__
#define __DEVICESTDREQ_H__
/* Includes: */
#include "../../../Common/Common.h"
#include "USBMode.h"
#include "StdDescriptors.h"
#include "Events.h"
#include "StdRequestType.h"
#include "USBTask.h"
#include "USBController.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: */
/* Enums: */
#if defined(ARCH_HAS_MULTI_ADDRESS_SPACE) || defined(__DOXYGEN__)
/** Enum for the possible descriptor memory spaces, for the \c MemoryAddressSpace parameter of the
* \ref CALLBACK_USB_GetDescriptor() function. This can be used when none of the \c USE_*_DESCRIPTORS
* compile time options are used, to indicate in which memory space the descriptor is stored.
*
* \ingroup Group_Device
*/
enum USB_DescriptorMemorySpaces_t
{
#if defined(ARCH_HAS_FLASH_ADDRESS_SPACE) || defined(__DOXYGEN__)
MEMSPACE_FLASH = 0, /**< Indicates the requested descriptor is located in FLASH memory. */
#endif
#if defined(ARCH_HAS_EEPROM_ADDRESS_SPACE) || defined(__DOXYGEN__)
MEMSPACE_EEPROM = 1, /**< Indicates the requested descriptor is located in EEPROM memory. */
#endif
MEMSPACE_RAM = 2, /**< Indicates the requested descriptor is located in RAM memory. */
};
#endif
/* Global Variables: */
/** Indicates the currently set configuration number of the device. USB devices may have several
* different configurations which the host can select between; this indicates the currently selected
* value, or 0 if no configuration has been selected.
*
* \attention This variable should be treated as read-only in the user application, and never manually
* changed in value.
*
* \ingroup Group_Device
*/
extern uint8_t USB_Device_ConfigurationNumber;
#if !defined(NO_DEVICE_REMOTE_WAKEUP)
/** Indicates if the host is currently allowing the device to issue remote wakeup events. If this
* flag is cleared, the device should not issue remote wakeup events to the host.
*
* \attention This variable should be treated as read-only in the user application, and never manually
* changed in value.
*
* \note To reduce FLASH usage of the compiled applications where Remote Wakeup is not supported,
* this global and the underlying management code can be disabled by defining the
* \c NO_DEVICE_REMOTE_WAKEUP token in the project makefile and passing it to the compiler via
* the -D switch.
*
* \ingroup Group_Device
*/
extern bool USB_Device_RemoteWakeupEnabled;
#endif
#if !defined(NO_DEVICE_SELF_POWER)
/** Indicates if the device is currently being powered by its own power supply, rather than being
* powered by the host's USB supply. This flag should remain cleared if the device does not
* support self powered mode, as indicated in the device descriptors.
*
* \ingroup Group_Device
*/
extern bool USB_Device_CurrentlySelfPowered;
#endif
/* Private Interface - For use in library only: */
#if !defined(__DOXYGEN__)
#if defined(USE_RAM_DESCRIPTORS) && defined(USE_EEPROM_DESCRIPTORS)
#error USE_RAM_DESCRIPTORS and USE_EEPROM_DESCRIPTORS are mutually exclusive.
#elif defined(USE_RAM_DESCRIPTORS) && defined(USE_FLASH_DESCRIPTORS)
#error USE_RAM_DESCRIPTORS and USE_FLASH_DESCRIPTORS are mutually exclusive.
#elif defined(USE_FLASH_DESCRIPTORS) && defined(USE_EEPROM_DESCRIPTORS)
#error USE_FLASH_DESCRIPTORS and USE_EEPROM_DESCRIPTORS are mutually exclusive.
#elif defined(USE_FLASH_DESCRIPTORS) && defined(USE_EEPROM_DESCRIPTORS) && defined(USE_RAM_DESCRIPTORS)
#error Only one of the USE_*_DESCRIPTORS modes should be selected.
#endif
/* Function Prototypes: */
void USB_Device_ProcessControlRequest(void);
#if defined(__INCLUDE_FROM_DEVICESTDREQ_C)
static void USB_Device_SetAddress(void);
static void USB_Device_SetConfiguration(void);
static void USB_Device_GetConfiguration(void);
static void USB_Device_GetDescriptor(void);
static void USB_Device_GetStatus(void);
static void USB_Device_ClearSetFeature(void);
#if !defined(NO_INTERNAL_SERIAL) && (USE_INTERNAL_SERIAL != NO_DESCRIPTOR)
static void USB_Device_GetInternalSerialDescriptor(void);
#endif
#endif
#endif
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif

View file

@ -0,0 +1,130 @@
/*
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 all architectures.
* \copydetails Group_EndpointManagement
*
* \note This file should not be included directly. It is automatically included as needed by the USB driver
* dispatch header located in LUFA/Drivers/USB/USB.h.
*/
/** \ingroup Group_EndpointManagement
* \defgroup Group_EndpointRW Endpoint Data Reading and Writing
* \brief Endpoint data read/write definitions.
*
* Functions, macros, variables, enums and types related to data reading and writing from and to endpoints.
*/
/** \ingroup Group_EndpointRW
* \defgroup Group_EndpointPrimitiveRW Read/Write of Primitive Data Types
* \brief Endpoint data primitive read/write definitions.
*
* Functions, macros, variables, enums and types related to data reading and writing of primitive data types
* from and to endpoints.
*/
/** \ingroup Group_EndpointManagement
* \defgroup Group_EndpointPacketManagement Endpoint Packet Management
* \brief USB Endpoint package management definitions.
*
* Functions, macros, variables, enums and types related to packet management of endpoints.
*/
/** \ingroup Group_USB
* \defgroup Group_EndpointManagement Endpoint Management
* \brief Endpoint management definitions.
*
* Functions, macros and enums related to endpoint management when in USB Device mode. This
* module contains the endpoint management macros, as well as endpoint interrupt and data
* send/receive functions for various data types.
*
* @{
*/
#ifndef __ENDPOINT_H__
#define __ENDPOINT_H__
/* Includes: */
#include "../../../Common/Common.h"
#include "USBMode.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: */
/* Type Defines: */
/** Type define for a endpoint table entry, used to configure endpoints in groups via
* \ref Endpoint_ConfigureEndpointTable().
*/
typedef struct
{
uint8_t Address; /**< Address of the endpoint to configure, or zero if the table entry is to be unused. */
uint16_t Size; /**< Size of the endpoint bank, in bytes. */
uint8_t Type; /**< Type of the endpoint, a \c EP_TYPE_* mask. */
uint8_t Banks; /**< Number of hardware banks to use for the endpoint. */
} USB_Endpoint_Table_t;
/* Macros: */
/** Endpoint number mask, for masking against endpoint addresses to retrieve the endpoint's
* numerical address in the device.
*/
#define ENDPOINT_EPNUM_MASK 0x0F
/** Endpoint address for the default control endpoint, which always resides in address 0. This is
* defined for convenience to give more readable code when used with the endpoint macros.
*/
#define ENDPOINT_CONTROLEP 0
/* Architecture Includes: */
#if (ARCH == ARCH_AVR8)
#include "AVR8/Endpoint_AVR8.h"
#elif (ARCH == ARCH_UC3)
#include "UC3/Endpoint_UC3.h"
#elif (ARCH == ARCH_XMEGA)
#include "XMEGA/Endpoint_XMEGA.h"
#endif
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,124 @@
/*
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.
* \copydetails Group_EndpointStreamRW
*
* \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_EndpointStreamRW Read/Write of Multi-Byte Streams
* \brief Endpoint data stream transmission and reception management.
*
* Functions, macros, variables, enums and types related to data reading and writing of data streams from
* and to endpoints.
*
* @{
*/
#ifndef __ENDPOINT_STREAM_H__
#define __ENDPOINT_STREAM_H__
/* Includes: */
#include "../../../Common/Common.h"
#include "USBMode.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: */
/* Enums: */
/** Enum for the possible error return codes of the \c Endpoint_*_Stream_* functions. */
enum Endpoint_Stream_RW_ErrorCodes_t
{
ENDPOINT_RWSTREAM_NoError = 0, /**< Command completed successfully, no error. */
ENDPOINT_RWSTREAM_EndpointStalled = 1, /**< The endpoint was stalled during the stream
* transfer by the host or device.
*/
ENDPOINT_RWSTREAM_DeviceDisconnected = 2, /**< Device was disconnected from the host during
* the transfer.
*/
ENDPOINT_RWSTREAM_BusSuspended = 3, /**< The USB bus has been suspended by the host and
* no USB endpoint traffic can occur until the bus
* has resumed.
*/
ENDPOINT_RWSTREAM_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.
*/
ENDPOINT_RWSTREAM_IncompleteTransfer = 5, /**< Indicates that the endpoint bank became full or empty before
* the complete contents of the current stream could be
* transferred. The endpoint stream function should be called
* again to process the next chunk of data in the transfer.
*/
};
/** Enum for the possible error return codes of the \c Endpoint_*_Control_Stream_* functions. */
enum Endpoint_ControlStream_RW_ErrorCodes_t
{
ENDPOINT_RWCSTREAM_NoError = 0, /**< Command completed successfully, no error. */
ENDPOINT_RWCSTREAM_HostAborted = 1, /**< The aborted the transfer prematurely. */
ENDPOINT_RWCSTREAM_DeviceDisconnected = 2, /**< Device was disconnected from the host during
* the transfer.
*/
ENDPOINT_RWCSTREAM_BusSuspended = 3, /**< The USB bus has been suspended by the host and
* no USB endpoint traffic can occur until the bus
* has resumed.
*/
};
/* Architecture Includes: */
#if (ARCH == ARCH_AVR8)
#include "AVR8/EndpointStream_AVR8.h"
#elif (ARCH == ARCH_UC3)
#include "UC3/EndpointStream_UC3.h"
#elif (ARCH == ARCH_XMEGA)
#include "XMEGA/EndpointStream_XMEGA.h"
#endif
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,39 @@
/*
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.
*/
#define __INCLUDE_FROM_EVENTS_C
#define __INCLUDE_FROM_USB_DRIVER
#include "Events.h"
void USB_Event_Stub(void)
{
}

View file

@ -0,0 +1,372 @@
/*
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 Event management definitions.
* \copydetails Group_Events
*
* \note This file should not be included directly. It is automatically included as needed by the USB driver
* dispatch header located in LUFA/Drivers/USB/USB.h.
*/
/** \ingroup Group_USB
* \defgroup Group_Events USB Events
* \brief USB Event management definitions.
*
* This module contains macros and functions relating to the management of library events, which are small
* pieces of code similar to ISRs which are run when a given condition is met. Each event can be fired from
* multiple places in the user or library code, which may or may not be inside an ISR, thus each handler
* should be written to be as small and fast as possible to prevent possible problems.
*
* Events can be hooked by the user application by declaring a handler function with the same name and parameters
* listed here. If an event with no user-associated handler is fired within the library, it by default maps to an
* internal empty stub function.
*
* Each event must only have one associated event handler, but can be raised by multiple sources by calling the
* event handler function (with any required event parameters).
*
* @{
*/
#ifndef __USBEVENTS_H__
#define __USBEVENTS_H__
/* Includes: */
#include "../../../Common/Common.h"
#include "USBMode.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: */
/* Pseudo-Functions for Doxygen: */
#if !defined(__INCLUDE_FROM_EVENTS_C) || defined(__DOXYGEN__)
/** Event for USB mode pin level change. This event fires when the USB interface is set to dual role
* mode, and the UID pin level has changed to indicate a new mode (device or host). This event fires
* before the mode is switched to the newly indicated mode but after the \ref EVENT_USB_Device_Disconnect
* event has fired (if disconnected before the role change).
*
* \note This event only exists on microcontrollers that support dual role USB modes.
* \n\n
*
* \note This event does not exist if the \c USB_DEVICE_ONLY or \c USB_HOST_ONLY tokens have been supplied
* to the compiler (see \ref Group_USBManagement documentation).
*/
void EVENT_USB_UIDChange(void);
/** Event for USB host error. This event fires when a hardware fault has occurred whilst the USB
* interface is in host mode.
*
* \param[in] ErrorCode Error code indicating the failure reason, a value in \ref USB_Host_ErrorCodes_t.
*
* \note This event only exists on microcontrollers that supports USB host mode.
* \n\n
*
* \note This event does not exist if the \c USB_DEVICE_ONLY token is supplied to the compiler (see
* \ref Group_USBManagement documentation).
*/
void EVENT_USB_Host_HostError(const uint8_t ErrorCode);
/** Event for USB device attachment. This event fires when a the USB interface is in host mode, and
* a USB device has been connected to the USB interface. This is interrupt driven, thus fires before
* the standard \ref EVENT_USB_Device_Connect() event and so can be used to programmatically start the USB
* management task to reduce CPU consumption.
*
* \note This event only exists on microcontrollers that supports USB host mode.
* \n\n
*
* \note This event does not exist if the \c USB_DEVICE_ONLY token is supplied to the compiler (see
* \ref Group_USBManagement documentation).
*
* \see \ref USB_USBTask() for more information on the USB management task and reducing CPU usage.
*/
void EVENT_USB_Host_DeviceAttached(void);
/** Event for USB device removal. This event fires when a the USB interface is in host mode, and
* a USB device has been removed the USB interface whether or not it has been enumerated. This
* can be used to programmatically stop the USB management task to reduce CPU consumption.
*
* \note This event only exists on microcontrollers that supports USB host mode.
* \n\n
*
* \note This event does not exist if the \c USB_DEVICE_ONLY token is supplied to the compiler (see
* \ref Group_USBManagement documentation).
*
* \see \ref USB_USBTask() for more information on the USB management task and reducing CPU usage.
*/
void EVENT_USB_Host_DeviceUnattached(void);
/** Event for USB device enumeration failure. This event fires when a the USB interface is
* in host mode, and an attached USB device has failed to enumerate completely.
*
* \param[in] ErrorCode Error code indicating the failure reason, a value in
* \ref USB_Host_EnumerationErrorCodes_t.
*
* \param[in] SubErrorCode Sub error code indicating the reason for failure - for example, if the
* ErrorCode parameter indicates a control error, this will give the error
* code returned by the \ref USB_Host_SendControlRequest() function.
*
* \note This event only exists on microcontrollers that supports USB host mode.
* \n\n
*
* \note This event does not exist if the \c USB_DEVICE_ONLY token is supplied to the compiler (see
* \ref Group_USBManagement documentation).
*/
void EVENT_USB_Host_DeviceEnumerationFailed(const uint8_t ErrorCode,
const uint8_t SubErrorCode);
/** Event for USB device enumeration completion. This event fires when a the USB interface is
* in host mode and an attached USB device has been completely enumerated and is ready to be
* controlled by the user application.
*
* This event is time-critical; exceeding OS-specific delays within this event handler (typically of around
* 1 second) when a transaction is waiting to be processed by the device will prevent break communications
* and cause the host to reset the USB bus.
*
* \note This event only exists on microcontrollers that supports USB host mode.
* \n\n
*
* \note This event does not exist if the \c USB_DEVICE_ONLY token is supplied to the compiler (see
* \ref Group_USBManagement documentation).
*/
void EVENT_USB_Host_DeviceEnumerationComplete(void);
/** Event for USB Start Of Frame detection, when enabled. This event fires at the start of each USB
* frame, once per millisecond, and is synchronized to the USB bus. This can be used as an accurate
* millisecond timer source when the USB bus is not suspended while in host mode.
*
* This event is time-critical; it is run once per millisecond and thus long handlers will significantly
* degrade device performance. This event should only be enabled when needed to reduce device wake-ups.
*
* \note This event is not normally active - it must be manually enabled and disabled via the
* \ref USB_Host_EnableSOFEvents() and \ref USB_Host_DisableSOFEvents() commands after enumeration of
* a USB device.
* \n\n
*
* \note This event does not exist if the \c USB_DEVICE_ONLY token is supplied to the compiler (see
* \ref Group_USBManagement documentation).
*/
void EVENT_USB_Host_StartOfFrame(void);
/** Event for USB device connection. This event fires when the microcontroller is in USB Device mode
* and the device is connected to a USB host, beginning the enumeration process measured by a rising
* level on the microcontroller's VBUS sense pin.
*
* This event is time-critical; exceeding OS-specific delays within this event handler (typically of around
* two seconds) will prevent the device from enumerating correctly.
*
* \attention This event may fire multiple times during device enumeration on the microcontrollers with limited USB controllers
* if \c NO_LIMITED_CONTROLLER_CONNECT is not defined.
*
* \note For the microcontrollers with limited USB controller functionality, VBUS sensing is not available.
* this means that the current connection state is derived from the bus suspension and wake up events by default,
* which is not always accurate (host may suspend the bus while still connected). If the actual connection state
* needs to be determined, VBUS should be routed to an external pin, and the auto-detect behavior turned off by
* passing the \c NO_LIMITED_CONTROLLER_CONNECT token to the compiler via the -D switch at compile time. The connection
* and disconnection events may be manually fired, and the \ref USB_DeviceState global changed manually.
* \n\n
*
* \see \ref Group_USBManagement for more information on the USB management task and reducing CPU usage.
*/
void EVENT_USB_Device_Connect(void);
/** Event for USB device disconnection. This event fires when the microcontroller is in USB Device mode and the device is
* disconnected from a host, measured by a falling level on the microcontroller's VBUS sense pin.
*
* \attention This event may fire multiple times during device enumeration on the microcontrollers with limited USB controllers
* if \c NO_LIMITED_CONTROLLER_CONNECT is not defined.
*
* \note For the microcontrollers with limited USB controllers, VBUS sense is not available to the USB controller.
* this means that the current connection state is derived from the bus suspension and wake up events by default,
* which is not always accurate (host may suspend the bus while still connected). If the actual connection state
* needs to be determined, VBUS should be routed to an external pin, and the auto-detect behavior turned off by
* passing the \c NO_LIMITED_CONTROLLER_CONNECT token to the compiler via the -D switch at compile time. The connection
* and disconnection events may be manually fired, and the \ref USB_DeviceState global changed manually.
* \n\n
*
* \see \ref Group_USBManagement for more information on the USB management task and reducing CPU usage.
*/
void EVENT_USB_Device_Disconnect(void);
/** Event for control requests. This event fires when a the USB host issues a control request
* to the mandatory device control endpoint (of address 0). This may either be a standard
* request that the library may have a handler code for internally, or a class specific request
* issued to the device which must be handled appropriately. If a request is not processed in the
* user application via this event, it will be passed to the library for processing internally
* if a suitable handler exists.
*
* This event is time-critical; each packet within the request transaction must be acknowledged or
* sent within 50ms or the host will abort the transfer.
*
* The library internally handles all standard control requests with the exceptions of SYNC FRAME,
* SET DESCRIPTOR and SET INTERFACE. These and all other non-standard control requests will be left
* for the user to process via this event if desired. If not handled in the user application or by
* the library internally, unknown requests are automatically STALLed.
*
* \note This event does not exist if the \c USB_HOST_ONLY token is supplied to the compiler (see
* \ref Group_USBManagement documentation).
* \n\n
*
* \note Requests should be handled in the same manner as described in the USB 2.0 Specification,
* or appropriate class specification. In all instances, the library has already read the
* request SETUP parameters into the \ref USB_ControlRequest structure which should then be used
* by the application to determine how to handle the issued request.
*/
void EVENT_USB_Device_ControlRequest(void);
/** Event for USB configuration number changed. This event fires when a the USB host changes the
* selected configuration number while in device mode. This event should be hooked in device
* applications to create the endpoints and configure the device for the selected configuration.
*
* This event is time-critical; exceeding OS-specific delays within this event handler (typically of around
* one second) will prevent the device from enumerating correctly.
*
* This event fires after the value of \ref USB_Device_ConfigurationNumber has been changed.
*
* \note This event does not exist if the \c USB_HOST_ONLY token is supplied to the compiler (see
* \ref Group_USBManagement documentation).
*/
void EVENT_USB_Device_ConfigurationChanged(void);
/** Event for USB suspend. This event fires when a the USB host suspends the device by halting its
* transmission of Start Of Frame pulses to the device. This is generally hooked in order to move
* the device over to a low power state until the host wakes up the device. If the USB interface is
* enumerated with the \ref USB_OPT_AUTO_PLL option set, the library will automatically suspend the
* USB PLL before the event is fired to save power.
*
* \note This event does not exist if the \c USB_HOST_ONLY token is supplied to the compiler (see
* \ref Group_USBManagement documentation).
* \n\n
*
* \note This event does not exist on the microcontrollers with limited USB VBUS sensing abilities
* when the \c NO_LIMITED_CONTROLLER_CONNECT compile time token is not set - see
* \ref EVENT_USB_Device_Disconnect.
*
* \see \ref EVENT_USB_Device_WakeUp() event for accompanying Wake Up event.
*/
void EVENT_USB_Device_Suspend(void);
/** Event for USB wake up. This event fires when a the USB interface is suspended while in device
* mode, and the host wakes up the device by supplying Start Of Frame pulses. This is generally
* hooked to pull the user application out of a low power state and back into normal operating
* mode. If the USB interface is enumerated with the \ref USB_OPT_AUTO_PLL option set, the library
* will automatically restart the USB PLL before the event is fired.
*
* \note This event does not exist if the \c USB_HOST_ONLY token is supplied to the compiler (see
* \ref Group_USBManagement documentation).
* \n\n
*
* \note This event does not exist on the microcontrollers with limited USB VBUS sensing abilities
* when the \c NO_LIMITED_CONTROLLER_CONNECT compile time token is not set - see
* \ref EVENT_USB_Device_Disconnect.
*
* \see \ref EVENT_USB_Device_Suspend() event for accompanying Suspend event.
*/
void EVENT_USB_Device_WakeUp(void);
/** Event for USB interface reset. This event fires when the USB interface is in device mode, and
* a the USB host requests that the device reset its interface. This event fires after the control
* endpoint has been automatically configured by the library.
*
* This event is time-critical; exceeding OS-specific delays within this event handler (typically of around
* two seconds) will prevent the device from enumerating correctly.
*
* \note This event does not exist if the \c USB_HOST_ONLY token is supplied to the compiler (see
* \ref Group_USBManagement documentation).
*/
void EVENT_USB_Device_Reset(void);
/** Event for USB Start Of Frame detection, when enabled. This event fires at the start of each USB
* frame, once per millisecond, and is synchronized to the USB bus. This can be used as an accurate
* millisecond timer source when the USB bus is enumerated in device mode to a USB host.
*
* This event is time-critical; it is run once per millisecond and thus long handlers will significantly
* degrade device performance. This event should only be enabled when needed to reduce device wake-ups.
*
* \pre This event is not normally active - it must be manually enabled and disabled via the
* \ref USB_Device_EnableSOFEvents() and \ref USB_Device_DisableSOFEvents() commands after enumeration.
* \n\n
*
* \note This event does not exist if the \c USB_HOST_ONLY token is supplied to the compiler (see
* \ref Group_USBManagement documentation).
*/
void EVENT_USB_Device_StartOfFrame(void);
#endif
/* Private Interface - For use in library only: */
#if !defined(__DOXYGEN__)
/* Function Prototypes: */
#if defined(__INCLUDE_FROM_EVENTS_C)
void USB_Event_Stub(void) ATTR_CONST;
#if defined(USB_CAN_BE_BOTH)
void EVENT_USB_UIDChange(void) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub);
#endif
#if defined(USB_CAN_BE_HOST)
void EVENT_USB_Host_HostError(const uint8_t ErrorCode) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub);
void EVENT_USB_Host_DeviceAttached(void) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub);
void EVENT_USB_Host_DeviceUnattached(void) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub);
void EVENT_USB_Host_DeviceEnumerationComplete(void) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub);
void EVENT_USB_Host_DeviceEnumerationFailed(const uint8_t ErrorCode,
const uint8_t SubErrorCode)
ATTR_WEAK ATTR_ALIAS(USB_Event_Stub);
void EVENT_USB_Host_StartOfFrame(void) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub);
#endif
#if defined(USB_CAN_BE_DEVICE)
void EVENT_USB_Device_Connect(void) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub);
void EVENT_USB_Device_Disconnect(void) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub);
void EVENT_USB_Device_ControlRequest(void) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub);
void EVENT_USB_Device_ConfigurationChanged(void) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub);
void EVENT_USB_Device_Suspend(void) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub);
void EVENT_USB_Device_WakeUp(void) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub);
void EVENT_USB_Device_Reset(void) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub);
void EVENT_USB_Device_StartOfFrame(void) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub);
#endif
#endif
#endif
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,139 @@
/*
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 Common USB Host definitions for all architectures.
* \copydetails Group_Host
*
* \note This file should not be included directly. It is automatically included as needed by the USB driver
* dispatch header located in LUFA/Drivers/USB/USB.h.
*/
/** \ingroup Group_USB
* \defgroup Group_Host Host Management
* \brief USB Host management definitions for USB host mode.
*
* USB Host mode related macros and enums. This module contains macros and enums which are used when
* the USB controller is initialized in host mode.
*
* @{
*/
#ifndef __USBHOST_H__
#define __USBHOST_H__
/* Includes: */
#include "../../../Common/Common.h"
#include "USBMode.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: */
/* Enums: */
/** Enum for the various states of the USB Host state machine.
*
* For information on each possible USB host state, refer to the USB 2.0 specification.
* Several of the USB host states are broken up further into multiple smaller sub-states,
* so that they can be internally implemented inside the library in an efficient manner.
*
* \see \ref USB_HostState, which stores the current host state machine state.
*/
enum USB_Host_States_t
{
HOST_STATE_WaitForDevice = 0, /**< This state indicates that the stack is waiting for an interval
* to elapse before continuing with the next step of the device
* enumeration process.
*/
HOST_STATE_Unattached = 1, /**< This state indicates that the host state machine is waiting for
* a device to be attached so that it can start the enumeration process.
*/
HOST_STATE_Powered = 2, /**< This state indicates that a device has been attached, and the
* library's internals are being configured to begin the enumeration
* process.
*/
HOST_STATE_Powered_WaitForDeviceSettle = 3, /**< This state indicates that the stack is waiting for the initial
* settling period to elapse before beginning the enumeration process.
*/
HOST_STATE_Powered_WaitForConnect = 4, /**< This state indicates that the stack is waiting for a connection event
* from the USB controller to indicate a valid USB device has been attached
* to the bus and is ready to be enumerated.
*/
HOST_STATE_Powered_DoReset = 5, /**< This state indicates that a valid USB device has been attached, and that
* it will now be reset to ensure it is ready for enumeration.
*/
HOST_STATE_Powered_ConfigPipe = 6, /**< This state indicates that the attached device is currently powered and
* reset, and that the control pipe is now being configured by the stack.
*/
HOST_STATE_Default = 7, /**< This state indicates that the stack is currently retrieving the control
* endpoint's size from the device, so that the control pipe can be altered
* to match.
*/
HOST_STATE_Default_PostReset = 8, /**< This state indicates that the control pipe is being reconfigured to match
* the retrieved control endpoint size from the device, and the device's USB
* bus address is being set.
*/
HOST_STATE_Default_PostAddressSet = 9, /**< This state indicates that the device's address has now been set, and the
* stack is has now completed the device enumeration process. This state causes
* the stack to change the current USB device address to that set for the
* connected device, before progressing to the \ref HOST_STATE_Addressed state
* ready for use in the user application.
*/
HOST_STATE_Addressed = 10, /**< Indicates that the device has been enumerated and addressed, and is now waiting
* for the user application to configure the device ready for use.
*/
HOST_STATE_Configured = 11, /**< Indicates that the device has been configured into a valid device configuration,
* ready for general use by the user application.
*/
};
/* Architecture Includes: */
#if (ARCH == ARCH_AVR8)
#include "AVR8/Host_AVR8.h"
#elif (ARCH == ARCH_UC3)
#include "UC3/Host_UC3.h"
#endif
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,322 @@
/*
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.
*/
#define __INCLUDE_FROM_USB_DRIVER
#include "USBMode.h"
#if defined(USB_CAN_BE_HOST)
#define __INCLUDE_FROM_HOSTSTDREQ_C
#include "HostStandardReq.h"
uint8_t USB_Host_ConfigurationNumber;
static uint8_t USB_Host_SendControlRequest_PRV(void* const BufferPtr)
{
uint8_t* DataStream = (uint8_t*)BufferPtr;
uint8_t ReturnStatus = HOST_SENDCONTROL_Successful;
uint16_t DataLen = USB_ControlRequest.wLength;
USB_Host_ResumeBus();
if ((ReturnStatus = USB_Host_WaitMS(1)) != HOST_WAITERROR_Successful)
return ReturnStatus;
Pipe_SetPipeToken(PIPE_TOKEN_SETUP);
Pipe_ClearError();
Pipe_Unfreeze();
#if defined(ARCH_BIG_ENDIAN)
Pipe_Write_8(USB_ControlRequest.bmRequestType);
Pipe_Write_8(USB_ControlRequest.bRequest);
Pipe_Write_16_LE(USB_ControlRequest.wValue);
Pipe_Write_16_LE(USB_ControlRequest.wIndex);
Pipe_Write_16_LE(USB_ControlRequest.wLength);
#else
uint8_t* HeaderStream = (uint8_t*)&USB_ControlRequest;
for (uint8_t HeaderByte = 0; HeaderByte < sizeof(USB_Request_Header_t); HeaderByte++)
Pipe_Write_8(*(HeaderStream++));
#endif
Pipe_ClearSETUP();
if ((ReturnStatus = USB_Host_WaitForIOS(USB_HOST_WAITFOR_SetupSent)) != HOST_SENDCONTROL_Successful)
return ReturnStatus;
Pipe_Freeze();
if ((ReturnStatus = USB_Host_WaitMS(1)) != HOST_WAITERROR_Successful)
return ReturnStatus;
if ((USB_ControlRequest.bmRequestType & CONTROL_REQTYPE_DIRECTION) == REQDIR_DEVICETOHOST)
{
Pipe_SetPipeToken(PIPE_TOKEN_IN);
if (DataStream != NULL)
{
while (DataLen)
{
Pipe_Unfreeze();
if ((ReturnStatus = USB_Host_WaitForIOS(USB_HOST_WAITFOR_InReceived)) != HOST_SENDCONTROL_Successful)
return ReturnStatus;
if (!(Pipe_BytesInPipe()))
DataLen = 0;
while (Pipe_BytesInPipe() && DataLen)
{
*(DataStream++) = Pipe_Read_8();
DataLen--;
}
Pipe_Freeze();
Pipe_ClearIN();
}
}
Pipe_SetPipeToken(PIPE_TOKEN_OUT);
Pipe_Unfreeze();
if ((ReturnStatus = USB_Host_WaitForIOS(USB_HOST_WAITFOR_OutReady)) != HOST_SENDCONTROL_Successful)
return ReturnStatus;
Pipe_ClearOUT();
if ((ReturnStatus = USB_Host_WaitForIOS(USB_HOST_WAITFOR_OutReady)) != HOST_SENDCONTROL_Successful)
return ReturnStatus;
}
else
{
if (DataStream != NULL)
{
Pipe_SetPipeToken(PIPE_TOKEN_OUT);
Pipe_Unfreeze();
while (DataLen)
{
if ((ReturnStatus = USB_Host_WaitForIOS(USB_HOST_WAITFOR_OutReady)) != HOST_SENDCONTROL_Successful)
return ReturnStatus;
while (DataLen && (Pipe_BytesInPipe() < USB_Host_ControlPipeSize))
{
Pipe_Write_8(*(DataStream++));
DataLen--;
}
Pipe_ClearOUT();
}
if ((ReturnStatus = USB_Host_WaitForIOS(USB_HOST_WAITFOR_OutReady)) != HOST_SENDCONTROL_Successful)
return ReturnStatus;
Pipe_Freeze();
}
Pipe_SetPipeToken(PIPE_TOKEN_IN);
Pipe_Unfreeze();
if ((ReturnStatus = USB_Host_WaitForIOS(USB_HOST_WAITFOR_InReceived)) != HOST_SENDCONTROL_Successful)
return ReturnStatus;
Pipe_ClearIN();
}
return ReturnStatus;
}
static uint8_t USB_Host_WaitForIOS(const uint8_t WaitType)
{
#if (USB_HOST_TIMEOUT_MS < 0xFF)
uint8_t TimeoutCounter = USB_HOST_TIMEOUT_MS;
#else
uint16_t TimeoutCounter = USB_HOST_TIMEOUT_MS;
#endif
while (!(((WaitType == USB_HOST_WAITFOR_SetupSent) && Pipe_IsSETUPSent()) ||
((WaitType == USB_HOST_WAITFOR_InReceived) && Pipe_IsINReceived()) ||
((WaitType == USB_HOST_WAITFOR_OutReady) && Pipe_IsOUTReady())))
{
uint8_t ErrorCode;
if ((ErrorCode = USB_Host_WaitMS(1)) != HOST_WAITERROR_Successful)
return ErrorCode;
if (!(TimeoutCounter--))
return HOST_SENDCONTROL_SoftwareTimeOut;
}
return HOST_SENDCONTROL_Successful;
}
uint8_t USB_Host_SendControlRequest(void* const BufferPtr)
{
bool BusSuspended = USB_Host_IsBusSuspended();
uint8_t ReturnStatus = USB_Host_SendControlRequest_PRV(BufferPtr);
Pipe_Freeze();
if (BusSuspended)
USB_Host_SuspendBus();
Pipe_ResetPipe(PIPE_CONTROLPIPE);
return ReturnStatus;
}
uint8_t USB_Host_SetDeviceConfiguration(const uint8_t ConfigNumber)
{
uint8_t ErrorCode;
USB_ControlRequest = (USB_Request_Header_t)
{
.bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_DEVICE),
.bRequest = REQ_SetConfiguration,
.wValue = ConfigNumber,
.wIndex = 0,
.wLength = 0,
};
Pipe_SelectPipe(PIPE_CONTROLPIPE);
if ((ErrorCode = USB_Host_SendControlRequest(NULL)) == HOST_SENDCONTROL_Successful)
{
USB_Host_ConfigurationNumber = ConfigNumber;
USB_HostState = (ConfigNumber) ? HOST_STATE_Configured : HOST_STATE_Addressed;
}
return ErrorCode;
}
uint8_t USB_Host_GetDeviceConfiguration(uint8_t* const ConfigNumber)
{
USB_ControlRequest = (USB_Request_Header_t)
{
.bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE),
.bRequest = REQ_GetConfiguration,
.wValue = 0,
.wIndex = 0,
.wLength = sizeof(uint8_t),
};
Pipe_SelectPipe(PIPE_CONTROLPIPE);
return USB_Host_SendControlRequest(ConfigNumber);
}
uint8_t USB_Host_GetDescriptor(const uint8_t Type,
const uint8_t Index,
void* const Buffer,
const uint8_t BufferLength)
{
USB_ControlRequest = (USB_Request_Header_t)
{
.bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE),
.bRequest = REQ_GetDescriptor,
.wValue = (((uint16_t)Type << 8) | Index),
.wIndex = 0,
.wLength = BufferLength,
};
Pipe_SelectPipe(PIPE_CONTROLPIPE);
return USB_Host_SendControlRequest(Buffer);
}
uint8_t USB_Host_GetDeviceStatus(uint8_t* const FeatureStatus)
{
USB_ControlRequest = (USB_Request_Header_t)
{
.bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE),
.bRequest = REQ_GetStatus,
.wValue = 0,
.wIndex = 0,
.wLength = 0,
};
Pipe_SelectPipe(PIPE_CONTROLPIPE);
return USB_Host_SendControlRequest(FeatureStatus);
}
uint8_t USB_Host_ClearEndpointStall(const uint8_t EndpointAddress)
{
USB_ControlRequest = (USB_Request_Header_t)
{
.bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_ENDPOINT),
.bRequest = REQ_ClearFeature,
.wValue = FEATURE_SEL_EndpointHalt,
.wIndex = EndpointAddress,
.wLength = 0,
};
Pipe_SelectPipe(PIPE_CONTROLPIPE);
return USB_Host_SendControlRequest(NULL);
}
uint8_t USB_Host_SetInterfaceAltSetting(const uint8_t InterfaceIndex,
const uint8_t AltSetting)
{
USB_ControlRequest = (USB_Request_Header_t)
{
.bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_INTERFACE),
.bRequest = REQ_SetInterface,
.wValue = AltSetting,
.wIndex = InterfaceIndex,
.wLength = 0,
};
Pipe_SelectPipe(PIPE_CONTROLPIPE);
return USB_Host_SendControlRequest(NULL);
}
uint8_t USB_Host_GetInterfaceAltSetting(const uint8_t InterfaceIndex,
uint8_t* const AltSetting)
{
USB_ControlRequest = (USB_Request_Header_t)
{
.bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_INTERFACE),
.bRequest = REQ_GetInterface,
.wValue = 0,
.wIndex = InterfaceIndex,
.wLength = sizeof(uint8_t),
};
Pipe_SelectPipe(PIPE_CONTROLPIPE);
return USB_Host_SendControlRequest(AltSetting);
}
#endif

View file

@ -0,0 +1,292 @@
/*
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 standard request management.
*
* This file contains the function prototypes necessary for the issuing of outgoing standard control requests
* when the library is in USB host mode.
*
* \note This file should not be included directly. It is automatically included as needed by the USB driver
* dispatch header located in LUFA/Drivers/USB/USB.h.
*/
#ifndef __HOSTSTDREQ_H__
#define __HOSTSTDREQ_H__
/* Includes: */
#include "../../../Common/Common.h"
#include "USBMode.h"
#include "StdRequestType.h"
#include "USBController.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: */
#if !defined(USB_HOST_TIMEOUT_MS) || defined(__DOXYGEN__)
/** Constant for the maximum software timeout period of sent USB control transactions to an attached
* device. If a device fails to respond to a sent control request within this period, the
* library will return a timeout error code.
*
* This value may be overridden in the user project makefile as the value of the
* \ref USB_HOST_TIMEOUT_MS token, and passed to the compiler using the -D switch.
*/
#define USB_HOST_TIMEOUT_MS 1000
#endif
/* Enums: */
/** Enum for the \ref USB_Host_SendControlRequest() return code, indicating the reason for the error
* if the transfer of the request is unsuccessful.
*
* \ingroup Group_PipeControlReq
*/
enum USB_Host_SendControlErrorCodes_t
{
HOST_SENDCONTROL_Successful = 0, /**< No error occurred in the request transfer. */
HOST_SENDCONTROL_DeviceDisconnected = 1, /**< The attached device was disconnected during the
* request transfer.
*/
HOST_SENDCONTROL_PipeError = 2, /**< An error occurred in the pipe while sending the request. */
HOST_SENDCONTROL_SetupStalled = 3, /**< The attached device stalled the request, usually
* indicating that the request is unsupported on the device.
*/
HOST_SENDCONTROL_SoftwareTimeOut = 4, /**< The request or data transfer timed out. */
};
/* Global Variables: */
/** Indicates the currently set configuration number of the attached device. This indicates the currently
* selected configuration value if one has been set successfully, or 0 if no configuration has been selected.
*
* To set a device configuration, call the \ref USB_Host_SetDeviceConfiguration() function.
*
* \attention This variable should be treated as read-only in the user application, and never manually
* changed in value.
*
* \ingroup Group_Host
*/
extern uint8_t USB_Host_ConfigurationNumber;
/* Function Prototypes: */
/** Sends the request stored in the \ref USB_ControlRequest global structure to the attached device,
* and transfers the data stored in the buffer to the device, or from the device to the buffer
* as requested. The transfer is made on the currently selected pipe.
*
* \ingroup Group_PipeControlReq
*
* \param[in] BufferPtr Pointer to the start of the data buffer if the request has a data stage, or
* \c NULL if the request transfers no data to or from the device.
*
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum to indicate the result.
*/
uint8_t USB_Host_SendControlRequest(void* const BufferPtr);
/** Sends a SET CONFIGURATION standard request to the attached device, with the given configuration index.
*
* This routine will automatically update the \ref USB_HostState and \ref USB_Host_ConfigurationNumber
* state variables according to the given function parameters and the result of the request.
*
* \note After this routine returns, the control pipe will be selected.
*
* \ingroup Group_PipeControlReq
*
* \param[in] ConfigNumber Configuration index to send to the device.
*
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum to indicate the result.
*/
uint8_t USB_Host_SetDeviceConfiguration(const uint8_t ConfigNumber);
/** Sends a GET CONFIGURATION standard request to the attached device, to retrieve the currently selected
* device configuration index.
*
* \note After this routine returns, the control pipe will be selected.
*
* \ingroup Group_PipeControlReq
*
* \param[out] ConfigNumber Pointer to a location where the retrieved configuration index should be stored.
*
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum to indicate the result.
*/
uint8_t USB_Host_GetDeviceConfiguration(uint8_t* const ConfigNumber) ATTR_NON_NULL_PTR_ARG(1);
/** Sends a GET DESCRIPTOR standard request to the attached device, requesting the descriptor of the
* specified type and index.
*
* \note After this routine returns, the control pipe will be selected.
*
* \ingroup Group_PipeControlReq
*
* \param[in] Type Type of descriptor to retrieve, a value from the \ref USB_DescriptorTypes_t enum.
* \param[in] Index Index of the descriptor to retrieve.
* \param[out] Buffer Pointer to the destination buffer where the retrieved string descriptor is to be stored.
* \param[in] BufferLength Maximum size of the string descriptor which can be stored into the buffer.
*
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum to indicate the result.
*/
uint8_t USB_Host_GetDescriptor(const uint8_t Type,
const uint8_t Index,
void* const Buffer,
const uint8_t BufferLength) ATTR_NON_NULL_PTR_ARG(3);
/** Retrieves the current feature status of the attached device, via a GET STATUS standard request. The
* retrieved feature status can then be examined by masking the retrieved value with the various
* \c FEATURE_* masks for bus/self power information and remote wakeup support.
*
* \note After this routine returns, the control pipe will be selected.
*
* \ingroup Group_PipeControlReq
*
* \param[out] FeatureStatus Location where the retrieved feature status should be stored.
*
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum to indicate the result.
*/
uint8_t USB_Host_GetDeviceStatus(uint8_t* const FeatureStatus) ATTR_NON_NULL_PTR_ARG(1);
/** Clears a stall condition on the given pipe, via a CLEAR FEATURE standard request to the attached device.
*
* \note After this routine returns, the control pipe will be selected.
*
* \ingroup Group_PipeControlReq
*
* \param[in] EndpointAddress Address of the endpoint to clear, including the endpoint's direction.
*
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum to indicate the result.
*/
uint8_t USB_Host_ClearEndpointStall(const uint8_t EndpointAddress);
/** Selects a given alternative setting for the specified interface, via a SET INTERFACE standard request to
* the attached device.
*
* \note After this routine returns, the control pipe will be selected.
*
* \ingroup Group_PipeControlReq
*
* \param[in] InterfaceIndex Index of the interface whose alternative setting is to be altered.
* \param[in] AltSetting Index of the interface's alternative setting which is to be selected.
*
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum to indicate the result.
*/
uint8_t USB_Host_SetInterfaceAltSetting(const uint8_t InterfaceIndex,
const uint8_t AltSetting);
/** Retrieves the current alternative setting for the specified interface, via a GET INTERFACE standard request to
* the attached device.
*
* \note After this routine returns, the control pipe will be selected.
*
* \ingroup Group_PipeControlReq
*
* \param[in] InterfaceIndex Index of the interface whose alternative setting is to be altered.
* \param[out] AltSetting Pointer to a location where the retrieved alternative setting value should be stored.
*
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum to indicate the result.
*/
uint8_t USB_Host_GetInterfaceAltSetting(const uint8_t InterfaceIndex,
uint8_t* const AltSetting) ATTR_NON_NULL_PTR_ARG(2);
/* Inline Functions: */
/** Sends a GET DESCRIPTOR standard request to the attached device, requesting the device descriptor.
* This can be used to easily retrieve information about the device such as its VID, PID and power
* requirements. This is a convenience wrapper for \ref USB_Host_GetDescriptor().
*
* \note After this routine returns, the control pipe will be selected.
*
* \ingroup Group_PipeControlReq
*
* \param[out] DeviceDescriptorPtr Pointer to the destination device descriptor structure where
* the read data is to be stored.
*
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum to indicate the result.
*/
static inline uint8_t USB_Host_GetDeviceDescriptor(USB_Descriptor_Device_t* const DeviceDescriptorPtr) ATTR_NON_NULL_PTR_ARG(1);
static inline uint8_t USB_Host_GetDeviceDescriptor(USB_Descriptor_Device_t* const DeviceDescriptorPtr)
{
return USB_Host_GetDescriptor(DTYPE_Device, 0, DeviceDescriptorPtr, sizeof(USB_Descriptor_Device_t));
}
/** Sends a GET DESCRIPTOR standard request to the attached device, requesting the string descriptor
* of the specified index. This can be used to easily retrieve string descriptors from the device by
* index, after the index is obtained from the Device or Configuration descriptors. This is a convenience
* wrapper for \ref USB_Host_GetDescriptor().
*
* \note After this routine returns, the control pipe will be selected.
*
* \ingroup Group_PipeControlReq
*
* \param[in] Index Index of the string descriptor to retrieve.
* \param[out] Buffer Pointer to the destination buffer where the retrieved string descriptor is
* to be stored.
* \param[in] BufferLength Maximum size of the string descriptor which can be stored into the buffer.
*
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum to indicate the result.
*/
static inline uint8_t USB_Host_GetDeviceStringDescriptor(const uint8_t Index,
void* const Buffer,
const uint8_t BufferLength) ATTR_NON_NULL_PTR_ARG(2);
static inline uint8_t USB_Host_GetDeviceStringDescriptor(const uint8_t Index,
void* const Buffer,
const uint8_t BufferLength)
{
return USB_Host_GetDescriptor(DTYPE_String, Index, Buffer, BufferLength);
}
/* Private Interface - For use in library only: */
#if !defined(__DOXYGEN__)
/* Enums: */
enum USB_WaitForTypes_t
{
USB_HOST_WAITFOR_SetupSent,
USB_HOST_WAITFOR_InReceived,
USB_HOST_WAITFOR_OutReady,
};
/* Function Prototypes: */
#if defined(__INCLUDE_FROM_HOSTSTDREQ_C)
static uint8_t USB_Host_SendControlRequest_PRV(void* const BufferPtr);
static uint8_t USB_Host_WaitForIOS(const uint8_t WaitType);
#endif
#endif
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif

View file

@ -0,0 +1,80 @@
/*
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 Common USB OTG definitions for all architectures.
* \copydetails Group_OTG
*
* \note This file should not be included directly. It is automatically included as needed by the USB driver
* dispatch header located in LUFA/Drivers/USB/USB.h.
*/
/** \ingroup Group_USB
* \defgroup Group_OTG USB On The Go (OTG) Management
* \brief USB OTG management definitions.
*
* This module contains macros for embedded USB hosts with dual role On The Go capabilities, for managing role
* exchange. OTG is a way for two USB dual role devices to talk to one another directly without fixed device/host
* roles.
*
* @{
*/
#ifndef __USBOTG_H__
#define __USBOTG_H__
/* Includes: */
#include "../../../Common/Common.h"
#include "USBMode.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
/* Architecture Includes: */
#if (ARCH == ARCH_AVR8)
#include "AVR8/OTG_AVR8.h"
#endif
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,144 @@
/*
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 Common USB Pipe definitions for all architectures.
* \copydetails Group_PipeManagement
*
* \note This file should not be included directly. It is automatically included as needed by the USB driver
* dispatch header located in LUFA/Drivers/USB/USB.h.
*/
/** \ingroup Group_PipeManagement
* \defgroup Group_PipeRW Pipe Data Reading and Writing
* \brief Pipe data read/write definitions.
*
* Functions, macros, variables, enums and types related to data reading and writing from and to pipes.
*/
/** \ingroup Group_PipeRW
* \defgroup Group_PipePrimitiveRW Read/Write of Primitive Data Types
* \brief Pipe data primitive read/write definitions.
*
* Functions, macros, variables, enums and types related to data reading and writing of primitive data types
* from and to pipes.
*/
/** \ingroup Group_PipeManagement
* \defgroup Group_PipePacketManagement Pipe Packet Management
* \brief Pipe packet management definitions.
*
* Functions, macros, variables, enums and types related to packet management of pipes.
*/
/** \ingroup Group_PipeManagement
* \defgroup Group_PipeControlReq Pipe Control Request Management
* \brief Pipe control request definitions.
*
* Module for host mode request processing. This module allows for the transmission of standard, class and
* vendor control requests to the default control endpoint of an attached device while in host mode.
*
* \see Chapter 9 of the USB 2.0 specification.
*/
/** \ingroup Group_USB
* \defgroup Group_PipeManagement Pipe Management
* \brief Pipe management definitions.
*
* This module contains functions, macros and enums related to pipe management when in USB Host mode. This
* module contains the pipe management macros, as well as pipe interrupt and data send/receive functions
* for various data types.
*
* @{
*/
#ifndef __PIPE_H__
#define __PIPE_H__
/* Includes: */
#include "../../../Common/Common.h"
#include "USBMode.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: */
/* Type Defines: */
/** Type define for a pipe table entry, used to configure pipes in groups via
* \ref Pipe_ConfigurePipeTable().
*/
typedef struct
{
uint8_t Address; /**< Address of the pipe to configure, or zero if the table entry is to be unused. */
uint16_t Size; /**< Size of the pipe bank, in bytes. */
uint8_t EndpointAddress; /**< Address of the endpoint in the connected device. */
uint8_t Type; /**< Type of the endpoint, a \c EP_TYPE_* mask. */
uint8_t Banks; /**< Number of hardware banks to use for the pipe. */
} USB_Pipe_Table_t;
/* Macros: */
/** Pipe address for the default control pipe, which always resides in address 0. This is
* defined for convenience to give more readable code when used with the pipe macros.
*/
#define PIPE_CONTROLPIPE 0
/** Pipe number mask, for masking against pipe addresses to retrieve the pipe's numerical address
* in the device.
*/
#define PIPE_PIPENUM_MASK 0x0F
/** Endpoint number mask, for masking against endpoint addresses to retrieve the endpoint's
* numerical address in the attached device.
*/
#define PIPE_EPNUM_MASK 0x0F
/* Architecture Includes: */
#if (ARCH == ARCH_AVR8)
#include "AVR8/Pipe_AVR8.h"
#elif (ARCH == ARCH_UC3)
#include "UC3/Pipe_UC3.h"
#endif
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,100 @@
/*
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.
* \copydetails Group_PipeStreamRW
*
* \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_PipeStreamRW Read/Write of Multi-Byte Streams
* \brief Pipe data stream transmission and reception management.
*
* Functions, macros, variables, enums and types related to data reading and writing of data streams from
* and to pipes.
*
* @{
*/
#ifndef __PIPE_STREAM_H__
#define __PIPE_STREAM_H__
/* Includes: */
#include "../../../Common/Common.h"
#include "USBMode.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: */
/* Enums: */
/** Enum for the possible error return codes of the Pipe_*_Stream_* functions. */
enum Pipe_Stream_RW_ErrorCodes_t
{
PIPE_RWSTREAM_NoError = 0, /**< Command completed successfully, no error. */
PIPE_RWSTREAM_PipeStalled = 1, /**< The device stalled the pipe during the transfer. */
PIPE_RWSTREAM_DeviceDisconnected = 2, /**< Device was disconnected from the host during
* the transfer.
*/
PIPE_RWSTREAM_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.
*/
PIPE_RWSTREAM_IncompleteTransfer = 4, /**< Indicates that the pipe bank became full/empty before the
* complete contents of the stream could be transferred.
*/
};
/* Architecture Includes: */
#if (ARCH == ARCH_AVR8)
#include "AVR8/PipeStream_AVR8.h"
#elif (ARCH == ARCH_UC3)
#include "UC3/PipeStream_UC3.h"
#endif
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,765 @@
/*
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 Common standard USB Descriptor definitions for all architectures.
* \copydetails Group_StdDescriptors
*
* \note This file should not be included directly. It is automatically included as needed by the USB driver
* dispatch header located in LUFA/Drivers/USB/USB.h.
*/
/** \ingroup Group_USB
* \defgroup Group_StdDescriptors USB Descriptors
* \brief Standard USB Descriptor definitions.
*
* Standard USB device descriptor defines and retrieval routines, for USB devices. This module contains
* structures and macros for the easy creation of standard USB descriptors in USB device projects.
*
* @{
*/
#ifndef __USBDESCRIPTORS_H__
#define __USBDESCRIPTORS_H__
/* Includes: */
#include "../../../Common/Common.h"
#include "USBMode.h"
#include "Events.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 that a given descriptor does not exist in the device. This can be used inside descriptors
* for string descriptor indexes, or may be use as a return value for GetDescriptor when the specified
* descriptor does not exist.
*/
#define NO_DESCRIPTOR 0
/** Macro to calculate the power value for the configuration descriptor, from a given number of milliamperes.
*
* \param[in] mA Maximum number of milliamps the device consumes when the given configuration is selected.
*/
#define USB_CONFIG_POWER_MA(mA) ((mA) >> 1)
/** Macro to calculate the Unicode length of a string with a given number of Unicode characters.
* Should be used in string descriptor's headers for giving the string descriptor's byte length.
*
* \param[in] UnicodeChars Number of Unicode characters in the string text.
*/
#define USB_STRING_LEN(UnicodeChars) (sizeof(USB_Descriptor_Header_t) + ((UnicodeChars) << 1))
/** Convenience macro to easily create \ref USB_Descriptor_String_t instances from a wide character string.
*
* \note This macro is for little-endian systems only.
*
* \param[in] String String to initialize a USB String Descriptor structure with.
*/
#define USB_STRING_DESCRIPTOR(String) { .Header = {.Size = sizeof(USB_Descriptor_Header_t) + (sizeof(String) - 2), .Type = DTYPE_String}, .UnicodeString = String }
/** Convenience macro to easily create \ref USB_Descriptor_String_t instances from an array of characters.
*
* \param[in] ... Characters to initialize a USB String Descriptor structure with.
*/
#define USB_STRING_DESCRIPTOR_ARRAY(...) { .Header = {.Size = sizeof(USB_Descriptor_Header_t) + sizeof((uint16_t){__VA_ARGS__}), .Type = DTYPE_String}, .UnicodeString = {__VA_ARGS__} }
/** Macro to encode a given major/minor/revision version number into Binary Coded Decimal format for descriptor
* fields requiring BCD encoding, such as the USB version number in the standard device descriptor.
*
* \note This value is automatically converted into Little Endian, suitable for direct use inside device
* descriptors on all architectures without endianness conversion macros.
*
* \param[in] Major Major version number to encode.
* \param[in] Minor Minor version number to encode.
* \param[in] Revision Revision version number to encode.
*/
#define VERSION_BCD(Major, Minor, Revision) \
CPU_TO_LE16( ((Major & 0xFF) << 8) | \
((Minor & 0x0F) << 4) | \
(Revision & 0x0F) )
/** String language ID for the English language. Should be used in \ref USB_Descriptor_String_t descriptors
* to indicate that the English language is supported by the device in its string descriptors.
*/
#define LANGUAGE_ID_ENG 0x0409
/** \name USB Configuration Descriptor Attribute Masks */
//@{
/** Mask for the reserved bit in the Configuration Descriptor's \c ConfigAttributes field, which must be set on all
* devices for historical purposes.
*/
#define USB_CONFIG_ATTR_RESERVED 0x80
/** Can be masked with other configuration descriptor attributes for a \ref USB_Descriptor_Configuration_Header_t
* descriptor's \c ConfigAttributes value to indicate that the specified configuration can draw its power
* from the device's own power source.
*/
#define USB_CONFIG_ATTR_SELFPOWERED 0x40
/** Can be masked with other configuration descriptor attributes for a \ref USB_Descriptor_Configuration_Header_t
* descriptor's \c ConfigAttributes value to indicate that the specified configuration supports the
* remote wakeup feature of the USB standard, allowing a suspended USB device to wake up the host upon
* request.
*/
#define USB_CONFIG_ATTR_REMOTEWAKEUP 0x20
//@}
/** \name Endpoint Descriptor Attribute Masks */
//@{
/** Can be masked with other endpoint descriptor attributes for a \ref USB_Descriptor_Endpoint_t descriptor's
* \c Attributes value to indicate that the specified endpoint is not synchronized.
*
* \see The USB specification for more details on the possible Endpoint attributes.
*/
#define ENDPOINT_ATTR_NO_SYNC (0 << 2)
/** Can be masked with other endpoint descriptor attributes for a \ref USB_Descriptor_Endpoint_t descriptor's
* \c Attributes value to indicate that the specified endpoint is asynchronous.
*
* \see The USB specification for more details on the possible Endpoint attributes.
*/
#define ENDPOINT_ATTR_ASYNC (1 << 2)
/** Can be masked with other endpoint descriptor attributes for a \ref USB_Descriptor_Endpoint_t descriptor's
* \c Attributes value to indicate that the specified endpoint is adaptive.
*
* \see The USB specification for more details on the possible Endpoint attributes.
*/
#define ENDPOINT_ATTR_ADAPTIVE (2 << 2)
/** Can be masked with other endpoint descriptor attributes for a \ref USB_Descriptor_Endpoint_t descriptor's
* \c Attributes value to indicate that the specified endpoint is synchronized.
*
* \see The USB specification for more details on the possible Endpoint attributes.
*/
#define ENDPOINT_ATTR_SYNC (3 << 2)
//@}
/** \name Endpoint Descriptor Usage Masks */
//@{
/** Can be masked with other endpoint descriptor attributes for a \ref USB_Descriptor_Endpoint_t descriptor's
* \c Attributes value to indicate that the specified endpoint is used for data transfers.
*
* \see The USB specification for more details on the possible Endpoint usage attributes.
*/
#define ENDPOINT_USAGE_DATA (0 << 4)
/** Can be masked with other endpoint descriptor attributes for a \ref USB_Descriptor_Endpoint_t descriptor's
* \c Attributes value to indicate that the specified endpoint is used for feedback.
*
* \see The USB specification for more details on the possible Endpoint usage attributes.
*/
#define ENDPOINT_USAGE_FEEDBACK (1 << 4)
/** Can be masked with other endpoint descriptor attributes for a \ref USB_Descriptor_Endpoint_t descriptor's
* \c Attributes value to indicate that the specified endpoint is used for implicit feedback.
*
* \see The USB specification for more details on the possible Endpoint usage attributes.
*/
#define ENDPOINT_USAGE_IMPLICIT_FEEDBACK (2 << 4)
//@}
/* Enums: */
/** Enum for the possible standard descriptor types, as given in each descriptor's header. */
enum USB_DescriptorTypes_t
{
DTYPE_Device = 0x01, /**< Indicates that the descriptor is a device descriptor. */
DTYPE_Configuration = 0x02, /**< Indicates that the descriptor is a configuration descriptor. */
DTYPE_String = 0x03, /**< Indicates that the descriptor is a string descriptor. */
DTYPE_Interface = 0x04, /**< Indicates that the descriptor is an interface descriptor. */
DTYPE_Endpoint = 0x05, /**< Indicates that the descriptor is an endpoint descriptor. */
DTYPE_DeviceQualifier = 0x06, /**< Indicates that the descriptor is a device qualifier descriptor. */
DTYPE_Other = 0x07, /**< Indicates that the descriptor is of other type. */
DTYPE_InterfacePower = 0x08, /**< Indicates that the descriptor is an interface power descriptor. */
DTYPE_InterfaceAssociation = 0x0B, /**< Indicates that the descriptor is an interface association descriptor. */
DTYPE_CSInterface = 0x24, /**< Indicates that the descriptor is a class specific interface descriptor. */
DTYPE_CSEndpoint = 0x25, /**< Indicates that the descriptor is a class specific endpoint descriptor. */
};
/** Enum for possible Class, Subclass and Protocol values of device and interface descriptors. */
enum USB_Descriptor_ClassSubclassProtocol_t
{
USB_CSCP_NoDeviceClass = 0x00, /**< Descriptor Class value indicating that the device does not belong
* to a particular class at the device level.
*/
USB_CSCP_NoDeviceSubclass = 0x00, /**< Descriptor Subclass value indicating that the device does not belong
* to a particular subclass at the device level.
*/
USB_CSCP_NoDeviceProtocol = 0x00, /**< Descriptor Protocol value indicating that the device does not belong
* to a particular protocol at the device level.
*/
USB_CSCP_VendorSpecificClass = 0xFF, /**< Descriptor Class value indicating that the device/interface belongs
* to a vendor specific class.
*/
USB_CSCP_VendorSpecificSubclass = 0xFF, /**< Descriptor Subclass value indicating that the device/interface belongs
* to a vendor specific subclass.
*/
USB_CSCP_VendorSpecificProtocol = 0xFF, /**< Descriptor Protocol value indicating that the device/interface belongs
* to a vendor specific protocol.
*/
USB_CSCP_IADDeviceClass = 0xEF, /**< Descriptor Class value indicating that the device belongs to the
* Interface Association Descriptor class.
*/
USB_CSCP_IADDeviceSubclass = 0x02, /**< Descriptor Subclass value indicating that the device belongs to the
* Interface Association Descriptor subclass.
*/
USB_CSCP_IADDeviceProtocol = 0x01, /**< Descriptor Protocol value indicating that the device belongs to the
* Interface Association Descriptor protocol.
*/
};
/* Type Defines: */
/** \brief Standard USB Descriptor Header (LUFA naming conventions).
*
* Type define for all descriptors' standard header, indicating the descriptor's length and type. This structure
* uses LUFA-specific element names to make each element's purpose clearer.
*
* \see \ref USB_StdDescriptor_Header_t for the version of this type with standard element names.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
uint8_t Size; /**< Size of the descriptor, in bytes. */
uint8_t Type; /**< Type of the descriptor, either a value in \ref USB_DescriptorTypes_t or a value
* given by the specific class.
*/
} ATTR_PACKED USB_Descriptor_Header_t;
/** \brief Standard USB Descriptor Header (USB-IF naming conventions).
*
* Type define for all descriptors' standard header, indicating the descriptor's length and type. This structure
* uses the relevant standard's given element names to ensure compatibility with the standard.
*
* \see \ref USB_Descriptor_Header_t for the version of this type with non-standard LUFA specific element names.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
uint8_t bLength; /**< Size of the descriptor, in bytes. */
uint8_t bDescriptorType; /**< Type of the descriptor, either a value in \ref USB_DescriptorTypes_t or a value
* given by the specific class.
*/
} ATTR_PACKED USB_StdDescriptor_Header_t;
/** \brief Standard USB Device Descriptor (LUFA naming conventions).
*
* Type define for a standard Device Descriptor. This structure uses LUFA-specific element names to make each
* element's purpose clearer.
*
* \see \ref USB_StdDescriptor_Device_t for the version of this type with standard element names.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
USB_Descriptor_Header_t Header; /**< Descriptor header, including type and size. */
uint16_t USBSpecification; /**< BCD of the supported USB specification.
*
* \see \ref VERSION_BCD() utility macro.
*/
uint8_t Class; /**< USB device class. */
uint8_t SubClass; /**< USB device subclass. */
uint8_t Protocol; /**< USB device protocol. */
uint8_t Endpoint0Size; /**< Size of the control (address 0) endpoint's bank in bytes. */
uint16_t VendorID; /**< Vendor ID for the USB product. */
uint16_t ProductID; /**< Unique product ID for the USB product. */
uint16_t ReleaseNumber; /**< Product release (version) number.
*
* \see \ref VERSION_BCD() utility macro.
*/
uint8_t ManufacturerStrIndex; /**< String index for the manufacturer's name. The
* host will request this string via a separate
* control request for the string descriptor.
*
* \note If no string supplied, use \ref NO_DESCRIPTOR.
*/
uint8_t ProductStrIndex; /**< String index for the product name/details.
*
* \see ManufacturerStrIndex structure entry.
*/
uint8_t SerialNumStrIndex; /**< String index for the product's globally unique hexadecimal
* serial number, in uppercase Unicode ASCII.
*
* \note On some microcontroller models, there is an embedded serial number
* in the chip which can be used for the device serial number.
* To use this serial number, set this to \c USE_INTERNAL_SERIAL.
* On unsupported devices, this will evaluate to \ref NO_DESCRIPTOR
* and will cause the host to generate a pseudo-unique value for the
* device upon insertion.
*
* \see \c ManufacturerStrIndex structure entry.
*/
uint8_t NumberOfConfigurations; /**< Total number of configurations supported by
* the device.
*/
} ATTR_PACKED USB_Descriptor_Device_t;
/** \brief Standard USB Device Descriptor (USB-IF naming conventions).
*
* Type define for a standard Device Descriptor. This structure uses the relevant standard's given element names
* to ensure compatibility with the standard.
*
* \see \ref USB_Descriptor_Device_t for the version of this type with non-standard LUFA specific element names.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
uint8_t bLength; /**< Size of the descriptor, in bytes. */
uint8_t bDescriptorType; /**< Type of the descriptor, either a value in \ref USB_DescriptorTypes_t or a value
* given by the specific class.
*/
uint16_t bcdUSB; /**< BCD of the supported USB specification.
*
* \see \ref VERSION_BCD() utility macro.
*/
uint8_t bDeviceClass; /**< USB device class. */
uint8_t bDeviceSubClass; /**< USB device subclass. */
uint8_t bDeviceProtocol; /**< USB device protocol. */
uint8_t bMaxPacketSize0; /**< Size of the control (address 0) endpoint's bank in bytes. */
uint16_t idVendor; /**< Vendor ID for the USB product. */
uint16_t idProduct; /**< Unique product ID for the USB product. */
uint16_t bcdDevice; /**< Product release (version) number.
*
* \see \ref VERSION_BCD() utility macro.
*/
uint8_t iManufacturer; /**< String index for the manufacturer's name. The
* host will request this string via a separate
* control request for the string descriptor.
*
* \note If no string supplied, use \ref NO_DESCRIPTOR.
*/
uint8_t iProduct; /**< String index for the product name/details.
*
* \see ManufacturerStrIndex structure entry.
*/
uint8_t iSerialNumber; /**< String index for the product's globally unique hexadecimal
* serial number, in uppercase Unicode ASCII.
*
* \note On some microcontroller models, there is an embedded serial number
* in the chip which can be used for the device serial number.
* To use this serial number, set this to \c USE_INTERNAL_SERIAL.
* On unsupported devices, this will evaluate to \ref NO_DESCRIPTOR
* and will cause the host to generate a pseudo-unique value for the
* device upon insertion.
*
* \see \c ManufacturerStrIndex structure entry.
*/
uint8_t bNumConfigurations; /**< Total number of configurations supported by
* the device.
*/
} ATTR_PACKED USB_StdDescriptor_Device_t;
/** \brief Standard USB Device Qualifier Descriptor (LUFA naming conventions).
*
* Type define for a standard Device Qualifier Descriptor. This structure uses LUFA-specific element names
* to make each element's purpose clearer.
*
* \see \ref USB_StdDescriptor_DeviceQualifier_t for the version of this type with standard element names.
*/
typedef struct
{
USB_Descriptor_Header_t Header; /**< Descriptor header, including type and size. */
uint16_t USBSpecification; /**< BCD of the supported USB specification.
*
* \see \ref VERSION_BCD() utility macro.
*/
uint8_t Class; /**< USB device class. */
uint8_t SubClass; /**< USB device subclass. */
uint8_t Protocol; /**< USB device protocol. */
uint8_t Endpoint0Size; /**< Size of the control (address 0) endpoint's bank in bytes. */
uint8_t NumberOfConfigurations; /**< Total number of configurations supported by
* the device.
*/
uint8_t Reserved; /**< Reserved for future use, must be 0. */
} ATTR_PACKED USB_Descriptor_DeviceQualifier_t;
/** \brief Standard USB Device Qualifier Descriptor (USB-IF naming conventions).
*
* Type define for a standard Device Qualifier Descriptor. This structure uses the relevant standard's given element names
* to ensure compatibility with the standard.
*
* \see \ref USB_Descriptor_DeviceQualifier_t for the version of this type with non-standard LUFA specific element names.
*/
typedef struct
{
uint8_t bLength; /**< Size of the descriptor, in bytes. */
uint8_t bDescriptorType; /**< Type of the descriptor, either a value in \ref USB_DescriptorTypes_t or a value
* given by the specific class.
*/
uint16_t bcdUSB; /**< BCD of the supported USB specification.
*
* \see \ref VERSION_BCD() utility macro.
*/
uint8_t bDeviceClass; /**< USB device class. */
uint8_t bDeviceSubClass; /**< USB device subclass. */
uint8_t bDeviceProtocol; /**< USB device protocol. */
uint8_t bMaxPacketSize0; /**< Size of the control (address 0) endpoint's bank in bytes. */
uint8_t bNumConfigurations; /**< Total number of configurations supported by
* the device.
*/
uint8_t bReserved; /**< Reserved for future use, must be 0. */
} ATTR_PACKED USB_StdDescriptor_DeviceQualifier_t;
/** \brief Standard USB Configuration Descriptor (LUFA naming conventions).
*
* Type define for a standard Configuration Descriptor header. This structure uses LUFA-specific element names
* to make each element's purpose clearer.
*
* \see \ref USB_StdDescriptor_Configuration_Header_t for the version of this type with standard element names.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
USB_Descriptor_Header_t Header; /**< Descriptor header, including type and size. */
uint16_t TotalConfigurationSize; /**< Size of the configuration descriptor header,
* and all sub descriptors inside the configuration.
*/
uint8_t TotalInterfaces; /**< Total number of interfaces in the configuration. */
uint8_t ConfigurationNumber; /**< Configuration index of the current configuration. */
uint8_t ConfigurationStrIndex; /**< Index of a string descriptor describing the configuration. */
uint8_t ConfigAttributes; /**< Configuration attributes, comprised of a mask of \c USB_CONFIG_ATTR_* masks.
* On all devices, this should include USB_CONFIG_ATTR_RESERVED at a minimum.
*/
uint8_t MaxPowerConsumption; /**< Maximum power consumption of the device while in the
* current configuration, calculated by the \ref USB_CONFIG_POWER_MA()
* macro.
*/
} ATTR_PACKED USB_Descriptor_Configuration_Header_t;
/** \brief Standard USB Configuration Descriptor (USB-IF naming conventions).
*
* Type define for a standard Configuration Descriptor header. This structure uses the relevant standard's given element names
* to ensure compatibility with the standard.
*
* \see \ref USB_Descriptor_Device_t for the version of this type with non-standard LUFA specific element names.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
uint8_t bLength; /**< Size of the descriptor, in bytes. */
uint8_t bDescriptorType; /**< Type of the descriptor, either a value in \ref USB_DescriptorTypes_t or a value
* given by the specific class.
*/
uint16_t wTotalLength; /**< Size of the configuration descriptor header,
* and all sub descriptors inside the configuration.
*/
uint8_t bNumInterfaces; /**< Total number of interfaces in the configuration. */
uint8_t bConfigurationValue; /**< Configuration index of the current configuration. */
uint8_t iConfiguration; /**< Index of a string descriptor describing the configuration. */
uint8_t bmAttributes; /**< Configuration attributes, comprised of a mask of \c USB_CONFIG_ATTR_* masks.
* On all devices, this should include USB_CONFIG_ATTR_RESERVED at a minimum.
*/
uint8_t bMaxPower; /**< Maximum power consumption of the device while in the
* current configuration, calculated by the \ref USB_CONFIG_POWER_MA()
* macro.
*/
} ATTR_PACKED USB_StdDescriptor_Configuration_Header_t;
/** \brief Standard USB Interface Descriptor (LUFA naming conventions).
*
* Type define for a standard Interface Descriptor. This structure uses LUFA-specific element names
* to make each element's purpose clearer.
*
* \see \ref USB_StdDescriptor_Interface_t for the version of this type with standard element names.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
USB_Descriptor_Header_t Header; /**< Descriptor header, including type and size. */
uint8_t InterfaceNumber; /**< Index of the interface in the current configuration. */
uint8_t AlternateSetting; /**< Alternate setting for the interface number. The same
* interface number can have multiple alternate settings
* with different endpoint configurations, which can be
* selected by the host.
*/
uint8_t TotalEndpoints; /**< Total number of endpoints in the interface. */
uint8_t Class; /**< Interface class ID. */
uint8_t SubClass; /**< Interface subclass ID. */
uint8_t Protocol; /**< Interface protocol ID. */
uint8_t InterfaceStrIndex; /**< Index of the string descriptor describing the interface. */
} ATTR_PACKED USB_Descriptor_Interface_t;
/** \brief Standard USB Interface Descriptor (USB-IF naming conventions).
*
* Type define for a standard Interface Descriptor. This structure uses the relevant standard's given element names
* to ensure compatibility with the standard.
*
* \see \ref USB_Descriptor_Interface_t for the version of this type with non-standard LUFA specific element names.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
uint8_t bLength; /**< Size of the descriptor, in bytes. */
uint8_t bDescriptorType; /**< Type of the descriptor, either a value in \ref USB_DescriptorTypes_t or a value
* given by the specific class.
*/
uint8_t bInterfaceNumber; /**< Index of the interface in the current configuration. */
uint8_t bAlternateSetting; /**< Alternate setting for the interface number. The same
* interface number can have multiple alternate settings
* with different endpoint configurations, which can be
* selected by the host.
*/
uint8_t bNumEndpoints; /**< Total number of endpoints in the interface. */
uint8_t bInterfaceClass; /**< Interface class ID. */
uint8_t bInterfaceSubClass; /**< Interface subclass ID. */
uint8_t bInterfaceProtocol; /**< Interface protocol ID. */
uint8_t iInterface; /**< Index of the string descriptor describing the
* interface.
*/
} ATTR_PACKED USB_StdDescriptor_Interface_t;
/** \brief Standard USB Interface Association Descriptor (LUFA naming conventions).
*
* Type define for a standard Interface Association Descriptor. This structure uses LUFA-specific element names
* to make each element's purpose clearer.
*
* This descriptor has been added as a supplement to the USB2.0 standard, in the ECN located at
* <a>http://www.usb.org/developers/docs/InterfaceAssociationDescriptor_ecn.pdf</a>. It allows composite
* devices with multiple interfaces related to the same function to have the multiple interfaces bound
* together at the point of enumeration, loading one generic driver for all the interfaces in the single
* function. Read the ECN for more information.
*
* \see \ref USB_StdDescriptor_Interface_Association_t for the version of this type with standard element names.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
USB_Descriptor_Header_t Header; /**< Descriptor header, including type and size. */
uint8_t FirstInterfaceIndex; /**< Index of the first associated interface. */
uint8_t TotalInterfaces; /**< Total number of associated interfaces. */
uint8_t Class; /**< Interface class ID. */
uint8_t SubClass; /**< Interface subclass ID. */
uint8_t Protocol; /**< Interface protocol ID. */
uint8_t IADStrIndex; /**< Index of the string descriptor describing the
* interface association.
*/
} ATTR_PACKED USB_Descriptor_Interface_Association_t;
/** \brief Standard USB Interface Association Descriptor (USB-IF naming conventions).
*
* Type define for a standard Interface Association Descriptor. This structure uses the relevant standard's given
* element names to ensure compatibility with the standard.
*
* This descriptor has been added as a supplement to the USB2.0 standard, in the ECN located at
* <a>http://www.usb.org/developers/docs/InterfaceAssociationDescriptor_ecn.pdf</a>. It allows composite
* devices with multiple interfaces related to the same function to have the multiple interfaces bound
* together at the point of enumeration, loading one generic driver for all the interfaces in the single
* function. Read the ECN for more information.
*
* \see \ref USB_Descriptor_Interface_Association_t for the version of this type with non-standard LUFA specific
* element names.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
uint8_t bLength; /**< Size of the descriptor, in bytes. */
uint8_t bDescriptorType; /**< Type of the descriptor, either a value in \ref USB_DescriptorTypes_t or a value
* given by the specific class.
*/
uint8_t bFirstInterface; /**< Index of the first associated interface. */
uint8_t bInterfaceCount; /**< Total number of associated interfaces. */
uint8_t bFunctionClass; /**< Interface class ID. */
uint8_t bFunctionSubClass; /**< Interface subclass ID. */
uint8_t bFunctionProtocol; /**< Interface protocol ID. */
uint8_t iFunction; /**< Index of the string descriptor describing the
* interface association.
*/
} ATTR_PACKED USB_StdDescriptor_Interface_Association_t;
/** \brief Standard USB Endpoint Descriptor (LUFA naming conventions).
*
* Type define for a standard Endpoint Descriptor. This structure uses LUFA-specific element names
* to make each element's purpose clearer.
*
* \see \ref USB_StdDescriptor_Endpoint_t for the version of this type with standard element names.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
USB_Descriptor_Header_t Header; /**< Descriptor header, including type and size. */
uint8_t EndpointAddress; /**< Logical address of the endpoint within the device for the current
* configuration, including direction mask.
*/
uint8_t Attributes; /**< Endpoint attributes, comprised of a mask of the endpoint type (EP_TYPE_*)
* and attributes (ENDPOINT_ATTR_*) masks.
*/
uint16_t EndpointSize; /**< Size of the endpoint bank, in bytes. This indicates the maximum packet
* size that the endpoint can receive at a time.
*/
uint8_t PollingIntervalMS; /**< Polling interval in milliseconds for the endpoint if it is an INTERRUPT
* or ISOCHRONOUS type.
*/
} ATTR_PACKED USB_Descriptor_Endpoint_t;
/** \brief Standard USB Endpoint Descriptor (USB-IF naming conventions).
*
* Type define for a standard Endpoint Descriptor. This structure uses the relevant standard's given
* element names to ensure compatibility with the standard.
*
* \see \ref USB_Descriptor_Endpoint_t for the version of this type with non-standard LUFA specific
* element names.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
uint8_t bLength; /**< Size of the descriptor, in bytes. */
uint8_t bDescriptorType; /**< Type of the descriptor, either a value in \ref USB_DescriptorTypes_t or a
* value given by the specific class.
*/
uint8_t bEndpointAddress; /**< Logical address of the endpoint within the device for the current
* configuration, including direction mask.
*/
uint8_t bmAttributes; /**< Endpoint attributes, comprised of a mask of the endpoint type (EP_TYPE_*)
* and attributes (ENDPOINT_ATTR_*) masks.
*/
uint16_t wMaxPacketSize; /**< Size of the endpoint bank, in bytes. This indicates the maximum packet size
* that the endpoint can receive at a time.
*/
uint8_t bInterval; /**< Polling interval in milliseconds for the endpoint if it is an INTERRUPT or
* ISOCHRONOUS type.
*/
} ATTR_PACKED USB_StdDescriptor_Endpoint_t;
/** \brief Standard USB String Descriptor (LUFA naming conventions).
*
* Type define for a standard string descriptor. Unlike other standard descriptors, the length
* of the descriptor for placement in the descriptor header must be determined by the \ref USB_STRING_LEN()
* macro rather than by the size of the descriptor structure, as the length is not fixed.
*
* This structure should also be used for string index 0, which contains the supported language IDs for
* the device as an array.
*
* This structure uses LUFA-specific element names to make each element's purpose clearer.
*
* \see \ref USB_StdDescriptor_String_t for the version of this type with standard element names.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
USB_Descriptor_Header_t Header; /**< Descriptor header, including type and size. */
#if (((ARCH == ARCH_AVR8) || (ARCH == ARCH_XMEGA)) && !defined(__DOXYGEN__))
wchar_t UnicodeString[];
#else
uint16_t UnicodeString[]; /**< String data, as unicode characters (alternatively,
* string language IDs). If normal ASCII characters are
* to be used, they must be added as an array of characters
* rather than a normal C string so that they are widened to
* Unicode size.
*
* Under GCC, strings prefixed with the "L" character (before
* the opening string quotation mark) are considered to be
* Unicode strings, and may be used instead of an explicit
* array of ASCII characters on little endian devices with
* UTF-16-LE \c wchar_t encoding.
*/
#endif
} ATTR_PACKED USB_Descriptor_String_t;
/** \brief Standard USB String Descriptor (USB-IF naming conventions).
*
* Type define for a standard string descriptor. Unlike other standard descriptors, the length
* of the descriptor for placement in the descriptor header must be determined by the \ref USB_STRING_LEN()
* macro rather than by the size of the descriptor structure, as the length is not fixed.
*
* This structure should also be used for string index 0, which contains the supported language IDs for
* the device as an array.
*
* This structure uses the relevant standard's given element names to ensure compatibility with the standard.
*
* \see \ref USB_Descriptor_String_t for the version of this type with with non-standard LUFA specific
* element names.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
uint8_t bLength; /**< Size of the descriptor, in bytes. */
uint8_t bDescriptorType; /**< Type of the descriptor, either a value in \ref USB_DescriptorTypes_t
* or a value given by the specific class.
*/
uint16_t bString[]; /**< String data, as unicode characters (alternatively, string language IDs).
* If normal ASCII characters are to be used, they must be added as an array
* of characters rather than a normal C string so that they are widened to
* Unicode size.
*
* Under GCC, strings prefixed with the "L" character (before the opening string
* quotation mark) are considered to be Unicode strings, and may be used instead
* of an explicit array of ASCII characters.
*/
} ATTR_PACKED USB_StdDescriptor_String_t;
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,258 @@
/*
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 control endpoint request definitions.
* \copydetails Group_StdRequest
*
* \note This file should not be included directly. It is automatically included as needed by the USB driver
* dispatch header located in LUFA/Drivers/USB/USB.h.
*/
/** \ingroup Group_USB
* \defgroup Group_StdRequest Standard USB Requests
* \brief USB control endpoint request definitions.
*
* This module contains definitions for the various control request parameters, so that the request
* details (such as data direction, request recipient, etc.) can be extracted via masking.
*
* @{
*/
#ifndef __STDREQTYPE_H__
#define __STDREQTYPE_H__
/* Includes: */
#include "../../../Common/Common.h"
#include "USBMode.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: */
/** Mask for the request type parameter, to indicate the direction of the request data (Host to Device
* or Device to Host). The result of this mask should then be compared to the request direction masks.
*
* \see \c REQDIR_* macros for masks indicating the request data direction.
*/
#define CONTROL_REQTYPE_DIRECTION 0x80
/** Mask for the request type parameter, to indicate the type of request (Device, Class or Vendor
* Specific). The result of this mask should then be compared to the request type masks.
*
* \see \c REQTYPE_* macros for masks indicating the request type.
*/
#define CONTROL_REQTYPE_TYPE 0x60
/** Mask for the request type parameter, to indicate the recipient of the request (Device, Interface
* Endpoint or Other). The result of this mask should then be compared to the request recipient
* masks.
*
* \see \c REQREC_* macros for masks indicating the request recipient.
*/
#define CONTROL_REQTYPE_RECIPIENT 0x1F
/** \name Control Request Data Direction Masks */
//@{
/** Request data direction mask, indicating that the request data will flow from host to device.
*
* \see \ref CONTROL_REQTYPE_DIRECTION macro.
*/
#define REQDIR_HOSTTODEVICE (0 << 7)
/** Request data direction mask, indicating that the request data will flow from device to host.
*
* \see \ref CONTROL_REQTYPE_DIRECTION macro.
*/
#define REQDIR_DEVICETOHOST (1 << 7)
//@}
/** \name Control Request Type Masks */
//@{
/** Request type mask, indicating that the request is a standard request.
*
* \see \ref CONTROL_REQTYPE_TYPE macro.
*/
#define REQTYPE_STANDARD (0 << 5)
/** Request type mask, indicating that the request is a class-specific request.
*
* \see \ref CONTROL_REQTYPE_TYPE macro.
*/
#define REQTYPE_CLASS (1 << 5)
/** Request type mask, indicating that the request is a vendor specific request.
*
* \see \ref CONTROL_REQTYPE_TYPE macro.
*/
#define REQTYPE_VENDOR (2 << 5)
//@}
/** \name Control Request Recipient Masks */
//@{
/** Request recipient mask, indicating that the request is to be issued to the device as a whole.
*
* \see \ref CONTROL_REQTYPE_RECIPIENT macro.
*/
#define REQREC_DEVICE (0 << 0)
/** Request recipient mask, indicating that the request is to be issued to an interface in the
* currently selected configuration.
*
* \see \ref CONTROL_REQTYPE_RECIPIENT macro.
*/
#define REQREC_INTERFACE (1 << 0)
/** Request recipient mask, indicating that the request is to be issued to an endpoint in the
* currently selected configuration.
*
* \see \ref CONTROL_REQTYPE_RECIPIENT macro.
*/
#define REQREC_ENDPOINT (2 << 0)
/** Request recipient mask, indicating that the request is to be issued to an unspecified element
* in the currently selected configuration.
*
* \see \ref CONTROL_REQTYPE_RECIPIENT macro.
*/
#define REQREC_OTHER (3 << 0)
//@}
/* Type Defines: */
/** \brief Standard USB Control Request
*
* Type define for a standard USB control request.
*
* \see The USB 2.0 specification for more information on standard control requests.
*/
typedef struct
{
uint8_t bmRequestType; /**< Type of the request. */
uint8_t bRequest; /**< Request command code. */
uint16_t wValue; /**< wValue parameter of the request. */
uint16_t wIndex; /**< wIndex parameter of the request. */
uint16_t wLength; /**< Length of the data to transfer in bytes. */
} ATTR_PACKED USB_Request_Header_t;
/* Enums: */
/** Enumeration for the various standard request commands. These commands are applicable when the
* request type is \ref REQTYPE_STANDARD (with the exception of \ref REQ_GetDescriptor, which is always
* handled regardless of the request type value).
*
* \see Chapter 9 of the USB 2.0 Specification.
*/
enum USB_Control_Request_t
{
REQ_GetStatus = 0, /**< Implemented in the library for device and endpoint recipients. Passed
* to the user application for other recipients via the
* \ref EVENT_USB_Device_ControlRequest() event when received in
* device mode. */
REQ_ClearFeature = 1, /**< Implemented in the library for device and endpoint recipients. Passed
* to the user application for other recipients via the
* \ref EVENT_USB_Device_ControlRequest() event when received in
* device mode. */
REQ_SetFeature = 3, /**< Implemented in the library for device and endpoint recipients. Passed
* to the user application for other recipients via the
* \ref EVENT_USB_Device_ControlRequest() event when received in
* device mode. */
REQ_SetAddress = 5, /**< Implemented in the library for the device recipient. Passed
* to the user application for other recipients via the
* \ref EVENT_USB_Device_ControlRequest() event when received in
* device mode. */
REQ_GetDescriptor = 6, /**< Implemented in the library for device and interface recipients. Passed to the
* user application for other recipients via the
* \ref EVENT_USB_Device_ControlRequest() event when received in
* device mode. */
REQ_SetDescriptor = 7, /**< Not implemented in the library, passed to the user application
* via the \ref EVENT_USB_Device_ControlRequest() event when received in
* device mode. */
REQ_GetConfiguration = 8, /**< Implemented in the library for the device recipient. Passed
* to the user application for other recipients via the
* \ref EVENT_USB_Device_ControlRequest() event when received in
* device mode. */
REQ_SetConfiguration = 9, /**< Implemented in the library for the device recipient. Passed
* to the user application for other recipients via the
* \ref EVENT_USB_Device_ControlRequest() event when received in
* device mode. */
REQ_GetInterface = 10, /**< Not implemented in the library, passed to the user application
* via the \ref EVENT_USB_Device_ControlRequest() event when received in
* device mode. */
REQ_SetInterface = 11, /**< Not implemented in the library, passed to the user application
* via the \ref EVENT_USB_Device_ControlRequest() event when received in
* device mode. */
REQ_SynchFrame = 12, /**< Not implemented in the library, passed to the user application
* via the \ref EVENT_USB_Device_ControlRequest() event when received in
* device mode. */
};
/** Feature Selector values for Set Feature and Clear Feature standard control requests directed to the device, interface
* and endpoint recipients.
*/
enum USB_Feature_Selectors_t
{
FEATURE_SEL_EndpointHalt = 0x00, /**< Feature selector for Clear Feature or Set Feature commands. When
* used in a Set Feature or Clear Feature request this indicates that an
* endpoint (whose address is given elsewhere in the request) should have
* its stall condition changed.
*/
FEATURE_SEL_DeviceRemoteWakeup = 0x01, /**< Feature selector for Device level Remote Wakeup enable set or clear.
* This feature can be controlled by the host on devices which indicate
* remote wakeup support in their descriptors to selectively disable or
* enable remote wakeup.
*/
FEATURE_SEL_TestMode = 0x02, /**< Feature selector for Test Mode features, used to test the USB controller
* to check for incorrect operation.
*/
};
/* Private Interface - For use in library only: */
#if !defined(__DOXYGEN__)
/* Macros: */
#define FEATURE_SELFPOWERED_ENABLED (1 << 0)
#define FEATURE_REMOTE_WAKEUP_ENABLED (1 << 1)
#endif
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

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

View file

@ -0,0 +1,165 @@
/*
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 Common USB Controller definitions for all architectures.
* \copydetails Group_USBManagement
*
* \note This file should not be included directly. It is automatically included as needed by the USB driver
* dispatch header located in LUFA/Drivers/USB/USB.h.
*/
/** \ingroup Group_USB
* \defgroup Group_USBManagement USB Interface Management
* \brief USB Controller definitions for general USB controller management.
*
* Functions, macros, variables, enums and types related to the setup and management of the USB interface.
*
* @{
*/
#ifndef __USBCONTROLLER_H__
#define __USBCONTROLLER_H__
/* Includes: */
#include "../../../Common/Common.h"
#include "USBMode.h"
/* 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
/* Defines: */
/** \name Endpoint Direction Masks */
//@{
/** Endpoint direction mask, for masking against endpoint addresses to retrieve the endpoint's
* direction for comparing with the \c ENDPOINT_DIR_* masks.
*/
#define ENDPOINT_DIR_MASK 0x80
/** Endpoint address direction mask for an OUT direction (Host to Device) endpoint. This may be ORed with
* the index of the address within a device to obtain the full endpoint address.
*/
#define ENDPOINT_DIR_OUT 0x00
/** Endpoint address direction mask for an IN direction (Device to Host) endpoint. This may be ORed with
* the index of the address within a device to obtain the full endpoint address.
*/
#define ENDPOINT_DIR_IN 0x80
//@}
/** \name Pipe Direction Masks */
//@{
/** Pipe direction mask, for masking against pipe addresses to retrieve the pipe's
* direction for comparing with the \c PIPE_DIR_* masks.
*/
#define PIPE_DIR_MASK 0x80
/** Endpoint address direction mask for an OUT direction (Host to Device) endpoint. This may be ORed with
* the index of the address within a device to obtain the full endpoint address.
*/
#define PIPE_DIR_OUT 0x00
/** Endpoint address direction mask for an IN direction (Device to Host) endpoint. This may be ORed with
* the index of the address within a device to obtain the full endpoint address.
*/
#define PIPE_DIR_IN 0x80
//@}
/** \name Endpoint/Pipe Type Masks */
//@{
/** Mask for determining the type of an endpoint from an endpoint descriptor. This should then be compared
* with the \c EP_TYPE_* masks to determine the exact type of the endpoint.
*/
#define EP_TYPE_MASK 0x03
/** Mask for a CONTROL type endpoint or pipe.
*
* \note See \ref Group_EndpointManagement and \ref Group_PipeManagement for endpoint/pipe functions.
*/
#define EP_TYPE_CONTROL 0x00
/** Mask for an ISOCHRONOUS type endpoint or pipe.
*
* \note See \ref Group_EndpointManagement and \ref Group_PipeManagement for endpoint/pipe functions.
*/
#define EP_TYPE_ISOCHRONOUS 0x01
/** Mask for a BULK type endpoint or pipe.
*
* \note See \ref Group_EndpointManagement and \ref Group_PipeManagement for endpoint/pipe functions.
*/
#define EP_TYPE_BULK 0x02
/** Mask for an INTERRUPT type endpoint or pipe.
*
* \note See \ref Group_EndpointManagement and \ref Group_PipeManagement for endpoint/pipe functions.
*/
#define EP_TYPE_INTERRUPT 0x03
//@}
/* Enums: */
/** Enum for the possible USB controller modes, for initialization via \ref USB_Init() and indication back to the
* user application via \ref USB_CurrentMode.
*/
enum USB_Modes_t
{
USB_MODE_None = 0, /**< Indicates that the controller is currently not initialized in any specific USB mode. */
USB_MODE_Device = 1, /**< Indicates that the controller is currently initialized in USB Device mode. */
USB_MODE_Host = 2, /**< Indicates that the controller is currently initialized in USB Host mode. */
USB_MODE_UID = 3, /**< Indicates that the controller should determine the USB mode from the UID pin of the
* USB connector.
*/
};
/* Architecture Includes: */
#if (ARCH == ARCH_AVR8)
#include "AVR8/USBController_AVR8.h"
#elif (ARCH == ARCH_UC3)
#include "UC3/USBController_UC3.h"
#elif (ARCH == ARCH_XMEGA)
#include "XMEGA/USBController_XMEGA.h"
#endif
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,73 @@
/*
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 service routine management.
*
* This file contains definitions required for the correct handling of low level USB service routine interrupts
* from the USB controller.
*
* \note This file should not be included directly. It is automatically included as needed by the USB driver
* dispatch header located in LUFA/Drivers/USB/USB.h.
*/
#ifndef __USBINTERRUPT_H__
#define __USBINTERRUPT_H__
/* Includes: */
#include "../../../Common/Common.h"
#include "USBMode.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
/* Architecture Includes: */
#if (ARCH == ARCH_AVR8)
#include "AVR8/USBInterrupt_AVR8.h"
#elif (ARCH == ARCH_UC3)
#include "UC3/USBInterrupt_UC3.h"
#elif (ARCH == ARCH_XMEGA)
#include "XMEGA/USBInterrupt_XMEGA.h"
#endif
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif

View file

@ -0,0 +1,283 @@
/*
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 mode and feature support definitions.
* \copydetails Group_USBMode
*
* \note This file should not be included directly. It is automatically included as needed by the USB driver
* dispatch header located in LUFA/Drivers/USB/USB.h.
*/
/** \ingroup Group_USB
* \defgroup Group_USBMode USB Mode Tokens
* \brief USB mode and feature support definitions.
*
* This file defines macros indicating the type of USB controller the library is being compiled for, and its
* capabilities. These macros may then be referenced in the user application to selectively enable or disable
* code sections depending on if they are defined or not.
*
* After the inclusion of the master USB driver header, one or more of the following tokens may be defined, to
* allow the user code to conditionally enable or disable code based on the USB controller family and allowable
* USB modes. These tokens may be tested against to eliminate code relating to a USB mode which is not enabled for
* the given compilation.
*
* @{
*/
#ifndef __USBMODE_H__
#define __USBMODE_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
/* Includes: */
#include "../../../Common/Common.h"
/* Public Interface - May be used in end-application: */
#if defined(__DOXYGEN__)
/** Indicates that the target AVR microcontroller belongs to the Series 2 AVR8 USB controller
* (i.e. AT90USBxxx2 or ATMEGAxxU2) when defined.
*/
#define USB_SERIES_2_AVR
/** Indicates that the target AVR microcontroller belongs to the Series 4 AVR8 USB controller
* (i.e. ATMEGAxxU4) when defined.
*/
#define USB_SERIES_4_AVR
/** Indicates that the target AVR microcontroller belongs to the Series 6 AVR8 USB controller
* (i.e. AT90USBxxx6) when defined.
*/
#define USB_SERIES_6_AVR
/** Indicates that the target AVR microcontroller belongs to the Series 7 AVR8 USB controller
* (i.e. AT90USBxxx7) when defined.
*/
#define USB_SERIES_7_AVR
/** Indicates that the target AVR microcontroller belongs to the AVR32 UC3A0 Series USB controller
* (i.e. AT32UC3A0*) when defined.
*/
#define USB_SERIES_UC3A0_AVR
/** Indicates that the target AVR microcontroller belongs to the AVR32 UC3A1 Series USB controller
* (i.e. AT32UC3A1*) when defined.
*/
#define USB_SERIES_UC3A1_AVR
/** Indicates that the target AVR microcontroller belongs to the AVR32 UC3A3 Series USB controller
* (i.e. AT32UC3A3*) when defined.
*/
#define USB_SERIES_UC3A3_AVR
/** Indicates that the target AVR microcontroller belongs to the AVR32 UC3A4 Series USB controller
* (i.e. AT32UC3A4*) when defined.
*/
#define USB_SERIES_UC3A4_AVR
/** Indicates that the target AVR microcontroller belongs to the AVR32 UC3B0 Series USB controller
* (i.e. AT32UC3B0*) when defined.
*/
#define USB_SERIES_UC3B0_AVR
/** Indicates that the target AVR microcontroller belongs to the AVR32 UC3B1 Series USB controller
* (i.e. AT32UC3B1*) when defined.
*/
#define USB_SERIES_UC3B1_AVR
/** Indicates that the target AVR microcontroller belongs to the XMEGA A1U Series USB controller
* (i.e. ATXMEGA*A1U) when defined.
*/
#define USB_SERIES_A1U_XMEGA
/** Indicates that the target AVR microcontroller belongs to the XMEGA A3U Series USB controller
* (i.e. ATXMEGA*A3U) when defined.
*/
#define USB_SERIES_A3U_XMEGA
/** Indicates that the target AVR microcontroller belongs to the XMEGA A4U Series USB controller
* (i.e. ATXMEGA*A4U) when defined.
*/
#define USB_SERIES_A4U_XMEGA
/** Indicates that the target AVR microcontroller belongs to the XMEGA B1 Series USB controller
* (i.e. ATXMEGA*B1) when defined.
*/
#define USB_SERIES_B1_XMEGA
/** Indicates that the target AVR microcontroller belongs to the XMEGA B3 Series USB controller
* (i.e. ATXMEGA*B3) when defined.
*/
#define USB_SERIES_B3_XMEGA
/** Indicates that the target AVR microcontroller belongs to the XMEGA C3 Series USB controller
* (i.e. ATXMEGA*C3) when defined.
*/
#define USB_SERIES_C3_XMEGA
/** Indicates that the target AVR microcontroller belongs to the XMEGA C4 Series USB controller
* (i.e. ATXMEGA*C4) when defined.
*/
#define USB_SERIES_C4_XMEGA
/** Indicates that the target microcontroller and compilation settings allow for the
* target to be configured in USB Device mode when defined.
*/
#define USB_CAN_BE_DEVICE
/** Indicates that the target microcontroller and compilation settings allow for the
* target to be configured in USB Host mode when defined.
*/
#define USB_CAN_BE_HOST
/** Indicates that the target microcontroller and compilation settings allow for the
* target to be configured in either USB Device or Host mode when defined.
*/
#define USB_CAN_BE_BOTH
#else
/* Macros: */
#if (defined(__AVR_AT90USB162__) || defined(__AVR_AT90USB82__) || \
defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega8U2__))
#define USB_SERIES_2_AVR
#define USB_CAN_BE_DEVICE
#elif (defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega16U4__))
#define USB_SERIES_4_AVR
#define USB_CAN_BE_DEVICE
#elif (defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__))
#define USB_SERIES_6_AVR
#define USB_CAN_BE_DEVICE
#elif (defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1287__))
#define USB_SERIES_7_AVR
#define USB_CAN_BE_DEVICE
#define USB_CAN_BE_HOST
#elif (defined(__AVR32_UC3A0512__) || defined(__AVR32_UC3A0256__) || \
defined(__AVR32_UC3A0128__) || defined(__AVR32_UC3A064__))
#define USB_SERIES_UC3A0_AVR32
#define USB_CAN_BE_DEVICE
#define USB_CAN_BE_HOST
#elif (defined(__AVR32_UC3A1512__) || defined(__AVR32_UC3A1256__) || \
defined(__AVR32_UC3A1128__) || defined(__AVR32_UC3A164__))
#define USB_SERIES_UC3A1_AVR32
#define USB_CAN_BE_DEVICE
#define USB_CAN_BE_HOST
#elif (defined(__AVR32_UC3A3256__) || defined(__AVR32_UC3A3256S__) || \
defined(__AVR32_UC3A3128__) || defined(__AVR32_UC3A3128S__) || \
defined(__AVR32_UC3A364__) || defined(__AVR32_UC3A364S__))
#define USB_SERIES_UC3A3_AVR32
#define USB_CAN_BE_DEVICE
#define USB_CAN_BE_HOST
#elif (defined(__AVR32_UC3A4256__) || defined(__AVR32_UC3A4256S__) || \
defined(__AVR32_UC3A4128__) || defined(__AVR32_UC3A4128S__) || \
defined(__AVR32_UC3A464__) || defined(__AVR32_UC3A464S__))
#define USB_SERIES_UC3A4_AVR32
#define USB_CAN_BE_DEVICE
#define USB_CAN_BE_HOST
#elif (defined(__AVR32_UC3B0512__) || defined(__AVR32_UC3B0256__) || \
defined(__AVR32_UC3B0128__) || defined(__AVR32_UC3B064__))
#define USB_SERIES_UC3B0_AVR32
#define USB_CAN_BE_DEVICE
#define USB_CAN_BE_HOST
#elif (defined(__AVR32_UC3B1512__) || defined(__AVR32_UC3B1256__) || \
defined(__AVR32_UC3B1128__) || defined(__AVR32_UC3B164__))
#define USB_SERIES_UC3B1_AVR32
#define USB_CAN_BE_DEVICE
#define USB_CAN_BE_HOST
#elif (defined(__AVR_ATxmega128A1U__) || defined(__AVR_ATxmega64A1U__))
#define USB_SERIES_A1U_XMEGA
#define USB_CAN_BE_DEVICE
#elif (defined(__AVR_ATxmega64A3U__) || defined(__AVR_ATxmega128A3U__) || \
defined(__AVR_ATxmega192A3U__) || defined(__AVR_ATxmega256A3U__))
#define USB_SERIES_A3U_XMEGA
#define USB_CAN_BE_DEVICE
#elif (defined(__AVR_ATxmega256A3BU__))
#define USB_SERIES_A3BU_XMEGA
#define USB_CAN_BE_DEVICE
#elif (defined(__AVR_ATxmega16A4U__) || defined(__AVR_ATxmega32A4U__) || \
defined(__AVR_ATxmega64A4U__) || defined(__AVR_ATxmega128A4U__))
#define USB_SERIES_A4U_XMEGA
#define USB_CAN_BE_DEVICE
#elif (defined(__AVR_ATxmega128B1__) || defined(__AVR_ATxmega64B1__))
#define USB_SERIES_B1_XMEGA
#define USB_CAN_BE_DEVICE
#elif (defined(__AVR_ATxmega128B3__) || defined(__AVR_ATxmega64B3__))
#define USB_SERIES_B3_XMEGA
#define USB_CAN_BE_DEVICE
#elif (defined(__AVR_ATxmega128C3__) || defined(__AVR_ATxmega64C3__) || \
defined(__AVR_ATxmega192C3__) || defined(__AVR_ATxmega256C3__) || \
defined(__AVR_ATxmega384C3__))
#define USB_SERIES_C3_XMEGA
#define USB_CAN_BE_DEVICE
#elif (defined(__AVR_ATxmega16C4__) || defined(__AVR_ATxmega32C4__))
#define USB_SERIES_C4_XMEGA
#define USB_CAN_BE_DEVICE
#endif
#if (defined(USB_HOST_ONLY) && defined(USB_DEVICE_ONLY))
#error USB_HOST_ONLY and USB_DEVICE_ONLY are mutually exclusive.
#elif defined(USB_HOST_ONLY)
#if !defined(USB_CAN_BE_HOST)
#error USB_HOST_ONLY is not available for the currently selected microcontroller model.
#else
#undef USB_CAN_BE_DEVICE
#endif
#elif defined(USB_DEVICE_ONLY)
#if !defined(USB_CAN_BE_DEVICE)
#error USB_DEVICE_ONLY is not available for the currently selected microcontroller model.
#else
#undef USB_CAN_BE_HOST
#endif
#endif
#if (defined(USB_CAN_BE_DEVICE) && defined(USB_CAN_BE_HOST))
#define USB_CAN_BE_BOTH
#endif
#if (!defined(USB_CAN_BE_DEVICE) && !defined(USB_CAN_BE_HOST))
#error The currently selected device, USB mode or architecture is not supported.
#endif
#endif
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#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.
*/
#define __INCLUDE_FROM_USBTASK_C
#define __INCLUDE_FROM_USB_DRIVER
#include "USBTask.h"
volatile bool USB_IsInitialized;
USB_Request_Header_t USB_ControlRequest;
#if defined(USB_CAN_BE_HOST) && !defined(HOST_STATE_AS_GPIOR)
volatile uint8_t USB_HostState;
#endif
#if defined(USB_CAN_BE_DEVICE) && !defined(DEVICE_STATE_AS_GPIOR)
volatile uint8_t USB_DeviceState;
#endif
void USB_USBTask(void)
{
#if defined(USB_CAN_BE_BOTH)
if (USB_CurrentMode == USB_MODE_Device)
USB_DeviceTask();
else if (USB_CurrentMode == USB_MODE_Host)
USB_HostTask();
#elif defined(USB_CAN_BE_HOST)
USB_HostTask();
#elif defined(USB_CAN_BE_DEVICE)
USB_DeviceTask();
#endif
}
#if defined(USB_CAN_BE_DEVICE)
static void USB_DeviceTask(void)
{
if (USB_DeviceState == DEVICE_STATE_Unattached)
return;
uint8_t PrevEndpoint = Endpoint_GetCurrentEndpoint();
Endpoint_SelectEndpoint(ENDPOINT_CONTROLEP);
if (Endpoint_IsSETUPReceived())
USB_Device_ProcessControlRequest();
Endpoint_SelectEndpoint(PrevEndpoint);
}
#endif
#if defined(USB_CAN_BE_HOST)
static void USB_HostTask(void)
{
uint8_t PrevPipe = Pipe_GetCurrentPipe();
Pipe_SelectPipe(PIPE_CONTROLPIPE);
USB_Host_ProcessNextHostState();
Pipe_SelectPipe(PrevPipe);
}
#endif

View file

@ -0,0 +1,200 @@
/*
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 Main USB service task management.
*
* This file contains the function definitions required for the main USB service task, which must be called
* from the user application to ensure that the USB connection to or from a connected USB device is maintained.
*
* \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 __USBTASK_H__
#define __USBTASK_H__
/* Includes: */
#include "../../../Common/Common.h"
#include "USBMode.h"
#include "USBController.h"
#include "Events.h"
#include "StdRequestType.h"
#include "StdDescriptors.h"
#if defined(USB_CAN_BE_DEVICE)
#include "DeviceStandardReq.h"
#endif
#if defined(USB_CAN_BE_HOST)
#include "HostStandardReq.h"
#endif
/* 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: */
/* Global Variables: */
/** Indicates if the USB interface is currently initialized but not necessarily connected to a host
* or device (i.e. if \ref USB_Init() has been run). If this is false, all other library globals related
* to the USB driver are invalid.
*
* \attention This variable should be treated as read-only in the user application, and never manually
* changed in value.
*
* \ingroup Group_USBManagement
*/
extern volatile bool USB_IsInitialized;
/** Structure containing the last received Control request when in Device mode (for use in user-applications
* inside of the \ref EVENT_USB_Device_ControlRequest() event, or for filling up with a control request to
* issue when in Host mode before calling \ref USB_Host_SendControlRequest().
*
* \note The contents of this structure is automatically endian-corrected for the current CPU architecture.
*
* \ingroup Group_USBManagement
*/
extern USB_Request_Header_t USB_ControlRequest;
#if defined(USB_CAN_BE_HOST) || defined(__DOXYGEN__)
#if !defined(HOST_STATE_AS_GPIOR) || defined(__DOXYGEN__)
/** Indicates the current host state machine state. When in host mode, this indicates the state
* via one of the values of the \ref USB_Host_States_t enum values.
*
* This value should not be altered by the user application as it is handled automatically by the
* library.
*
* To reduce program size and speed up checks of this global on the AVR8 architecture, it can be
* placed into one of the AVR's \c GPIOR hardware registers instead of RAM by defining the
* \c HOST_STATE_AS_GPIOR token to a value between 0 and 2 in the project makefile and passing it to
* the compiler via the -D switch. When defined, the corresponding GPIOR register should not be used
* in the user application except implicitly via the library APIs.
*
* \note This global is only present if the user application can be a USB host.
*
* \see \ref USB_Host_States_t for a list of possible device states.
*
* \ingroup Group_Host
*/
extern volatile uint8_t USB_HostState;
#else
#define USB_HostState CONCAT_EXPANDED(GPIOR, HOST_STATE_AS_GPIOR)
#endif
#endif
#if defined(USB_CAN_BE_DEVICE) || defined(__DOXYGEN__)
#if !defined(DEVICE_STATE_AS_GPIOR) || defined(__DOXYGEN__)
/** Indicates the current device state machine state. When in device mode, this indicates the state
* via one of the values of the \ref USB_Device_States_t enum values.
*
* This value should not be altered by the user application as it is handled automatically by the
* library. The only exception to this rule is if the NO_LIMITED_CONTROLLER_CONNECT token is used
* (see \ref EVENT_USB_Device_Connect() and \ref EVENT_USB_Device_Disconnect() events).
*
* To reduce program size and speed up checks of this global on the AVR8 architecture, it can be
* placed into one of the AVR's \c GPIOR hardware registers instead of RAM by defining the
* \c DEVICE_STATE_AS_GPIOR token to a value between 0 and 2 in the project makefile and passing it to
* the compiler via the -D switch. When defined, the corresponding GPIOR register should not be used
* in the user application except implicitly via the library APIs.
*
* \attention This variable should be treated as read-only in the user application, and never manually
* changed in value except in the circumstances outlined above.
*
* \note This global is only present if the user application can be a USB device.
* \n\n
*
* \see \ref USB_Device_States_t for a list of possible device states.
*
* \ingroup Group_Device
*/
extern volatile uint8_t USB_DeviceState;
#else
#define USB_DeviceState CONCAT_EXPANDED(GPIOR, DEVICE_STATE_AS_GPIOR)
#endif
#endif
/* Function Prototypes: */
/** This is the main USB management task. The USB driver requires this task to be executed
* continuously when the USB system is active (device attached in host mode, or attached to a host
* in device mode) in order to manage USB communications. This task may be executed inside an RTOS,
* fast timer ISR or the main user application loop.
*
* The USB task must be serviced within 30ms while in device mode, or within 1ms while in host mode.
* The task may be serviced at all times, or (for minimum CPU consumption):
*
* - In device mode, it may be disabled at start-up, enabled on the firing of the \ref EVENT_USB_Device_Connect()
* event and disabled again on the firing of the \ref EVENT_USB_Device_Disconnect() event.
*
* - In host mode, it may be disabled at start-up, enabled on the firing of the \ref EVENT_USB_Host_DeviceAttached()
* event and disabled again on the firing of the \ref EVENT_USB_Host_DeviceEnumerationComplete() or
* \ref EVENT_USB_Host_DeviceEnumerationFailed() events.
*
* If in device mode (only), the control endpoint can instead be managed via interrupts entirely by the library
* by defining the INTERRUPT_CONTROL_ENDPOINT token and passing it to the compiler via the -D switch.
*
* \see \ref Group_Events for more information on the USB events.
*
* \ingroup Group_USBManagement
*/
void USB_USBTask(void);
/* Private Interface - For use in library only: */
#if !defined(__DOXYGEN__)
/* Function Prototypes: */
#if defined(__INCLUDE_FROM_USBTASK_C)
#if defined(USB_CAN_BE_HOST)
static void USB_HostTask(void);
#endif
#if defined(USB_CAN_BE_DEVICE)
static void USB_DeviceTask(void);
#endif
#endif
/* Macros: */
#define HOST_TASK_NONBLOCK_WAIT(Duration, NextState) do { USB_HostState = HOST_STATE_WaitForDevice; \
WaitMSRemaining = (Duration); \
PostWaitState = (NextState); } while (0)
#endif
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif

View file

@ -0,0 +1,49 @@
/*
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_XMEGA)
#define __INCLUDE_FROM_USB_DRIVER
#include "../USBMode.h"
#if defined(USB_CAN_BE_DEVICE)
#include "../Device.h"
void USB_Device_SendRemoteWakeup(void)
{
USB.CTRLB |= USB_RWAKEUP_bm;
}
#endif
#endif

View file

@ -0,0 +1,266 @@
/*
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 AVR XMEGA microcontrollers.
* \copydetails Group_Device_XMEGA
*
* \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_XMEGA Device Management (XMEGA)
* \brief USB Device definitions for the AVR XMEGA microcontrollers.
*
* Architecture specific USB Device definitions for the Atmel AVR XMEGA microcontrollers.
*
* @{
*/
#ifndef __USBDEVICE_XMEGA_H__
#define __USBDEVICE_XMEGA_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
#if (defined(USE_RAM_DESCRIPTORS) && defined(USE_EEPROM_DESCRIPTORS))
#error USE_RAM_DESCRIPTORS and USE_EEPROM_DESCRIPTORS are mutually exclusive.
#endif
#if (defined(USE_FLASH_DESCRIPTORS) && defined(USE_EEPROM_DESCRIPTORS))
#error USE_FLASH_DESCRIPTORS and USE_EEPROM_DESCRIPTORS are mutually exclusive.
#endif
#if (defined(USE_FLASH_DESCRIPTORS) && defined(USE_RAM_DESCRIPTORS))
#error USE_FLASH_DESCRIPTORS and USE_RAM_DESCRIPTORS are mutually exclusive.
#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 Low Speed mode is not available on all USB AVR models.
* \n
*
* \note Restrictions apply on the number, size and type of endpoints which can be used
* when running in low speed mode - refer to the USB 2.0 specification.
*/
#define USB_DEVICE_OPT_LOWSPEED (1 << 0)
#if (F_USB > 6000000)
/** 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)
#endif
//@}
#if (!defined(NO_INTERNAL_SERIAL) || 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 (8 * (1 + (offsetof(NVM_PROD_SIGNATURES_t, COORDY1) - offsetof(NVM_PROD_SIGNATURES_t, LOTNUM0))))
/** Start address of the internal serial number, in the appropriate address space, if present on the selected microcontroller
* model.
*/
#define INTERNAL_SERIAL_START_ADDRESS offsetof(NVM_PROD_SIGNATURES_t, LOTNUM0)
#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.
* \n\n
*
* \note The USB clock must be running for this function to operate. If the stack is initialized with
* the \ref USB_OPT_MANUAL_PLL option enabled, the user must ensure that the PLL is running
* before attempting to call this function.
*
* \see \ref Group_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 ((USB_EndpointTable_t*)USB.EPPTR)->FrameNum;
}
#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 This function is 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.INTCTRLA |= USB_SOFIE_bm;
}
/** 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 This function is 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.INTCTRLA &= ~USB_SOFIE_bm;
}
#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)
{
USB.CTRLA &= ~USB_SPEED_bm;
}
static inline void USB_Device_SetFullSpeed(void) ATTR_ALWAYS_INLINE;
static inline void USB_Device_SetFullSpeed(void)
{
USB.CTRLA |= USB_SPEED_bm;
}
static inline void USB_Device_SetDeviceAddress(const uint8_t Address) ATTR_ALWAYS_INLINE;
static inline void USB_Device_SetDeviceAddress(const uint8_t Address)
{
(void)Address;
/* No implementation for XMEGA architecture */
}
static inline void USB_Device_EnableDeviceAddress(const uint8_t Address) ATTR_ALWAYS_INLINE;
static inline void USB_Device_EnableDeviceAddress(const uint8_t Address)
{
USB.ADDR = Address;
}
static inline bool USB_Device_IsAddressSet(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
static inline bool USB_Device_IsAddressSet(void)
{
return ((USB.ADDR != 0) ? true : false);
}
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 = INTERNAL_SERIAL_START_ADDRESS;
for (uint8_t SerialCharNum = 0; SerialCharNum < (INTERNAL_SERIAL_LENGTH_BITS / 4); SerialCharNum++)
{
uint8_t SerialByte;
NVM.CMD = NVM_CMD_READ_CALIB_ROW_gc;
SerialByte = pgm_read_byte(SigReadAddress);
NVM.CMD = 0;
if (SerialCharNum & 0x01)
{
SerialByte >>= 4;
SigReadAddress++;
}
SerialByte &= 0x0F;
UnicodeString[SerialCharNum] = cpu_to_le16((SerialByte >= 10) ?
(('A' - 10) + SerialByte) : ('0' + SerialByte));
}
SetGlobalInterruptMask(CurrentGlobalInt);
}
#endif
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,275 @@
/*
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_XMEGA)
#define __INCLUDE_FROM_USB_DRIVER
#include "../USBMode.h"
#if defined(USB_CAN_BE_DEVICE)
#include "EndpointStream_XMEGA.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"
#if defined(ARCH_HAS_FLASH_ADDRESS_SPACE)
#define TEMPLATE_FUNC_NAME Endpoint_Write_Control_PStream_LE
#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_Control_W.c"
#define TEMPLATE_FUNC_NAME Endpoint_Write_Control_PStream_BE
#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_Control_W.c"
#endif
#if defined(ARCH_HAS_EEPROM_ADDRESS_SPACE)
#define TEMPLATE_FUNC_NAME Endpoint_Write_Control_EStream_LE
#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_Control_W.c"
#define TEMPLATE_FUNC_NAME Endpoint_Write_Control_EStream_BE
#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_Control_W.c"
#define TEMPLATE_FUNC_NAME Endpoint_Read_Control_EStream_LE
#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_Control_R.c"
#define TEMPLATE_FUNC_NAME Endpoint_Read_Control_EStream_BE
#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_Control_R.c"
#endif
#endif
#endif

View file

@ -0,0 +1,658 @@
/*
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 AVR XMEGA microcontrollers.
* \copydetails Group_EndpointStreamRW_XMEGA
*
* \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_XMEGA Read/Write of Multi-Byte Streams (XMEGA)
* \brief Endpoint data stream transmission and reception management for the Atmel AVR XMEGA architecture.
*
* Functions, macros, variables, enums and types related to data reading and writing of data streams from
* and to endpoints.
*
* @{
*/
#ifndef __ENDPOINT_STREAM_XMEGA_H__
#define __ENDPOINT_STREAM_XMEGA_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);
//@}
/** \name Stream functions for EEPROM source/destination data */
//@{
/** EEPROM buffer source version of \ref Endpoint_Write_Stream_LE().
*
* \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_EStream_LE(const void* const Buffer,
uint16_t Length,
uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
/** EEPROM buffer source version of \ref Endpoint_Write_Stream_BE().
*
* \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_EStream_BE(const void* const Buffer,
uint16_t Length,
uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
/** EEPROM buffer destination version of \ref Endpoint_Read_Stream_LE().
*
* \param[out] Buffer Pointer to the destination data buffer to write to, located in EEPROM memory space.
* \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_EStream_LE(void* const Buffer,
uint16_t Length,
uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
/** EEPROM buffer destination version of \ref Endpoint_Read_Stream_BE().
*
* \param[out] Buffer Pointer to the destination data buffer to write to, located in EEPROM memory space.
* \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_EStream_BE(void* const Buffer,
uint16_t Length,
uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
/** EEPROM buffer source version of Endpoint_Write_Control_Stream_LE.
*
* \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.
* \n\n
*
* \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_EStream_LE(const void* const Buffer,
uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
/** EEPROM buffer source version of \ref Endpoint_Write_Control_Stream_BE().
*
* \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.
* \n\n
*
* \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_EStream_BE(const void* const Buffer,
uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
/** EEPROM buffer source version of \ref Endpoint_Read_Control_Stream_LE().
*
* \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.
* \n\n
*
* \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_EStream_LE(void* const Buffer,
uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
/** EEPROM buffer source version of \ref Endpoint_Read_Control_Stream_BE().
*
* \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.
* \n\n
*
* \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_EStream_BE(void* const Buffer,
uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
//@}
/** \name Stream functions for PROGMEM source/destination data */
//@{
/** FLASH buffer source version of \ref Endpoint_Write_Stream_LE().
*
* \pre The FLASH data must be located in the first 64KB of FLASH for this function to work correctly.
*
* \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_PStream_LE(const void* const Buffer,
uint16_t Length,
uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
/** FLASH buffer source version of \ref Endpoint_Write_Stream_BE().
*
* \pre The FLASH data must be located in the first 64KB of FLASH for this function to work correctly.
*
* \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_PStream_BE(const void* const Buffer,
uint16_t Length,
uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
/** FLASH buffer source version of \ref Endpoint_Write_Control_Stream_LE().
*
* \pre The FLASH data must be located in the first 64KB of FLASH for this function to work correctly.
*
* \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.
* \n\n
*
* \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_PStream_LE(const void* const Buffer,
uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
/** FLASH buffer source version of \ref Endpoint_Write_Control_Stream_BE().
*
* \pre The FLASH data must be located in the first 64KB of FLASH for this function to work correctly.
*
* \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.
* \n\n
*
* \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_PStream_BE(const 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,268 @@
/*
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_XMEGA)
#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
Endpoint_FIFOPair_t USB_Endpoint_FIFOs[ENDPOINT_TOTAL_ENDPOINTS];
volatile uint8_t USB_Endpoint_SelectedEndpoint;
volatile USB_EP_t* USB_Endpoint_SelectedHandle;
volatile Endpoint_FIFO_t* USB_Endpoint_SelectedFIFO;
bool Endpoint_IsINReady(void)
{
Endpoint_SelectEndpoint(USB_Endpoint_SelectedEndpoint | ENDPOINT_DIR_IN);
return ((USB_Endpoint_SelectedHandle->STATUS & USB_EP_BUSNACK0_bm) ? true : false);
}
bool Endpoint_IsOUTReceived(void)
{
Endpoint_SelectEndpoint(USB_Endpoint_SelectedEndpoint & ~ENDPOINT_DIR_IN);
if (USB_Endpoint_SelectedHandle->STATUS & USB_EP_TRNCOMPL0_bm)
{
USB_Endpoint_SelectedFIFO->Length = USB_Endpoint_SelectedHandle->CNT;
return true;
}
return false;
}
bool Endpoint_IsSETUPReceived(void)
{
Endpoint_SelectEndpoint(USB_Endpoint_SelectedEndpoint & ~ENDPOINT_DIR_IN);
if (USB_Endpoint_SelectedHandle->STATUS & USB_EP_SETUP_bm)
{
USB_Endpoint_SelectedFIFO->Length = USB_Endpoint_SelectedHandle->CNT;
return true;
}
return false;
}
void Endpoint_ClearSETUP(void)
{
Endpoint_SelectEndpoint(USB_Endpoint_SelectedEndpoint & ~ENDPOINT_DIR_IN);
USB_Endpoint_SelectedHandle->STATUS &= ~(USB_EP_SETUP_bm | USB_EP_TRNCOMPL0_bm | USB_EP_BUSNACK0_bm | USB_EP_OVF_bm);
USB_Endpoint_SelectedHandle->STATUS |= USB_EP_TOGGLE_bm;
USB_Endpoint_SelectedFIFO->Position = 0;
Endpoint_SelectEndpoint(USB_Endpoint_SelectedEndpoint | ENDPOINT_DIR_IN);
USB_Endpoint_SelectedHandle->STATUS |= USB_EP_TOGGLE_bm;
USB_Endpoint_SelectedFIFO->Position = 0;
}
void Endpoint_ClearIN(void)
{
USB_Endpoint_SelectedHandle->CNT = USB_Endpoint_SelectedFIFO->Position;
USB_Endpoint_SelectedHandle->STATUS &= ~(USB_EP_TRNCOMPL0_bm | USB_EP_BUSNACK0_bm | USB_EP_OVF_bm);
USB_Endpoint_SelectedFIFO->Position = 0;
}
void Endpoint_ClearOUT(void)
{
USB_Endpoint_SelectedHandle->STATUS &= ~(USB_EP_TRNCOMPL0_bm | USB_EP_BUSNACK0_bm | USB_EP_OVF_bm);
USB_Endpoint_SelectedFIFO->Position = 0;
}
void Endpoint_StallTransaction(void)
{
USB_Endpoint_SelectedHandle->CTRL |= USB_EP_STALL_bm;
if ((USB_Endpoint_SelectedHandle->CTRL & USB_EP_TYPE_gm) == USB_EP_TYPE_CONTROL_gc)
{
Endpoint_SelectEndpoint(USB_Endpoint_SelectedEndpoint ^ ENDPOINT_DIR_IN);
USB_Endpoint_SelectedHandle->CTRL |= USB_EP_STALL_bm;
}
}
uint8_t Endpoint_Read_8(void)
{
return USB_Endpoint_SelectedFIFO->Data[USB_Endpoint_SelectedFIFO->Position++];
}
void Endpoint_Write_8(const uint8_t Data)
{
USB_Endpoint_SelectedFIFO->Data[USB_Endpoint_SelectedFIFO->Position++] = Data;
}
void Endpoint_SelectEndpoint(const uint8_t Address)
{
uint8_t EndpointNumber = (Address & ENDPOINT_EPNUM_MASK);
USB_Endpoint_SelectedEndpoint = Address;
Endpoint_FIFOPair_t* EndpointFIFOPair = &USB_Endpoint_FIFOs[EndpointNumber];
USB_EndpointTable_t* EndpointTable = (USB_EndpointTable_t*)USB.EPPTR;
if (Address & ENDPOINT_DIR_IN)
{
USB_Endpoint_SelectedFIFO = &EndpointFIFOPair->IN;
USB_Endpoint_SelectedHandle = &EndpointTable->Endpoints[EndpointNumber].IN;
}
else
{
USB_Endpoint_SelectedFIFO = &EndpointFIFOPair->OUT;
USB_Endpoint_SelectedHandle = &EndpointTable->Endpoints[EndpointNumber].OUT;
}
}
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 Address,
const uint8_t Config,
const uint8_t Size)
{
Endpoint_SelectEndpoint(Address);
USB_Endpoint_SelectedHandle->CTRL = 0;
USB_Endpoint_SelectedHandle->STATUS = (Address & ENDPOINT_DIR_IN) ? USB_EP_BUSNACK0_bm : 0;
USB_Endpoint_SelectedHandle->CTRL = Config;
USB_Endpoint_SelectedHandle->CNT = 0;
USB_Endpoint_SelectedHandle->DATAPTR = (intptr_t)USB_Endpoint_SelectedFIFO->Data;
USB_Endpoint_SelectedFIFO->Length = (Address & ENDPOINT_DIR_IN) ? Size : 0;
USB_Endpoint_SelectedFIFO->Position = 0;
return true;
}
void Endpoint_ClearEndpoints(void)
{
for (uint8_t EPNum = 0; EPNum < ENDPOINT_TOTAL_ENDPOINTS; EPNum++)
{
((USB_EndpointTable_t*)USB.EPPTR)->Endpoints[EPNum].IN.CTRL = 0;
((USB_EndpointTable_t*)USB.EPPTR)->Endpoints[EPNum].OUT.CTRL = 0;
}
}
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,689 @@
/*
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 AVR XMEGA microcontrollers.
* \copydetails Group_EndpointManagement_XMEGA
*
* \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_XMEGA Endpoint Data Reading and Writing (XMEGA)
* \brief Endpoint data read/write definitions for the Atmel AVR XMEGA architecture.
*
* Functions, macros, variables, enums and types related to data reading and writing from and to endpoints.
*/
/** \ingroup Group_EndpointPrimitiveRW
* \defgroup Group_EndpointPrimitiveRW_XMEGA Read/Write of Primitive Data Types (XMEGA)
* \brief Endpoint primitive read/write definitions for the Atmel AVR XMEGA 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_XMEGA Endpoint Packet Management (XMEGA)
* \brief Endpoint packet management definitions for the Atmel AVR XMEGA architecture.
*
* Functions, macros, variables, enums and types related to packet management of endpoints.
*/
/** \ingroup Group_EndpointManagement
* \defgroup Group_EndpointManagement_XMEGA Endpoint Management (XMEGA)
* \brief Endpoint management definitions for the Atmel AVR XMEGA 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_XMEGA_H__
#define __ENDPOINT_XMEGA_H__
/* Includes: */
#include "../../../../Common/Common.h"
#include "../USBTask.h"
#include "../USBInterrupt.h"
#include "../USBController.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: */
#if (!defined(MAX_ENDPOINT_INDEX) && !defined(CONTROL_ONLY_DEVICE)) || defined(__DOXYGEN__)
/** Total number of endpoints (including the default control endpoint at address 0) which may
* be used in the device. Different USB AVR models support different amounts of endpoints,
* this value reflects the maximum number of endpoints for the currently selected AVR model.
*/
#define ENDPOINT_TOTAL_ENDPOINTS 16
#else
#if defined(CONTROL_ONLY_DEVICE)
#define ENDPOINT_TOTAL_ENDPOINTS 1
#else
#define ENDPOINT_TOTAL_ENDPOINTS (MAX_ENDPOINT_INDEX + 1)
#endif
#endif
/* Private Interface - For use in library only: */
#if !defined(__DOXYGEN__)
/* Type Defines: */
typedef struct
{
uint8_t Data[64];
uint8_t Length;
uint8_t Position;
} Endpoint_FIFO_t;
typedef struct
{
Endpoint_FIFO_t OUT;
Endpoint_FIFO_t IN;
} Endpoint_FIFOPair_t;
/* External Variables: */
extern Endpoint_FIFOPair_t USB_Endpoint_FIFOs[ENDPOINT_TOTAL_ENDPOINTS];
extern volatile uint8_t USB_Endpoint_SelectedEndpoint;
extern volatile USB_EP_t* USB_Endpoint_SelectedHandle;
extern volatile Endpoint_FIFO_t* USB_Endpoint_SelectedFIFO;
/* Inline Functions: */
static inline uint8_t Endpoint_BytesToEPSizeMask(const uint16_t Bytes) ATTR_WARN_UNUSED_RESULT ATTR_CONST
ATTR_ALWAYS_INLINE;
static inline uint8_t Endpoint_BytesToEPSizeMask(const uint16_t Bytes)
{
uint8_t MaskVal = 0;
uint16_t CheckBytes = 8;
while (CheckBytes < Bytes)
{
MaskVal++;
CheckBytes <<= 1;
}
return (MaskVal << USB_EP_BUFSIZE_gp);
}
/* Function Prototypes: */
bool Endpoint_ConfigureEndpoint_PRV(const uint8_t Address,
const uint8_t Config,
const uint8_t Size);
void Endpoint_ClearEndpoints(void);
#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
/* Enums: */
/** Enum for the possible error return codes of the \ref Endpoint_WaitUntilReady() function.
*
* \ingroup Group_EndpointRW_XMEGA
*/
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: */
/** 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.
*/
void Endpoint_SelectEndpoint(const uint8_t Address);
/** 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.
*
* \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.
*
* \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 EPConfigMask = (USB_EP_INTDSBL_bm | ((Banks > 1) ? USB_EP_PINGPONG_bm : 0) | Endpoint_BytesToEPSizeMask(Size));
if ((Address & ENDPOINT_EPNUM_MASK) >= ENDPOINT_TOTAL_ENDPOINTS)
return false;
// TODO - Fix once limitations are lifted
EPConfigMask &= ~USB_EP_PINGPONG_bm;
if (Size > 64)
return false;
switch (Type)
{
case EP_TYPE_CONTROL:
EPConfigMask |= USB_EP_TYPE_CONTROL_gc;
break;
case EP_TYPE_ISOCHRONOUS:
EPConfigMask |= USB_EP_TYPE_ISOCHRONOUS_gc;
break;
default:
EPConfigMask |= USB_EP_TYPE_BULK_gc;
break;
}
if (Type == EP_TYPE_CONTROL)
Endpoint_ConfigureEndpoint_PRV(Address ^ ENDPOINT_DIR_IN, EPConfigMask, Size);
return Endpoint_ConfigureEndpoint_PRV(Address, EPConfigMask, Size);
}
/** Indicates the number of bytes currently stored in the current endpoint's selected bank.
*
* \ingroup Group_EndpointRW_XMEGA
*
* \return Total number of bytes in the currently selected Endpoint's FIFO buffer.
*/
static inline uint16_t Endpoint_BytesInEndpoint(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline uint16_t Endpoint_BytesInEndpoint(void)
{
if (USB_Endpoint_SelectedEndpoint & ENDPOINT_DIR_IN)
return USB_Endpoint_SelectedFIFO->Position;
else
return (USB_Endpoint_SelectedFIFO->Length - USB_Endpoint_SelectedFIFO->Position);
}
/** 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;
}
/** 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 address 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)
{
if (Address & ENDPOINT_DIR_IN)
USB_Endpoint_FIFOs[Address & ENDPOINT_EPNUM_MASK].IN.Position = 0;
else
USB_Endpoint_FIFOs[Address & ENDPOINT_EPNUM_MASK].OUT.Position = 0;
}
/** 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 true;
}
/** 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_XMEGA
*/
static inline void Endpoint_AbortPendingIN(void)
{
USB_Endpoint_SelectedHandle->STATUS |= USB_EP_BUSNACK0_bm;
}
/** 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_XMEGA
*
* \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 (USB_Endpoint_SelectedFIFO->Position < USB_Endpoint_SelectedFIFO->Length);
}
/** 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 ((USB_Endpoint_SelectedHandle->CTRL & USB_EP_TYPE_gm) ? true : false);
}
/** Determines if the selected IN endpoint is ready for a new packet to be sent to the host.
*
* \ingroup Group_EndpointPacketManagement_XMEGA
*
* \return Boolean \c true if the current endpoint is ready for an IN packet, \c false otherwise.
*/
bool Endpoint_IsINReady(void) ATTR_WARN_UNUSED_RESULT;
/** Determines if the selected OUT endpoint has received new packet from the host.
*
* \ingroup Group_EndpointPacketManagement_XMEGA
*
* \return Boolean \c true if current endpoint is has received an OUT packet, \c false otherwise.
*/
bool Endpoint_IsOUTReceived(void) ATTR_WARN_UNUSED_RESULT;
/** Determines if the current CONTROL type endpoint has received a SETUP packet.
*
* \ingroup Group_EndpointPacketManagement_XMEGA
*
* \return Boolean \c true if the selected endpoint has received a SETUP packet, \c false otherwise.
*/
bool Endpoint_IsSETUPReceived(void) ATTR_WARN_UNUSED_RESULT;
/** Clears a received SETUP packet on the currently selected CONTROL type endpoint, freeing up the
* endpoint for the next packet.
*
* \ingroup Group_EndpointPacketManagement_XMEGA
*
* \note This is not applicable for non CONTROL type endpoints.
*/
void Endpoint_ClearSETUP(void);
/** 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_XMEGA
*/
void Endpoint_ClearIN(void);
/** 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_XMEGA
*/
void Endpoint_ClearOUT(void);
/** 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_XMEGA
*/
void Endpoint_StallTransaction(void);
/** Clears the STALL condition on the currently selected endpoint.
*
* \ingroup Group_EndpointPacketManagement_XMEGA
*/
static inline void Endpoint_ClearStall(void) ATTR_ALWAYS_INLINE;
static inline void Endpoint_ClearStall(void)
{
USB_Endpoint_SelectedHandle->CTRL &= ~USB_EP_STALL_bm;
}
/** Determines if the currently selected endpoint is stalled, \c false otherwise.
*
* \ingroup Group_EndpointPacketManagement_XMEGA
*
* \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 ((USB_Endpoint_SelectedHandle->CTRL & USB_EP_STALL_bm) ? true : false);
}
/** Resets the data toggle of the currently selected endpoint. */
static inline void Endpoint_ResetDataToggle(void) ATTR_ALWAYS_INLINE;
static inline void Endpoint_ResetDataToggle(void)
{
USB_Endpoint_SelectedHandle->STATUS &= ~USB_EP_TOGGLE_bm;
}
/** Determines the currently selected endpoint's direction.
*
* \return The currently selected endpoint's direction, as a \c ENDPOINT_DIR_* mask.
*/
static inline uint8_t Endpoint_GetEndpointDirection(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline uint8_t Endpoint_GetEndpointDirection(void)
{
return (USB_Endpoint_SelectedEndpoint & ENDPOINT_DIR_IN);
}
/** Reads one byte from the currently selected endpoint's bank, for OUT direction endpoints.
*
* \ingroup Group_EndpointPrimitiveRW_XMEGA
*
* \return Next byte in the currently selected endpoint's FIFO buffer.
*/
uint8_t Endpoint_Read_8(void) ATTR_WARN_UNUSED_RESULT;
/** Writes one byte to the currently selected endpoint's bank, for IN direction endpoints.
*
* \ingroup Group_EndpointPrimitiveRW_XMEGA
*
* \param[in] Data Data to write into the the currently selected endpoint's FIFO buffer.
*/
void Endpoint_Write_8(const uint8_t Data);
/** Discards one byte from the currently selected endpoint's bank, for OUT direction endpoints.
*
* \ingroup Group_EndpointPrimitiveRW_XMEGA
*/
static inline void Endpoint_Discard_8(void) ATTR_ALWAYS_INLINE;
static inline void Endpoint_Discard_8(void)
{
USB_Endpoint_SelectedFIFO->Position++;
}
/** Reads two bytes from the currently selected endpoint's bank in little endian format, for OUT
* direction endpoints.
*
* \ingroup Group_EndpointPrimitiveRW_XMEGA
*
* \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 = Endpoint_Read_8();
uint16_t Byte1 = Endpoint_Read_8();
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_XMEGA
*
* \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 = Endpoint_Read_8();
uint16_t Byte1 = Endpoint_Read_8();
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_XMEGA
*
* \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)
{
Endpoint_Write_8(Data & 0xFF);
Endpoint_Write_8(Data >> 8);
}
/** Writes two bytes to the currently selected endpoint's bank in big endian format, for IN
* direction endpoints.
*
* \ingroup Group_EndpointPrimitiveRW_XMEGA
*
* \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)
{
Endpoint_Write_8(Data >> 8);
Endpoint_Write_8(Data & 0xFF);
}
/** Discards two bytes from the currently selected endpoint's bank, for OUT direction endpoints.
*
* \ingroup Group_EndpointPrimitiveRW_XMEGA
*/
static inline void Endpoint_Discard_16(void) ATTR_ALWAYS_INLINE;
static inline void Endpoint_Discard_16(void)
{
Endpoint_Discard_8();
Endpoint_Discard_8();
}
/** Reads four bytes from the currently selected endpoint's bank in little endian format, for OUT
* direction endpoints.
*
* \ingroup Group_EndpointPrimitiveRW_XMEGA
*
* \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 = Endpoint_Read_8();
uint32_t Byte1 = Endpoint_Read_8();
uint32_t Byte2 = Endpoint_Read_8();
uint32_t Byte3 = Endpoint_Read_8();
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_XMEGA
*
* \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 = Endpoint_Read_8();
uint32_t Byte1 = Endpoint_Read_8();
uint32_t Byte2 = Endpoint_Read_8();
uint32_t Byte3 = Endpoint_Read_8();
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_XMEGA
*
* \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)
{
Endpoint_Write_8(Data & 0xFF);
Endpoint_Write_8(Data >> 8);
Endpoint_Write_8(Data >> 16);
Endpoint_Write_8(Data >> 24);
}
/** Writes four bytes to the currently selected endpoint's bank in big endian format, for IN
* direction endpoints.
*
* \ingroup Group_EndpointPrimitiveRW_XMEGA
*
* \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)
{
Endpoint_Write_8(Data >> 24);
Endpoint_Write_8(Data >> 16);
Endpoint_Write_8(Data >> 8);
Endpoint_Write_8(Data & 0xFF);
}
/** Discards four bytes from the currently selected endpoint's bank, for OUT direction endpoints.
*
* \ingroup Group_EndpointPrimitiveRW_XMEGA
*/
static inline void Endpoint_Discard_32(void) ATTR_ALWAYS_INLINE;
static inline void Endpoint_Discard_32(void)
{
Endpoint_Discard_8();
Endpoint_Discard_8();
Endpoint_Discard_8();
Endpoint_Discard_8();
}
/* 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_XMEGA
*
* \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,41 @@
/*
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_XMEGA)
#define __INCLUDE_FROM_USB_DRIVER
#include "../USBMode.h"
#if defined(USB_CAN_BE_HOST)
#endif
#endif

View file

@ -0,0 +1,41 @@
/*
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_XMEGA)
#define __INCLUDE_FROM_USB_DRIVER
#include "../USBMode.h"
#if defined(USB_CAN_BE_HOST)
#endif
#endif

View file

@ -0,0 +1,37 @@
/*
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.
*/
#define __INCLUDE_FROM_USB_DRIVER
#include "../USBMode.h"
#if defined(USB_CAN_BE_HOST)
#endif

View file

@ -0,0 +1,86 @@
/*
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));
Endpoint_SelectEndpoint(USB_Endpoint_SelectedEndpoint & ~ENDPOINT_DIR_IN);
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,97 @@
/*
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;
Endpoint_SelectEndpoint(USB_Endpoint_SelectedEndpoint | ENDPOINT_DIR_IN);
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,204 @@
/*
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_XMEGA)
#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
/* Ugly workaround to ensure an aligned table, since __BIGGEST_ALIGNMENT__ == 1 for the 8-bit AVR-GCC toolchain */
uint8_t USB_EndpointTable[sizeof(USB_EndpointTable_t) + 1];
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
uint_reg_t CurrentGlobalInt = GetGlobalInterruptMask();
GlobalInterruptDisable();
NVM.CMD = NVM_CMD_READ_CALIB_ROW_gc;
USB.CAL0 = pgm_read_byte(offsetof(NVM_PROD_SIGNATURES_t, USBCAL0));
USB.CAL1 = pgm_read_byte(offsetof(NVM_PROD_SIGNATURES_t, USBCAL1));
NVM.CMD = NVM_CMD_NO_OPERATION_gc;
/* Ugly workaround to ensure an aligned table, since __BIGGEST_ALIGNMENT__ == 1 for the 8-bit AVR-GCC toolchain */
USB.EPPTR = ((intptr_t)&USB_EndpointTable[1] & ~(1 << 0));
USB.CTRLA = (USB_STFRNUM_bm | ((ENDPOINT_TOTAL_ENDPOINTS - 1) << USB_MAXEP_gp));
if ((USB_Options & USB_OPT_BUSEVENT_PRIHIGH) == USB_OPT_BUSEVENT_PRIHIGH)
USB.INTCTRLA = (3 << USB_INTLVL_gp);
else if ((USB_Options & USB_OPT_BUSEVENT_PRIMED) == USB_OPT_BUSEVENT_PRIMED)
USB.INTCTRLA = (2 << USB_INTLVL_gp);
else
USB.INTCTRLA = (1 << USB_INTLVL_gp);
SetGlobalInterruptMask(CurrentGlobalInt);
#if defined(USB_CAN_BE_BOTH)
USB_CurrentMode = Mode;
#endif
USB_IsInitialized = true;
USB_ResetInterface();
}
void USB_Disable(void)
{
USB_INT_DisableAllInterrupts();
USB_INT_ClearAllInterrupts();
USB_Detach();
USB_Controller_Disable();
USB_IsInitialized = false;
}
void USB_ResetInterface(void)
{
uint8_t PrescalerNeeded;
#if defined(USB_DEVICE_OPT_FULLSPEED)
if (USB_Options & USB_DEVICE_OPT_LOWSPEED)
PrescalerNeeded = F_USB / 6000000;
else
PrescalerNeeded = F_USB / 48000000;
#else
PrescalerNeeded = F_USB / 6000000;
#endif
uint8_t DividerIndex = 0;
while (PrescalerNeeded > 0)
{
DividerIndex++;
PrescalerNeeded >>= 1;
}
CLK.USBCTRL = (DividerIndex - 1) << CLK_USBPSDIV_gp;
if (USB_Options & USB_OPT_PLLCLKSRC)
CLK.USBCTRL |= (CLK_USBSRC_PLL_gc | CLK_USBSEN_bm);
else
CLK.USBCTRL |= (CLK_USBSRC_RC32M_gc | CLK_USBSEN_bm);
USB_Device_SetDeviceAddress(0);
USB_INT_DisableAllInterrupts();
USB_INT_ClearAllInterrupts();
USB_Controller_Reset();
USB_Init_Device();
}
#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 defined(ARCH_HAS_MULTI_ADDRESS_SPACE) && \
!(defined(USE_FLASH_DESCRIPTORS) || defined(USE_EEPROM_DESCRIPTORS) || defined(USE_RAM_DESCRIPTORS))
uint8_t DescriptorAddressSpace;
if (CALLBACK_USB_GetDescriptor((DTYPE_Device << 8), 0, (void*)&DeviceDescriptorPtr, &DescriptorAddressSpace) != NO_DESCRIPTOR)
{
if (DescriptorAddressSpace == MEMSPACE_FLASH)
USB_Device_ControlEndpointSize = pgm_read_byte(&DeviceDescriptorPtr->Endpoint0Size);
else if (DescriptorAddressSpace == MEMSPACE_EEPROM)
USB_Device_ControlEndpointSize = eeprom_read_byte(&DeviceDescriptorPtr->Endpoint0Size);
else
USB_Device_ControlEndpointSize = DeviceDescriptorPtr->Endpoint0Size;
}
#else
if (CALLBACK_USB_GetDescriptor((DTYPE_Device << 8), 0, (void*)&DeviceDescriptorPtr) != NO_DESCRIPTOR)
{
#if defined(USE_RAM_DESCRIPTORS)
USB_Device_ControlEndpointSize = DeviceDescriptorPtr->Endpoint0Size;
#elif defined(USE_EEPROM_DESCRIPTORS)
USB_Device_ControlEndpointSize = eeprom_read_byte(&DeviceDescriptorPtr->Endpoint0Size);
#else
USB_Device_ControlEndpointSize = pgm_read_byte(&DeviceDescriptorPtr->Endpoint0Size);
#endif
}
#endif
#endif
if (USB_Options & USB_DEVICE_OPT_LOWSPEED)
USB_Device_SetLowSpeed();
else
USB_Device_SetFullSpeed();
Endpoint_ConfigureEndpoint(ENDPOINT_CONTROLEP, EP_TYPE_CONTROL,
USB_Device_ControlEndpointSize, 1);
USB_INT_Enable(USB_INT_BUSEVENTI);
USB_Attach();
}
#endif
#endif

View file

@ -0,0 +1,313 @@
/*
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 AVR XMEGA microcontrollers.
* \copydetails Group_USBManagement_XMEGA
*
* \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_XMEGA USB Interface Management (XMEGA)
* \brief USB Controller definitions for the AVR XMEGA microcontrollers.
*
* Functions, macros, variables, enums and types related to the setup and management of the USB interface.
*
* @{
*/
#ifndef __USBCONTROLLER_XMEGA_H__
#define __USBCONTROLLER_XMEGA_H__
/* Includes: */
#include "../../../../Common/Common.h"
#include "../USBMode.h"
#include "../Events.h"
#include "../USBTask.h"
#include "../USBInterrupt.h"
/* Private Interface - For use in library only: */
#if !defined(__DOXYGEN__)
/* Macros: */
#if defined(MAX_ENDPOINT_INDEX)
#define ENDPOINT_TABLE_COUNT (MAX_ENDPOINT_INDEX + 1)
#else
#define ENDPOINT_TABLE_COUNT 16
#endif
/* Type Defines: */
typedef struct
{
struct
{
USB_EP_t OUT;
USB_EP_t IN;
} Endpoints[ENDPOINT_TABLE_COUNT];
uint16_t FrameNum;
} ATTR_PACKED USB_EndpointTable_t;
/* External Variables: */
extern uint8_t USB_EndpointTable[];
#endif
/* Includes: */
#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 unprescaled USB controller clock in your project makefile.
#endif
#if ((F_USB % 6000000) || (F_USB < 6000000))
#error Invalid F_USB specified. F_USB must be a multiple of 6MHz for USB Low Speed operation, and a multiple of 48MHz for Full Speed operation.
#endif
/* Public Interface - May be used in end-application: */
/* Macros: */
/** \name USB Controller Option Masks */
//@{
/** Sets the USB bus interrupt priority level to be low priority. The USB bus interrupt is used for Start of Frame events, bus suspend
* and resume events, bus reset events and other events related to the management of the USB bus.
*/
#define USB_OPT_BUSEVENT_PRILOW ((0 << 2) | (0 << 1))
/** Sets the USB bus interrupt priority level to be medium priority. The USB bus interrupt is used for Start of Frame events, bus suspend
* and resume events, bus reset events and other events related to the management of the USB bus.
*/
#define USB_OPT_BUSEVENT_PRIMED ((0 << 2) | (1 << 1))
/** Sets the USB bus interrupt priority level to be high priority. The USB bus interrupt is used for Start of Frame events, bus suspend
* and resume events, bus reset events and other events related to the management of the USB bus.
*/
#define USB_OPT_BUSEVENT_PRIHIGH ((1 << 2) | (0 << 1))
/** Sets the USB controller to source its clock from the internal RC 32MHz clock, once it has been DFLL calibrated to 48MHz. */
#define USB_OPT_RC32MCLKSRC (0 << 3)
/** Sets the USB controller to source its clock from the internal PLL. */
#define USB_OPT_PLLCLKSRC (1 << 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: */
/** 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)
{
USB.CTRLB &= ~USB_ATTACH_bm;
}
/** 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)
{
USB.CTRLB |= USB_ATTACH_bm;
}
/* 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.
* \n\n
*
* \note The mode parameter does not exist on devices where only one mode is possible, such as USB
* AVR models which only implement the USB device mode in hardware.
*
* \see \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__)
/* Function Prototypes: */
#if defined(__INCLUDE_FROM_USB_CONTROLLER_C)
static void USB_Init_Device(void);
#endif
/* Inline Functions: */
static inline void USB_Controller_Enable(void) ATTR_ALWAYS_INLINE;
static inline void USB_Controller_Enable(void)
{
USB.CTRLA |= USB_ENABLE_bm;
}
static inline void USB_Controller_Disable(void) ATTR_ALWAYS_INLINE;
static inline void USB_Controller_Disable(void)
{
USB.CTRLA &= ~USB_ENABLE_bm;
}
static inline void USB_Controller_Reset(void) ATTR_ALWAYS_INLINE;
static inline void USB_Controller_Reset(void)
{
USB.CTRLA &= ~USB_ENABLE_bm;
USB.CTRLA |= USB_ENABLE_bm;
}
#endif
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,106 @@
/*
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_XMEGA)
#define __INCLUDE_FROM_USB_DRIVER
#include "../USBInterrupt.h"
void USB_INT_DisableAllInterrupts(void)
{
USB.INTCTRLA &= USB_INTLVL_gm;
USB.INTCTRLB = 0;
}
void USB_INT_ClearAllInterrupts(void)
{
USB.INTFLAGSACLR = 0xFF;
USB.INTFLAGSBCLR = 0xFF;
}
ISR(USB_BUSEVENT_vect)
{
#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_BUSEVENTI_Suspend))
{
USB_INT_Clear(USB_INT_BUSEVENTI_Suspend);
#if !defined(NO_LIMITED_CONTROLLER_CONNECT)
USB_DeviceState = DEVICE_STATE_Unattached;
EVENT_USB_Device_Disconnect();
#else
USB_DeviceState = DEVICE_STATE_Suspended;
EVENT_USB_Device_Suspend();
#endif
}
if (USB_INT_HasOccurred(USB_INT_BUSEVENTI_Resume))
{
USB_INT_Clear(USB_INT_BUSEVENTI_Resume);
if (USB_Device_ConfigurationNumber)
USB_DeviceState = DEVICE_STATE_Configured;
else
USB_DeviceState = (USB_Device_IsAddressSet()) ? DEVICE_STATE_Addressed : DEVICE_STATE_Powered;
#if !defined(NO_LIMITED_CONTROLLER_CONNECT)
EVENT_USB_Device_Connect();
#else
EVENT_USB_Device_WakeUp();
#endif
}
if (USB_INT_HasOccurred(USB_INT_BUSEVENTI_Reset))
{
USB_INT_Clear(USB_INT_BUSEVENTI_Reset);
USB_DeviceState = DEVICE_STATE_Default;
USB_Device_ConfigurationNumber = 0;
USB_Device_EnableDeviceAddress(0);
Endpoint_ClearEndpoints();
Endpoint_ConfigureEndpoint(ENDPOINT_CONTROLEP, EP_TYPE_CONTROL,
USB_Device_ControlEndpointSize, 1);
EVENT_USB_Device_Reset();
}
}
#endif

View file

@ -0,0 +1,172 @@
/*
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 AVR XMEGA 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_XMEGA_H__
#define __USBINTERRUPT_XMEGA_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__)
/* Enums: */
enum USB_Interrupts_t
{
USB_INT_BUSEVENTI = 1,
USB_INT_BUSEVENTI_Suspend = 2,
USB_INT_BUSEVENTI_Resume = 3,
USB_INT_BUSEVENTI_Reset = 4,
USB_INT_SOFI = 5,
};
/* 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_BUSEVENTI:
USB.INTCTRLA |= USB_BUSEVIE_bm;
break;
case USB_INT_SOFI:
USB.INTCTRLA |= USB_SOFIE_bm;
break;
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_BUSEVENTI:
USB.INTCTRLA &= ~USB_BUSEVIE_bm;
break;
case USB_INT_SOFI:
USB.INTCTRLA &= ~USB_SOFIE_bm;
break;
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_BUSEVENTI_Suspend:
USB.INTFLAGSACLR = USB_SUSPENDIF_bm;
break;
case USB_INT_BUSEVENTI_Resume:
USB.INTFLAGSACLR = USB_RESUMEIF_bm;
break;
case USB_INT_BUSEVENTI_Reset:
USB.INTFLAGSACLR = USB_RSTIF_bm;
break;
case USB_INT_SOFI:
USB.INTFLAGSACLR = USB_SOFIF_bm;
break;
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_BUSEVENTI:
return ((USB.INTCTRLA & USB_BUSEVIE_bm) ? true : false);
case USB_INT_SOFI:
return ((USB.INTCTRLA & USB_SOFIE_bm) ? true : false);
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_BUSEVENTI_Suspend:
return ((USB.INTFLAGSACLR & USB_SUSPENDIF_bm) ? true : false);
case USB_INT_BUSEVENTI_Resume:
return ((USB.INTFLAGSACLR & USB_RESUMEIF_bm) ? true : false);
case USB_INT_BUSEVENTI_Reset:
return ((USB.INTFLAGSACLR & USB_RSTIF_bm) ? true : false);
case USB_INT_SOFI:
return ((USB.INTFLAGSACLR & USB_SOFIF_bm) ? true : false);
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
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif