From 38039765346c7441208dbcb3fd3cf8f13b7ced58 Mon Sep 17 00:00:00 2001
From: Dean Camera <dean@fourwalledcubicle.com>
Date: Tue, 10 Mar 2009 05:56:17 +0000
Subject: [PATCH] Fixed incorrect/missing control status stage transfers on
 demos, bootloaders and applications (thanks to Nate Lawson).

---
 Bootloaders/CDC/BootloaderCDC.c                |  3 +++
 Bootloaders/DFU/BootloaderDFU.c                | 17 ++++++++++++-----
 Bootloaders/TeensyHID/TeensyHID.c              |  4 +---
 Demos/AudioInput/AudioInput.c                  |  3 ++-
 Demos/AudioOutput/AudioOutput.c                |  5 +++--
 Demos/CDC/CDC.c                                |  9 +++++----
 Demos/DualCDC/DualCDC.c                        |  9 +++++----
 Demos/Keyboard/Keyboard.c                      | 18 +++++++++++++-----
 Demos/KeyboardFullInt/KeyboardFullInt.c        | 18 +++++++++++++-----
 Demos/KeyboardMouse/KeyboardMouse.c            |  4 +---
 Demos/KeyboardViaInt/KeyboardViaInt.c          | 18 +++++++++++++-----
 Demos/MassStorage/MassStorage.c                | 17 +++++++++++++----
 Demos/Mouse/Mouse.c                            | 14 ++++++++++++--
 Demos/MouseFullInt/MouseFullInt.c              | 14 ++++++++++++--
 Demos/MouseViaInt/MouseViaInt.c                | 14 ++++++++++++--
 Demos/USBtoSerial/USBtoSerial.c                |  9 +++++----
 LUFA/ChangeLog.txt                             |  6 ++++--
 LUFA/Drivers/USB/LowLevel/Endpoint.h           | 10 +++++-----
 LUFA/Drivers/USB/LowLevel/LowLevel.h           |  2 +-
 LUFA/Drivers/USB/LowLevel/Pipe.h               |  4 ++--
 LUFA/MigrationInformation.txt                  |  3 +++
 Projects/AVRISP_Programmer/AVRISP_Programmer.c |  9 +++++----
 Projects/Magstripe/Magstripe.c                 | 14 ++++++++++++--
 23 files changed, 157 insertions(+), 67 deletions(-)

diff --git a/Bootloaders/CDC/BootloaderCDC.c b/Bootloaders/CDC/BootloaderCDC.c
index 60fe4a4bc..0add977ce 100644
--- a/Bootloaders/CDC/BootloaderCDC.c
+++ b/Bootloaders/CDC/BootloaderCDC.c
@@ -167,6 +167,7 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 				
 				Endpoint_ClearSetupIN();
 				
+				/* Acknowledge status stage */
 				while (!(Endpoint_IsSetupOUTReceived()));
 				Endpoint_ClearSetupOUT();
 			}
@@ -184,6 +185,7 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 
 				Endpoint_ClearSetupOUT();
 
+				/* Acknowledge status stage */
 				while (!(Endpoint_IsSetupINReady()));
 				Endpoint_ClearSetupIN();
 			}
@@ -194,6 +196,7 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 			{
 				Endpoint_ClearSetupReceived();
 				
+				/* Acknowledge status stage */
 				while (!(Endpoint_IsSetupINReady()));
 				Endpoint_ClearSetupIN();
 			}
diff --git a/Bootloaders/DFU/BootloaderDFU.c b/Bootloaders/DFU/BootloaderDFU.c
index 8cc5fd409..9fff20c12 100644
--- a/Bootloaders/DFU/BootloaderDFU.c
+++ b/Bootloaders/DFU/BootloaderDFU.c
@@ -57,7 +57,7 @@ bool RunBootloader = true;
 
 /** Flag to indicate if the bootloader is waiting to exit. When the host requests the bootloader to exit and
  *  jump to the application address it specifies, it sends two sequential commands which must be properly
- *  acknowedged. Upon reception of the first the RunBootloader flag is cleared and the WaitForExit flag is set,
+ *  acknowledged. Upon reception of the first the RunBootloader flag is cleared and the WaitForExit flag is set,
  *  causing the bootloader to wait for the final exit command before shutting down.
  */
 bool WaitForExit = false;
@@ -305,7 +305,8 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 
 			Endpoint_ClearSetupOUT();
 
-			/* Send ZLP to the host to acknowedge the request */
+			/* Acknowledge status stage */
+			while (!(Endpoint_IsSetupINReady()));
 			Endpoint_ClearSetupIN();
 				
 			break;
@@ -392,7 +393,7 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 
 			Endpoint_ClearSetupIN();
 
-			/* Send ZLP to the host to acknowedge the request */
+			/* Acknowledge status stage */
 			while (!(Endpoint_IsSetupOUTReceived()));
 			Endpoint_ClearSetupOUT();
 
@@ -415,6 +416,7 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 
 			Endpoint_ClearSetupIN();
 			
+			/* Acknowledge status stage */
 			while (!(Endpoint_IsSetupOUTReceived()));
 			Endpoint_ClearSetupOUT();
 	
@@ -424,9 +426,11 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 			
 			/* Reset the status value variable to the default OK status */
 			DFU_Status = OK;
-			
-			Endpoint_ClearSetupIN();
 
+			/* Acknowledge status stage */
+			while (!(Endpoint_IsSetupINReady()));
+			Endpoint_ClearSetupIN();
+			
 			break;
 		case DFU_GETSTATE:
 			Endpoint_ClearSetupReceived();
@@ -436,6 +440,7 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 		
 			Endpoint_ClearSetupIN();
 			
+			/* Acknowledge status stage */
 			while (!(Endpoint_IsSetupOUTReceived()));
 			Endpoint_ClearSetupOUT();
 
@@ -446,6 +451,8 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 			/* Reset the current state variable to the default idle state */
 			DFU_State = dfuIDLE;
 			
+			/* Acknowledge status stage */
+			while (!(Endpoint_IsSetupINReady()));
 			Endpoint_ClearSetupIN();
 
 			break;
diff --git a/Bootloaders/TeensyHID/TeensyHID.c b/Bootloaders/TeensyHID/TeensyHID.c
index fe20702cd..93f062195 100644
--- a/Bootloaders/TeensyHID/TeensyHID.c
+++ b/Bootloaders/TeensyHID/TeensyHID.c
@@ -144,10 +144,8 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 
 				Endpoint_ClearSetupOUT();
 
-				/* Wait until the host is ready to receive the request confirmation */
+				/* Acknowledge status stage */
 				while (!(Endpoint_IsSetupINReady()));
-				
-				/* Handshake the request by sending an empty IN packet */
 				Endpoint_ClearSetupIN();
 			}
 			
diff --git a/Demos/AudioInput/AudioInput.c b/Demos/AudioInput/AudioInput.c
index 0db41c3c1..6ead7a015 100644
--- a/Demos/AudioInput/AudioInput.c
+++ b/Demos/AudioInput/AudioInput.c
@@ -163,7 +163,8 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 					Scheduler_SetTaskMode(USB_Audio_Task, TASK_STOP);				
 				}
 				
-				/* Handshake the request */
+				/* Acknowledge status stage */
+				while (!(Endpoint_IsSetupINReady()));
 				Endpoint_ClearSetupIN();
 			}
 
diff --git a/Demos/AudioOutput/AudioOutput.c b/Demos/AudioOutput/AudioOutput.c
index 3d2e3249e..87afd3606 100644
--- a/Demos/AudioOutput/AudioOutput.c
+++ b/Demos/AudioOutput/AudioOutput.c
@@ -193,7 +193,8 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 					Scheduler_SetTaskMode(USB_Audio_Task, TASK_STOP);				
 				}
 				
-				/* Handshake the request */
+				/* Acknowledge status stage */
+				while (!(Endpoint_IsSetupINReady()));
 				Endpoint_ClearSetupIN();
 			}
 
@@ -249,7 +250,7 @@ TASK(USB_Audio_Task)
 		/* Check to see if the bank is now empty */
 		if (!(Endpoint_ReadWriteAllowed()))
 		{
-			/* Acknowedge the packet, clear the bank ready for the next packet */
+			/* Acknowledge the packet, clear the bank ready for the next packet */
 			Endpoint_ClearCurrentBank();
 		}
 
diff --git a/Demos/CDC/CDC.c b/Demos/CDC/CDC.c
index eeae625cf..6e933d581 100644
--- a/Demos/CDC/CDC.c
+++ b/Demos/CDC/CDC.c
@@ -171,7 +171,7 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 		case REQ_GetLineEncoding:
 			if (bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
 			{	
-				/* Acknowedge the SETUP packet, ready for data transfer */
+				/* Acknowledge the SETUP packet, ready for data transfer */
 				Endpoint_ClearSetupReceived();
 
 				/* Write the line coding data to the control endpoint */
@@ -185,7 +185,7 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 		case REQ_SetLineEncoding:
 			if (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
 			{
-				/* Acknowedge the SETUP packet, ready for data transfer */
+				/* Acknowledge the SETUP packet, ready for data transfer */
 				Endpoint_ClearSetupReceived();
 
 				/* Read the line coding data in from the host into the global struct */
@@ -210,10 +210,11 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 				// Do something with the given line states in wIndex
 #endif
 				
-				/* Acknowedge the SETUP packet, ready for data transfer */
+				/* Acknowledge the SETUP packet, ready for data transfer */
 				Endpoint_ClearSetupReceived();
 				
-				/* Send an empty packet to acknowedge the command */
+				/* Acknowledge status stage */
+				while (!(Endpoint_IsSetupINReady()));
 				Endpoint_ClearSetupIN();
 			}
 	
diff --git a/Demos/DualCDC/DualCDC.c b/Demos/DualCDC/DualCDC.c
index 8e6e38907..3c598da42 100644
--- a/Demos/DualCDC/DualCDC.c
+++ b/Demos/DualCDC/DualCDC.c
@@ -209,7 +209,7 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 		case REQ_GetLineEncoding:
 			if (bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
 			{	
-				/* Acknowedge the SETUP packet, ready for data transfer */
+				/* Acknowledge the SETUP packet, ready for data transfer */
 				Endpoint_ClearSetupReceived();
 
 				/* Write the line coding data to the control endpoint */
@@ -223,7 +223,7 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 		case REQ_SetLineEncoding:
 			if (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
 			{
-				/* Acknowedge the SETUP packet, ready for data transfer */
+				/* Acknowledge the SETUP packet, ready for data transfer */
 				Endpoint_ClearSetupReceived();
 
 				/* Read the line coding data in from the host into the global struct */
@@ -237,10 +237,11 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 		case REQ_SetControlLineState:
 			if (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
 			{
-				/* Acknowedge the SETUP packet, ready for data transfer */
+				/* Acknowledge the SETUP packet, ready for data transfer */
 				Endpoint_ClearSetupReceived();
 				
-				/* Send an empty packet to acknowedge the command (currently unused) */
+				/* Acknowledge status stage */
+				while (!(Endpoint_IsSetupINReady()));
 				Endpoint_ClearSetupIN();
 			}
 	
diff --git a/Demos/Keyboard/Keyboard.c b/Demos/Keyboard/Keyboard.c
index 22d406dbe..931f08098 100644
--- a/Demos/Keyboard/Keyboard.c
+++ b/Demos/Keyboard/Keyboard.c
@@ -210,10 +210,8 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 				/* Clear the endpoint data */
 				Endpoint_ClearSetupOUT();
 
-				/* Wait until the host is ready to receive the request confirmation */
+				/* Acknowledge status stage */
 				while (!(Endpoint_IsSetupINReady()));
-				
-				/* Handshake the request by sending an empty IN packet */
 				Endpoint_ClearSetupIN();
 			}
 			
@@ -228,6 +226,10 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 				
 				/* Send the flag to the host */
 				Endpoint_ClearSetupIN();
+				
+				/* Acknowledge status stage */
+				while (!(Endpoint_IsSetupOUTReceived()));
+				Endpoint_ClearSetupOUT();
 			}
 			
 			break;
@@ -242,7 +244,8 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 				/* Set or clear the flag depending on what the host indicates that the current Protocol should be */
 				UsingReportProtocol = (wValue != 0x0000);
 				
-				/* Send an empty packet to acknowedge the command */
+				/* Acknowledge status stage */
+				while (!(Endpoint_IsSetupINReady()));
 				Endpoint_ClearSetupIN();
 			}
 			
@@ -258,7 +261,8 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 				/* Get idle period in MSB */
 				IdleCount = (wValue >> 8);
 				
-				/* Send an empty packet to acknowedge the command */
+				/* Acknowledge status stage */
+				while (!(Endpoint_IsSetupINReady()));
 				Endpoint_ClearSetupIN();
 			}
 			
@@ -273,6 +277,10 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 				
 				/* Send the flag to the host */
 				Endpoint_ClearSetupIN();
+
+				/* Acknowledge status stage */
+				while (!(Endpoint_IsSetupOUTReceived()));
+				Endpoint_ClearSetupOUT();
 			}
 
 			break;
diff --git a/Demos/KeyboardFullInt/KeyboardFullInt.c b/Demos/KeyboardFullInt/KeyboardFullInt.c
index ed081376d..6a15a9233 100644
--- a/Demos/KeyboardFullInt/KeyboardFullInt.c
+++ b/Demos/KeyboardFullInt/KeyboardFullInt.c
@@ -212,10 +212,8 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 				/* Clear the endpoint data */
 				Endpoint_ClearSetupOUT();
 
-				/* Wait until the host is ready to receive the request confirmation */
+				/* Acknowledge status stage */
 				while (!(Endpoint_IsSetupINReady()));
-				
-				/* Handshake the request by sending an empty IN packet */
 				Endpoint_ClearSetupIN();
 			}
 			
@@ -230,6 +228,10 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 				
 				/* Send the flag to the host */
 				Endpoint_ClearSetupIN();
+
+				/* Acknowledge status stage */
+				while (!(Endpoint_IsSetupOUTReceived()));
+				Endpoint_ClearSetupOUT();
 			}
 			
 			break;
@@ -244,7 +246,8 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 				/* Set or clear the flag depending on what the host indicates that the current Protocol should be */
 				UsingReportProtocol = (wValue != 0x0000);
 
-				/* Send an empty packet to acknowedge the command */
+				/* Acknowledge status stage */
+				while (!(Endpoint_IsSetupINReady()));
 				Endpoint_ClearSetupIN();
 			}
 			
@@ -260,7 +263,8 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 				/* Get idle period in MSB */
 				IdleCount = (wValue >> 8);
 				
-				/* Send an empty packet to acknowedge the command */
+				/* Acknowledge status stage */
+				while (!(Endpoint_IsSetupINReady()));
 				Endpoint_ClearSetupIN();
 			}
 			
@@ -275,6 +279,10 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 				
 				/* Send the flag to the host */
 				Endpoint_ClearSetupIN();
+
+				/* Acknowledge status stage */
+				while (!(Endpoint_IsSetupOUTReceived()));
+				Endpoint_ClearSetupOUT();
 			}
 
 			break;
diff --git a/Demos/KeyboardMouse/KeyboardMouse.c b/Demos/KeyboardMouse/KeyboardMouse.c
index 8108a3032..3ee101b8d 100644
--- a/Demos/KeyboardMouse/KeyboardMouse.c
+++ b/Demos/KeyboardMouse/KeyboardMouse.c
@@ -213,10 +213,8 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 				/* Clear the endpoint data */
 				Endpoint_ClearSetupOUT();
 
-				/* Wait until the host is ready to receive the request confirmation */
+				/* Acknowledge status stage */
 				while (!(Endpoint_IsSetupINReady()));
-				
-				/* Handshake the request by sending an empty IN packet */
 				Endpoint_ClearSetupIN();
 			}
 			
diff --git a/Demos/KeyboardViaInt/KeyboardViaInt.c b/Demos/KeyboardViaInt/KeyboardViaInt.c
index b66506df5..1e724e6fa 100644
--- a/Demos/KeyboardViaInt/KeyboardViaInt.c
+++ b/Demos/KeyboardViaInt/KeyboardViaInt.c
@@ -211,10 +211,8 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 				/* Clear the endpoint data */
 				Endpoint_ClearSetupOUT();
 
-				/* Wait until the host is ready to receive the request confirmation */
+				/* Acknowledge status stage */
 				while (!(Endpoint_IsSetupINReady()));
-				
-				/* Handshake the request by sending an empty IN packet */
 				Endpoint_ClearSetupIN();
 			}
 			
@@ -229,6 +227,10 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 				
 				/* Send the flag to the host */
 				Endpoint_ClearSetupIN();
+
+				/* Acknowledge status stage */
+				while (!(Endpoint_IsSetupOUTReceived()));
+				Endpoint_ClearSetupOUT();
 			}
 			
 			break;
@@ -243,7 +245,8 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 				/* Set or clear the flag depending on what the host indicates that the current Protocol should be */
 				UsingReportProtocol = (wValue != 0x0000);
 				
-				/* Send an empty packet to acknowedge the command */
+				/* Acknowledge status stage */
+				while (!(Endpoint_IsSetupINReady()));
 				Endpoint_ClearSetupIN();
 			}
 			
@@ -259,7 +262,8 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 				/* Get idle period in MSB */
 				IdleCount = (wValue >> 8);
 				
-				/* Send an empty packet to acknowedge the command */
+				/* Acknowledge status stage */
+				while (!(Endpoint_IsSetupINReady()));
 				Endpoint_ClearSetupIN();
 			}
 			
@@ -274,6 +278,10 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 				
 				/* Send the flag to the host */
 				Endpoint_ClearSetupIN();
+
+				/* Acknowledge status stage */
+				while (!(Endpoint_IsSetupOUTReceived()));
+				Endpoint_ClearSetupOUT();
 			}
 
 			break;
diff --git a/Demos/MassStorage/MassStorage.c b/Demos/MassStorage/MassStorage.c
index 34fcee488..92e33073c 100644
--- a/Demos/MassStorage/MassStorage.c
+++ b/Demos/MassStorage/MassStorage.c
@@ -159,10 +159,13 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 		case REQ_MassStorageReset:
 			if (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
 			{
-				/* Indicate that the current transfer should be aborted */
-				IsMassStoreReset = true;
-			
 				Endpoint_ClearSetupReceived();
+
+				/* Indicate that the current transfer should be aborted */
+				IsMassStoreReset = true;			
+
+				/* Acknowledge status stage */
+				while (!(Endpoint_IsSetupINReady()));
 				Endpoint_ClearSetupIN();
 			}
 
@@ -171,9 +174,15 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 			if (bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
 			{
 				/* Indicate to the host the number of supported LUNs (virtual disks) on the device */
-				Endpoint_ClearSetupReceived();			
+				Endpoint_ClearSetupReceived();
+
 				Endpoint_Write_Byte(TOTAL_LUNS - 1);
+				
 				Endpoint_ClearSetupIN();
+				
+				/* Acknowledge status stage */
+				while (!(Endpoint_IsSetupOUTReceived()));
+				Endpoint_ClearSetupOUT();
 			}
 			
 			break;
diff --git a/Demos/Mouse/Mouse.c b/Demos/Mouse/Mouse.c
index 3e59706c9..da8a4a809 100644
--- a/Demos/Mouse/Mouse.c
+++ b/Demos/Mouse/Mouse.c
@@ -201,6 +201,10 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 				
 				/* Send the flag to the host */
 				Endpoint_ClearSetupIN();
+
+				/* Acknowledge status stage */
+				while (!(Endpoint_IsSetupOUTReceived()));
+				Endpoint_ClearSetupOUT();
 			}
 			
 			break;
@@ -215,7 +219,8 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 				/* Set or clear the flag depending on what the host indicates that the current Protocol should be */
 				UsingReportProtocol = (wValue != 0x0000);
 				
-				/* Send an empty packet to acknowedge the command */
+				/* Acknowledge status stage */
+				while (!(Endpoint_IsSetupINReady()));
 				Endpoint_ClearSetupIN();
 			}
 			
@@ -231,7 +236,8 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 				/* Get idle period in MSB */
 				IdleCount = (wValue >> 8);
 				
-				/* Send an empty packet to acknowedge the command */
+				/* Acknowledge status stage */
+				while (!(Endpoint_IsSetupINReady()));
 				Endpoint_ClearSetupIN();
 			}
 			
@@ -246,6 +252,10 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 				
 				/* Send the flag to the host */
 				Endpoint_ClearSetupIN();
+
+				/* Acknowledge status stage */
+				while (!(Endpoint_IsSetupOUTReceived()));
+				Endpoint_ClearSetupOUT();
 			}
 
 			break;
diff --git a/Demos/MouseFullInt/MouseFullInt.c b/Demos/MouseFullInt/MouseFullInt.c
index 98782b6cf..7e69d81e7 100644
--- a/Demos/MouseFullInt/MouseFullInt.c
+++ b/Demos/MouseFullInt/MouseFullInt.c
@@ -200,6 +200,10 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 				
 				/* Send the flag to the host */
 				Endpoint_ClearSetupIN();
+
+				/* Acknowledge status stage */
+				while (!(Endpoint_IsSetupOUTReceived()));
+				Endpoint_ClearSetupOUT();
 			}
 			
 			break;
@@ -214,7 +218,8 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 				/* Set or clear the flag depending on what the host indicates that the current Protocol should be */
 				UsingReportProtocol = (wValue != 0x0000);
 				
-				/* Send an empty packet to acknowedge the command */
+				/* Acknowledge status stage */
+				while (!(Endpoint_IsSetupINReady()));
 				Endpoint_ClearSetupIN();
 			}
 			
@@ -230,7 +235,8 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 				/* Get idle period in MSB */
 				IdleCount = (wValue >> 8);
 				
-				/* Send an empty packet to acknowedge the command */
+				/* Acknowledge status stage */
+				while (!(Endpoint_IsSetupINReady()));
 				Endpoint_ClearSetupIN();
 			}
 			
@@ -245,6 +251,10 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 				
 				/* Send the flag to the host */
 				Endpoint_ClearSetupIN();
+
+				/* Acknowledge status stage */
+				while (!(Endpoint_IsSetupOUTReceived()));
+				Endpoint_ClearSetupOUT();
 			}
 
 			break;
diff --git a/Demos/MouseViaInt/MouseViaInt.c b/Demos/MouseViaInt/MouseViaInt.c
index 445fb4994..465459a36 100644
--- a/Demos/MouseViaInt/MouseViaInt.c
+++ b/Demos/MouseViaInt/MouseViaInt.c
@@ -198,6 +198,10 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 				
 				/* Send the flag to the host */
 				Endpoint_ClearSetupIN();
+
+				/* Acknowledge status stage */
+				while (!(Endpoint_IsSetupOUTReceived()));
+				Endpoint_ClearSetupOUT();
 			}
 			
 			break;
@@ -212,7 +216,8 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 				/* Set or clear the flag depending on what the host indicates that the current Protocol should be */
 				UsingReportProtocol = (wValue != 0x0000);
 				
-				/* Send an empty packet to acknowedge the command */
+				/* Acknowledge status stage */
+				while (!(Endpoint_IsSetupINReady()));
 				Endpoint_ClearSetupIN();
 			}
 			
@@ -228,7 +233,8 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 				/* Get idle period in MSB */
 				IdleCount = (wValue >> 8);
 				
-				/* Send an empty packet to acknowedge the command */
+				/* Acknowledge status stage */
+				while (!(Endpoint_IsSetupINReady()));
 				Endpoint_ClearSetupIN();
 			}
 			
@@ -243,6 +249,10 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 				
 				/* Send the flag to the host */
 				Endpoint_ClearSetupIN();
+
+				/* Acknowledge status stage */
+				while (!(Endpoint_IsSetupOUTReceived()));
+				Endpoint_ClearSetupOUT();
 			}
 
 			break;
diff --git a/Demos/USBtoSerial/USBtoSerial.c b/Demos/USBtoSerial/USBtoSerial.c
index 0495826b9..c7c9e4b04 100644
--- a/Demos/USBtoSerial/USBtoSerial.c
+++ b/Demos/USBtoSerial/USBtoSerial.c
@@ -164,7 +164,7 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 		case REQ_GetLineEncoding:
 			if (bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
 			{	
-				/* Acknowedge the SETUP packet, ready for data transfer */
+				/* Acknowledge the SETUP packet, ready for data transfer */
 				Endpoint_ClearSetupReceived();
 
 				/* Write the line coding data to the control endpoint */
@@ -178,7 +178,7 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 		case REQ_SetLineEncoding:
 			if (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
 			{
-				/* Acknowedge the SETUP packet, ready for data transfer */
+				/* Acknowledge the SETUP packet, ready for data transfer */
 				Endpoint_ClearSetupReceived();
 
 				/* Read the line coding data in from the host into the global struct */
@@ -206,10 +206,11 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 				// Do something with the given line states in wIndex
 #endif
 				
-				/* Acknowedge the SETUP packet, ready for data transfer */
+				/* Acknowledge the SETUP packet, ready for data transfer */
 				Endpoint_ClearSetupReceived();
 				
-				/* Send an empty packet to acknowedge the command */
+				/* Acknowledge status stage */
+				while (!(Endpoint_IsSetupINReady()));
 				Endpoint_ClearSetupIN();
 			}
 	
diff --git a/LUFA/ChangeLog.txt b/LUFA/ChangeLog.txt
index 1a2b9f8a1..d283d7f95 100644
--- a/LUFA/ChangeLog.txt
+++ b/LUFA/ChangeLog.txt
@@ -29,13 +29,15 @@
   *  - Function attribute ATTR_ALWAYSINLINE renamed to ATTR_ALWAYS_INLINE to match other function attribute macro naming conventions
   *  - Added ATTR_ALWAYS_INLINE attribute to several key inlined library components, to ensure they are inlined in all circumstances
   *  - Removed SetSystemClockPrescaler() macro, the clock_prescale_set() avr-libc macro has been corrected in recent avr-libc versions
+  *  - Fixed incorrect/missing control status stage transfers on demos, bootloaders and applications (thanks to Nate Lawson)
   *
   *  \section Sec_ChangeLog090209 Version 090209
   *
   *  - PWM timer mode in AudioOut demo changed to Fast PWM for speed
   *  - Updated Magstripe project to work with the latest hardware revision
   *  - Fixed library not responding to the BCERRI flag correctly in host mode, leading to device lockups
-  *  - Fixed library handling Get Descriptor requests when not addressed as standard requests to the device or interface
+  *  - Fixed library handling Get Descriptor requests when not addressed as standard requests to the device or interface (thanks to
+  *    Nate Lawson)
   *  - Fixed serious data corruption issue in MassStorage demo dataflash write routine
   *  - Added new NO_CLEARSET_FEATURE_REQUEST compile time token
   *  - USB task now restores previous global interrupt state after execution, rather than forcing global interrupts to be enabled
@@ -326,7 +328,7 @@
   *  - Added Endpoint_Read_Stream, Endpoint_Write_Stream, Pipe_Read_Stream and Pipe_Write_Stream functions
   *    (including Big and Little Endian variants)
   *  - Made Dataflash functions inline for speed, removed now empty Dataflash.c driver file
-  *  - Added new SetSystemClockPrescaler() macro - thanks to Joerg Wunsch
+  *  - Added new SetSystemClockPrescaler() macro (thanks to Joerg Wunsch)
   *  - Fixed Endpoint_ClearStall() to function correctly on full USB controller AVRs (AT90USBXXX6/7)
   *  - Endpoint_Setup_In_Clear() and Endpoint_Setup_Out_Clear() no longer set FIFOCON, in line with the
   *    directives in the datasheet
diff --git a/LUFA/Drivers/USB/LowLevel/Endpoint.h b/LUFA/Drivers/USB/LowLevel/Endpoint.h
index d1ad1315a..16266868c 100644
--- a/LUFA/Drivers/USB/LowLevel/Endpoint.h
+++ b/LUFA/Drivers/USB/LowLevel/Endpoint.h
@@ -256,7 +256,7 @@
 			/** Sends an IN packet to the host on the currently selected CONTROL type endpoint. */
 			#define Endpoint_ClearSetupIN()               MACROS{ UEINTX &= ~(1 << TXINI); }MACROE
 
-			/** Acknowedges an OUT packet to the host on the currently selected CONTROL type endpoint, freeing
+			/** Acknowledges an OUT packet to the host on the currently selected CONTROL type endpoint, freeing
 			 *  up the endpoint for the next packet.
 			 */
 			#define Endpoint_ClearSetupOUT()              MACROS{ UEINTX &= ~(1 << RXOUTI); }MACROE
@@ -667,7 +667,7 @@
 			                                ) 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 acknowedgement is not automatically cleared
+			 *  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 setup OUT to
 			 *  finalize the transfer via the Endpoint_ClearSetupOUT() macro.
 			 *
@@ -684,7 +684,7 @@
 			uint8_t Endpoint_Write_Control_Stream_LE(const void* 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 acknowedgement is not automatically cleared
+			 *  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 setup OUT to
 			 *  finalize the transfer via the Endpoint_ClearSetupOUT() macro.
 			 *
@@ -701,7 +701,7 @@
 			uint8_t Endpoint_Write_Control_Stream_BE(const void* 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 acknowedgement is not
+			 *  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
 			 *  setup IN to finalize the transfer via the Endpoint_ClearSetupIN() macro.
 			 *
@@ -718,7 +718,7 @@
 			uint8_t Endpoint_Read_Control_Stream_LE(void* 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 acknowedgement is not
+			 *  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
 			 *  setup IN to finalize the transfer via the Endpoint_ClearSetupIN() macro.
 			 *
diff --git a/LUFA/Drivers/USB/LowLevel/LowLevel.h b/LUFA/Drivers/USB/LowLevel/LowLevel.h
index 9721baca0..98deaaca1 100644
--- a/LUFA/Drivers/USB/LowLevel/LowLevel.h
+++ b/LUFA/Drivers/USB/LowLevel/LowLevel.h
@@ -205,7 +205,7 @@
 			#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 acknowedged within this time period, the stream function will fail.
+				 *  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 
 				 *  USB_STREAM_TIMEOUT_MS token, and passed to the compiler using the -D switch.
diff --git a/LUFA/Drivers/USB/LowLevel/Pipe.h b/LUFA/Drivers/USB/LowLevel/Pipe.h
index f7d10bc1d..5d4793eb2 100644
--- a/LUFA/Drivers/USB/LowLevel/Pipe.h
+++ b/LUFA/Drivers/USB/LowLevel/Pipe.h
@@ -347,7 +347,7 @@
 			 */
 			#define Pipe_IsSetupOUTReady()         ((UPINTX & (1 << TXOUTI)) ? true : false)
 
-			/** Acknowedges the reception of a setup IN request from the attached device on the currently selected
+			/** Acknowledges the reception of a setup IN request from the attached device on the currently selected
 			 *  CONTROL type endpoint, allowing for the transmission of a setup OUT packet, or the reception of
 			 *  another setup IN packet.
 			 */
@@ -356,7 +356,7 @@
 			/** Sends the currently selected CONTROL type pipe's contents to the device as a setup OUT packet. */
 			#define Pipe_ClearSetupOUT()           MACROS{ UPINTX &= ~(1 << TXOUTI); UPINTX &= ~(1 << FIFOCON); }MACROE
 			
-			/** Returns true if the device sent a NAK (Negative Acknowedge) in response to the last sent packet on
+			/** Returns true if the device sent a NAK (Negative Acknowledge) in response to the last sent packet on
 			 *  the currently selected pipe. This ocurrs 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 cleard using Pipe_ClearNAKReceived() before the previous (or any other) packet
diff --git a/LUFA/MigrationInformation.txt b/LUFA/MigrationInformation.txt
index 364f09c3e..75b5d1912 100644
--- a/LUFA/MigrationInformation.txt
+++ b/LUFA/MigrationInformation.txt
@@ -22,6 +22,9 @@
  *
  *  <b>Library Demos</b>
  *    - The USBtoSerial demo now discards all data when not connected to a host, rather than buffering it for later transmission.
+ *    - Most demos, bootloaders and applications have had their control request handling code corrected, to properly send the status
+ *      stage in all handled requests. If you are using code based off one of the library demos, bootloaders or applications, you should
+ *      update to the latest revisions.
  *
  *  <b>Non-USB Library Components</b>
  *    - The ATTR_ALWAYSINLINE function attribute macro has been renamed to ATTR_ALWAYS_INLINE.
diff --git a/Projects/AVRISP_Programmer/AVRISP_Programmer.c b/Projects/AVRISP_Programmer/AVRISP_Programmer.c
index 4bc4f9cc3..58593670e 100644
--- a/Projects/AVRISP_Programmer/AVRISP_Programmer.c
+++ b/Projects/AVRISP_Programmer/AVRISP_Programmer.c
@@ -267,7 +267,7 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 		case REQ_GetLineEncoding:
 			if (bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
 			{	
-				/* Acknowedge the SETUP packet, ready for data transfer */
+				/* Acknowledge the SETUP packet, ready for data transfer */
 				Endpoint_ClearSetupReceived();
 
 				/* Write the line coding data to the control endpoint */
@@ -281,7 +281,7 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 		case REQ_SetLineEncoding:
 			if (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
 			{
-				/* Acknowedge the SETUP packet, ready for data transfer */
+				/* Acknowledge the SETUP packet, ready for data transfer */
 				Endpoint_ClearSetupReceived();
 
 				/* Read the line coding data in from the host into the global struct */
@@ -298,10 +298,11 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 		case REQ_SetControlLineState:
 			if (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
 			{
-				/* Acknowedge the SETUP packet, ready for data transfer */
+				/* Acknowledge the SETUP packet, ready for data transfer */
 				Endpoint_ClearSetupReceived();
 				
-				/* Send an empty packet to acknowedge the command */
+				/* Acknowledge status stage */
+				while (!(Endpoint_IsSetupINReady()));
 				Endpoint_ClearSetupIN();
 			}
 	
diff --git a/Projects/Magstripe/Magstripe.c b/Projects/Magstripe/Magstripe.c
index 2826c140e..0e10053da 100644
--- a/Projects/Magstripe/Magstripe.c
+++ b/Projects/Magstripe/Magstripe.c
@@ -204,6 +204,10 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 				
 				/* Send the flag to the host */
 				Endpoint_ClearSetupIN();
+
+				/* Acknowledge status stage */
+				while (!(Endpoint_IsSetupOUTReceived()));
+				Endpoint_ClearSetupOUT();
 			}
 			
 			break;
@@ -218,7 +222,8 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 				/* Set or clear the flag depending on what the host indicates that the current Protocol should be */
 				UsingReportProtocol = (wValue != 0x0000);
 				
-				/* Send an empty packet to acknowedge the command */
+				/* Acknowledge status stage */
+				while (!(Endpoint_IsSetupINReady()));
 				Endpoint_ClearSetupIN();
 			}
 			
@@ -234,7 +239,8 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 				/* Get idle period in MSB */
 				IdleCount = (wValue >> 8);
 				
-				/* Send an empty packet to acknowedge the command */
+				/* Acknowledge status stage */
+				while (!(Endpoint_IsSetupINReady()));
 				Endpoint_ClearSetupIN();
 			}
 			
@@ -249,6 +255,10 @@ EVENT_HANDLER(USB_UnhandledControlPacket)
 				
 				/* Send the flag to the host */
 				Endpoint_ClearSetupIN();
+
+				/* Acknowledge status stage */
+				while (!(Endpoint_IsSetupOUTReceived()));
+				Endpoint_ClearSetupOUT();
 			}
 
 			break;
-- 
GitLab