From 0304916356ea83bb17783df157c79cbfdef0d45b Mon Sep 17 00:00:00 2001
From: Dean Camera <dean@fourwalledcubicle.com>
Date: Mon, 31 Oct 2011 02:26:21 +0000
Subject: [PATCH] Fix XMEGA core USB driver so that device mode enumerates
 correctly on the host PC.

---
 LUFA/DoxygenPages/LUFAPoweredProjects.txt     |  1 +
 LUFA/Drivers/USB/Core/XMEGA/Device_XMEGA.h    |  1 +
 LUFA/Drivers/USB/Core/XMEGA/Endpoint_XMEGA.c  | 23 +++++++++++++++----
 LUFA/Drivers/USB/Core/XMEGA/Endpoint_XMEGA.h  | 21 +++++++++++++----
 .../USB/Core/XMEGA/USBController_XMEGA.c      |  2 +-
 LUFA/Platform/XMEGA/ClockManagement.h         |  4 ++--
 6 files changed, 40 insertions(+), 12 deletions(-)

diff --git a/LUFA/DoxygenPages/LUFAPoweredProjects.txt b/LUFA/DoxygenPages/LUFAPoweredProjects.txt
index df72cbc0e..4b85285b8 100644
--- a/LUFA/DoxygenPages/LUFAPoweredProjects.txt
+++ b/LUFA/DoxygenPages/LUFAPoweredProjects.txt
@@ -56,6 +56,7 @@
  *  - Gamecube controller to USB adapter: https://www.facebook.com/media/set/?set=a.10150202447076304.310536.688776303&l=df53851c50 
  *  - Garmin GPS USB to NMEA standard serial sentence translator: http://github.com/nall/garmin-transmogrifier/tree/master
  *  - Generic HID Device Creator: http://generichid.sourceforge.net/
+ *  - Generic HID Open Source Framework: http://www.waitingforfriday.com/index.php/USB_Generic_HID_Open_Source_Framework_for_Atmel_AVR_and_Windows
  *  - Ghetto Drum, a MIDI drum controller: http://noisybox.net/art/gdrum/
  *  - Hiduino, a USB-MIDI replacement firmware for the Arduino Uno: http://code.google.com/p/hiduino/
  *  - Ikea RGB LED USB modification: http://slashhome.se/p/projects/id/ikea_dioder_usb/#project
diff --git a/LUFA/Drivers/USB/Core/XMEGA/Device_XMEGA.h b/LUFA/Drivers/USB/Core/XMEGA/Device_XMEGA.h
index df6823a9c..1c128dc10 100644
--- a/LUFA/Drivers/USB/Core/XMEGA/Device_XMEGA.h
+++ b/LUFA/Drivers/USB/Core/XMEGA/Device_XMEGA.h
@@ -211,6 +211,7 @@
 
 					NVM.CMD    = NVM_CMD_READ_CALIB_ROW_gc;
 					SerialByte = pgm_read_byte(SigReadAddress);
+					NVM.CMD    = 0;
 
 					if (SerialCharNum & 0x01)
 					{
diff --git a/LUFA/Drivers/USB/Core/XMEGA/Endpoint_XMEGA.c b/LUFA/Drivers/USB/Core/XMEGA/Endpoint_XMEGA.c
index 3c9ba27ea..604427fca 100644
--- a/LUFA/Drivers/USB/Core/XMEGA/Endpoint_XMEGA.c
+++ b/LUFA/Drivers/USB/Core/XMEGA/Endpoint_XMEGA.c
@@ -53,7 +53,7 @@ bool Endpoint_ConfigureEndpoint_PRV(const uint8_t Number,
 	Endpoint_SelectEndpoint(Number | Direction);
 	
 	USB_Endpoint_SelectedHandle->CTRL      = 0;
-	USB_Endpoint_SelectedHandle->STATUS    = (Direction == ENDPOINT_DIR_IN) ? (USB_EP_BUSNACK0_bm | USB_EP_TRNCOMPL0_bm) : USB_EP_BUSNACK0_bm;
+	USB_Endpoint_SelectedHandle->STATUS    = (Direction == 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[0];
@@ -72,13 +72,26 @@ void Endpoint_ClearEndpoints(void)
 
 void Endpoint_ClearStatusStage(void)
 {
-	while (!(Endpoint_IsOUTReceived()))
+	if (USB_ControlRequest.bmRequestType & REQDIR_DEVICETOHOST)
 	{
-		if (USB_DeviceState == DEVICE_STATE_Unattached)
-		  return;
+		while (!(Endpoint_IsOUTReceived()))
+		{
+			if (USB_DeviceState == DEVICE_STATE_Unattached)
+			  return;
+		}
+
+		Endpoint_ClearOUT();
 	}
+	else
+	{
+		while (!(Endpoint_IsINReady()))
+		{
+			if (USB_DeviceState == DEVICE_STATE_Unattached)
+			  return;
+		}
 
-	Endpoint_ClearOUT();
+		Endpoint_ClearIN();
+	}
 }
 
 #if !defined(CONTROL_ONLY_DEVICE)
diff --git a/LUFA/Drivers/USB/Core/XMEGA/Endpoint_XMEGA.h b/LUFA/Drivers/USB/Core/XMEGA/Endpoint_XMEGA.h
index c26f7e5b4..2ba135619 100644
--- a/LUFA/Drivers/USB/Core/XMEGA/Endpoint_XMEGA.h
+++ b/LUFA/Drivers/USB/Core/XMEGA/Endpoint_XMEGA.h
@@ -433,7 +433,7 @@
 			{
 				Endpoint_SelectEndpoint(USB_Endpoint_SelectedEndpoint | ENDPOINT_DIR_IN);
 				
-				return ((USB_Endpoint_SelectedHandle->STATUS & USB_EP_TRNCOMPL0_bm) ? true : false);
+				return ((USB_Endpoint_SelectedHandle->STATUS & USB_EP_BUSNACK0_bm) ? true : false);
 			}
 
 			/** Determines if the selected OUT endpoint has received new packet from the host.
@@ -486,7 +486,13 @@
 			static inline void Endpoint_ClearSETUP(void) ATTR_ALWAYS_INLINE;
 			static inline void Endpoint_ClearSETUP(void)
 			{
-				USB_Endpoint_SelectedHandle->STATUS &= ~(USB_EP_SETUP_bm | USB_EP_BUSNACK0_bm);
+				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;
 			}
 
@@ -529,7 +535,14 @@
 			static inline void Endpoint_StallTransaction(void) ATTR_ALWAYS_INLINE;
 			static inline void Endpoint_StallTransaction(void)
 			{
-				USB_Endpoint_SelectedHandle->CTRL |=  USB_EP_STALL_bm;
+				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->STATUS |= USB_EP_STALL_bm;
+					Endpoint_SelectEndpoint(USB_Endpoint_SelectedEndpoint & ~ENDPOINT_DIR_IN);
+				}
 			}
 
 			/** Clears the STALL condition on the currently selected endpoint.
@@ -551,7 +564,7 @@
 			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);
+				return ((USB_Endpoint_SelectedHandle->CTRL & USB_EP_STALLF_bm) ? true : false);
 			}
 
 			/** Resets the data toggle of the currently selected endpoint. */
diff --git a/LUFA/Drivers/USB/Core/XMEGA/USBController_XMEGA.c b/LUFA/Drivers/USB/Core/XMEGA/USBController_XMEGA.c
index 58d1b768b..3b7793020 100644
--- a/LUFA/Drivers/USB/Core/XMEGA/USBController_XMEGA.c
+++ b/LUFA/Drivers/USB/Core/XMEGA/USBController_XMEGA.c
@@ -69,8 +69,8 @@ void USB_Init(
 
 	NVM.CMD  = NVM_CMD_READ_CALIB_ROW_gc;
 	USB.CAL0 = pgm_read_byte(offsetof(NVM_PROD_SIGNATURES_t, USBCAL0));
-	NVM.CMD  = NVM_CMD_READ_CALIB_ROW_gc;
 	USB.CAL1 = pgm_read_byte(offsetof(NVM_PROD_SIGNATURES_t, USBCAL1));
+	NVM.CMD  = 0;
 	
 	USB.EPPTR = (intptr_t)&USB_EndpointTable;
 	USB.CTRLA = (USB_STFRNUM_bm | USB_MAXEP_gm);
diff --git a/LUFA/Platform/XMEGA/ClockManagement.h b/LUFA/Platform/XMEGA/ClockManagement.h
index 357ed7b32..1305d0e4b 100644
--- a/LUFA/Platform/XMEGA/ClockManagement.h
+++ b/LUFA/Platform/XMEGA/ClockManagement.h
@@ -282,8 +282,8 @@
 						{
 							NVM.CMD        = NVM_CMD_READ_CALIB_ROW_gc;
 							DFLLRC32M.CALA = pgm_read_byte(offsetof(NVM_PROD_SIGNATURES_t, USBRCOSCA));
-							NVM.CMD        = NVM_CMD_READ_CALIB_ROW_gc;
 							DFLLRC32M.CALB = pgm_read_byte(offsetof(NVM_PROD_SIGNATURES_t, USBRCOSC));
+							NVM.CMD        = 0;
 						}
 
 						DFLLRC32M.CTRL  = DFLL_ENABLE_bm;
@@ -359,7 +359,7 @@
 				GlobalInterruptDisable();
 
 				CCP      = CCP_IOREG_gc;
-				CLK.CTRL = ClockSourceMask;
+				CLK_CTRL = ClockSourceMask;
 				
 				SetGlobalInterruptMask(CurrentGlobalInt);
 				
-- 
GitLab