From 8629e1918c9be8cab4421077cf2e62445599fc47 Mon Sep 17 00:00:00 2001 From: Dean Camera Date: Thu, 14 Jul 2011 07:19:30 +0000 Subject: [PATCH] Implementation of several key core USB driver functions for the new USB XMEGA devices. --- LUFA/Drivers/USB/Core/XMEGA/Device_XMEGA.h | 48 +++++++--- LUFA/Drivers/USB/Core/XMEGA/Endpoint_XMEGA.h | 37 ++------ .../USB/Core/XMEGA/USBController_XMEGA.c | 74 +++++++++++++++- .../USB/Core/XMEGA/USBController_XMEGA.h | 87 +++---------------- 4 files changed, 124 insertions(+), 122 deletions(-) diff --git a/LUFA/Drivers/USB/Core/XMEGA/Device_XMEGA.h b/LUFA/Drivers/USB/Core/XMEGA/Device_XMEGA.h index 805e8f9ba7..f0a472ed61 100644 --- a/LUFA/Drivers/USB/Core/XMEGA/Device_XMEGA.h +++ b/LUFA/Drivers/USB/Core/XMEGA/Device_XMEGA.h @@ -81,12 +81,12 @@ * \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) + #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) + #define USB_DEVICE_OPT_FULLSPEED (0 << 0) //@} /** String descriptor index for the device's unique serial number string descriptor within the device. @@ -98,17 +98,17 @@ * 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 NO_DESCRIPTOR + #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 0 + #define INTERNAL_SERIAL_LENGTH_BITS 112 /** Start address of the internal serial number, in the appropriate address space, if present on the selected microcontroller * model. */ - #define INTERNAL_SERIAL_START_ADDRESS 0 + #define INTERNAL_SERIAL_START_ADDRESS 0x08 /* Function Prototypes: */ /** Sends a Remote Wakeup request to the host. This signals to the host that the device should @@ -173,34 +173,58 @@ static inline void USB_Device_SetLowSpeed(void) ATTR_ALWAYS_INLINE; static inline void USB_Device_SetLowSpeed(void) { - // TODO + USB.CTRLA &= ~USB_SPEED_bm; } static inline void USB_Device_SetFullSpeed(void) ATTR_ALWAYS_INLINE; static inline void USB_Device_SetFullSpeed(void) { - // TODO + 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) { - // TODO + 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 false; // TODO + return ((USB.ADDR != 0) ? true : false); } - #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) { - // TODO + 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); + + if (SerialCharNum & 0x01) + { + SerialByte >>= 4; + SigReadAddress++; + } + + SerialByte &= 0x0F; + + UnicodeString[SerialCharNum] = cpu_to_le16((SerialByte >= 10) ? + (('A' - 10) + SerialByte) : ('0' + SerialByte)); + } + + SetGlobalInterruptMask(CurrentGlobalInt); + + } - #endif #endif diff --git a/LUFA/Drivers/USB/Core/XMEGA/Endpoint_XMEGA.h b/LUFA/Drivers/USB/Core/XMEGA/Endpoint_XMEGA.h index e43422ef50..c444433a62 100644 --- a/LUFA/Drivers/USB/Core/XMEGA/Endpoint_XMEGA.h +++ b/LUFA/Drivers/USB/Core/XMEGA/Endpoint_XMEGA.h @@ -90,33 +90,10 @@ /* Private Interface - For use in library only: */ #if !defined(__DOXYGEN__) /* Macros: */ - #define _ENDPOINT_GET_MAXSIZE(EPIndex) _ENDPOINT_GET_MAXSIZE2(ENDPOINT_DETAILS_EP ## EPIndex) - #define _ENDPOINT_GET_MAXSIZE2(EPDetails) _ENDPOINT_GET_MAXSIZE3(EPDetails) - #define _ENDPOINT_GET_MAXSIZE3(MaxSize, Banks) (MaxSize) - - #define _ENDPOINT_GET_BANKS(EPIndex) _ENDPOINT_GET_BANKS2(ENDPOINT_DETAILS_EP ## EPIndex) - #define _ENDPOINT_GET_BANKS2(EPDetails) _ENDPOINT_GET_BANKS3(EPDetails) - #define _ENDPOINT_GET_BANKS3(MaxSize, Banks) (Banks) - - #if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR) - #define ENDPOINT_DETAILS_MAXEP 7 - - #define ENDPOINT_DETAILS_EP0 64, 1 - #define ENDPOINT_DETAILS_EP1 256, 2 - #define ENDPOINT_DETAILS_EP2 64, 2 - #define ENDPOINT_DETAILS_EP3 64, 2 - #define ENDPOINT_DETAILS_EP4 64, 2 - #define ENDPOINT_DETAILS_EP5 64, 2 - #define ENDPOINT_DETAILS_EP6 64, 2 - #else - #define ENDPOINT_DETAILS_MAXEP 5 + #define _ENDPOINT_GET_MAXSIZE(EPIndex) 1023 + #define _ENDPOINT_GET_BANKS(EPIndex) 2 - #define ENDPOINT_DETAILS_EP0 64, 1 - #define ENDPOINT_DETAILS_EP1 64, 1 - #define ENDPOINT_DETAILS_EP2 64, 1 - #define ENDPOINT_DETAILS_EP3 64, 2 - #define ENDPOINT_DETAILS_EP4 64, 2 - #endif + #define ENDPOINT_DETAILS_MAXEP 16 /* Inline Functions: */ static inline uint8_t Endpoint_BytesToEPSizeMask(const uint16_t Bytes) ATTR_WARN_UNUSED_RESULT ATTR_CONST @@ -141,12 +118,12 @@ /** Endpoint data direction mask for \ref Endpoint_ConfigureEndpoint(). This indicates that the endpoint * should be initialized in the OUT direction - i.e. data flows from host to device. */ - #define ENDPOINT_DIR_OUT (0 << EPDIR) + #define ENDPOINT_DIR_OUT 0 // TODO /** Endpoint data direction mask for \ref Endpoint_ConfigureEndpoint(). This indicates that the endpoint * should be initialized in the IN direction - i.e. data flows from device to host. */ - #define ENDPOINT_DIR_IN (1 << EPDIR) + #define ENDPOINT_DIR_IN 0 // TODO //@} /** \name Endpoint Bank Mode Masks */ @@ -156,14 +133,14 @@ * in slower transfers as only one USB device (the AVR or the host) can access the endpoint's * bank at the one time. */ - #define ENDPOINT_BANK_SINGLE (0 << EPBK0) + #define ENDPOINT_BANK_SINGLE 0 // TODO /** Mask for the bank mode selection for the \ref Endpoint_ConfigureEndpoint() macro. This indicates * that the endpoint should have two banks, which requires more USB FIFO memory but results * in faster transfers as one USB device (the AVR or the host) can access one bank while the other * accesses the second bank. */ - #define ENDPOINT_BANK_DOUBLE (1 << EPBK0) + #define ENDPOINT_BANK_DOUBLE 0 // TODO //@} #if (!defined(FIXED_CONTROL_ENDPOINT_SIZE) || defined(__DOXYGEN__)) diff --git a/LUFA/Drivers/USB/Core/XMEGA/USBController_XMEGA.c b/LUFA/Drivers/USB/Core/XMEGA/USBController_XMEGA.c index 52d44feada..2556ee858e 100644 --- a/LUFA/Drivers/USB/Core/XMEGA/USBController_XMEGA.c +++ b/LUFA/Drivers/USB/Core/XMEGA/USBController_XMEGA.c @@ -56,22 +56,88 @@ void USB_Init( #endif ) { - // TODO + #if !defined(USE_STATIC_OPTIONS) + USB_Options = Options; + #endif + + USB_IsInitialized = true; + + USB_ResetInterface(); } void USB_Disable(void) { - // TODO + USB_INT_DisableAllInterrupts(); + USB_INT_ClearAllInterrupts(); + + USB_Detach(); + USB_Controller_Disable(); + + USB_IsInitialized = false; } void USB_ResetInterface(void) { - // TODO + USB_INT_DisableAllInterrupts(); + USB_INT_ClearAllInterrupts(); + + USB_Controller_Reset(); + USB_Init_Device(); } #if defined(USB_CAN_BE_DEVICE) static void USB_Init_Device(void) { - // TODO + 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, + ENDPOINT_DIR_OUT, USB_Device_ControlEndpointSize, + ENDPOINT_BANK_SINGLE); + + USB_Attach(); } #endif diff --git a/LUFA/Drivers/USB/Core/XMEGA/USBController_XMEGA.h b/LUFA/Drivers/USB/Core/XMEGA/USBController_XMEGA.h index 8be4ed2e1a..f5adc1200f 100644 --- a/LUFA/Drivers/USB/Core/XMEGA/USBController_XMEGA.h +++ b/LUFA/Drivers/USB/Core/XMEGA/USBController_XMEGA.h @@ -77,62 +77,32 @@ #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) - - /** 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) - //@} - + /* Macros: */ /** \name Endpoint/Pipe Type Masks */ //@{ /** Mask for a CONTROL type endpoint or pipe. * * \note See \ref Group_EndpointManagement and \ref Group_PipeManagement for endpoint/pipe functions. */ - #define EP_TYPE_CONTROL 0x00 + #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 + #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 + #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 + #define EP_TYPE_INTERRUPT 0x03 //@} #if !defined(USB_STREAM_TIMEOUT_MS) || defined(__DOXYGEN__) @@ -147,18 +117,6 @@ #endif /* Inline Functions: */ - /** 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 0; // TODO - } - /** 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. @@ -166,7 +124,7 @@ static inline void USB_Detach(void) ATTR_ALWAYS_INLINE; static inline void USB_Detach(void) { - // TODO + USB.CTRLB &= ~USB_ATTACH_bm; } /** Attaches the device to the USB bus. This announces the device's presence to any attached @@ -180,7 +138,7 @@ static inline void USB_Attach(void) ATTR_ALWAYS_INLINE; static inline void USB_Attach(void) { - // TODO + USB.CTRLB |= USB_ATTACH_bm; } /* Function Prototypes: */ @@ -304,46 +262,23 @@ #endif /* Inline Functions: */ - static inline void USB_REG_On(void) ATTR_ALWAYS_INLINE; - static inline void USB_REG_On(void) - { - // TODO - } - - static inline void USB_REG_Off(void) ATTR_ALWAYS_INLINE; - static inline void USB_REG_Off(void) - { - // TODO - } - - static inline void USB_CLK_Freeze(void) ATTR_ALWAYS_INLINE; - static inline void USB_CLK_Freeze(void) - { - // TODO - } - - static inline void USB_CLK_Unfreeze(void) ATTR_ALWAYS_INLINE; - static inline void USB_CLK_Unfreeze(void) - { - // TODO - } - static inline void USB_Controller_Enable(void) ATTR_ALWAYS_INLINE; static inline void USB_Controller_Enable(void) { - // TODO + USB.CTRLA |= (USB_ENABLE_bm | USB_STFRNUM_bm | USB_MAXEP_gm); } static inline void USB_Controller_Disable(void) ATTR_ALWAYS_INLINE; static inline void USB_Controller_Disable(void) { - // TODO + USB.CTRLA &= ~USB_ENABLE_bm; } static inline void USB_Controller_Reset(void) ATTR_ALWAYS_INLINE; static inline void USB_Controller_Reset(void) { - // TODO + USB.CTRLA &= ~USB_ENABLE_bm; + USB.CTRLA |= USB_ENABLE_bm; } #endif