From 4ba40977162ef46f328d49c4d48d7d8a0c6cddf0 Mon Sep 17 00:00:00 2001
From: Dean Camera <dean@fourwalledcubicle.com>
Date: Wed, 27 Mar 2013 18:55:30 +0000
Subject: [PATCH] Fixed race condition in the DFU class bootloader causing
 failed device reprogramming in some circumstances (thanks to Luis Mendes).

---
 Bootloaders/DFU/BootloaderDFU.c         | 16 ++++++++++++++--
 Bootloaders/Printer/BootloaderPrinter.c | 14 ++++++++++++++
 LUFA/DoxygenPages/ChangeLog.txt         |  1 +
 3 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/Bootloaders/DFU/BootloaderDFU.c b/Bootloaders/DFU/BootloaderDFU.c
index 0ac9af9f7..f19fa03ed 100644
--- a/Bootloaders/DFU/BootloaderDFU.c
+++ b/Bootloaders/DFU/BootloaderDFU.c
@@ -132,7 +132,7 @@ void Application_Jump_Check(void)
 	{
 		/* Turn off the watchdog */
 		MCUSR &= ~(1<<WDRF);
-		wdt_disable(); 
+		wdt_disable();
 
 		/* Clear the boot key and jump to the user application */
 		MagicBootKey = 0;
@@ -197,7 +197,7 @@ static void ResetHardware(void)
 	/* Shut down the USB and other board hardware drivers */
 	USB_Disable();
 	LEDs_Disable();
-	
+
 	/* Disable Bootloader active LED toggle timer */
 	TIMSK1 = 0;
 	TCCR1B = 0;
@@ -489,6 +489,12 @@ void EVENT_USB_Device_ControlRequest(void)
 		case DFU_REQ_GETSTATUS:
 			Endpoint_ClearSETUP();
 
+			while (!(Endpoint_IsINReady()))
+			{
+				if (USB_DeviceState == DEVICE_STATE_Unattached)
+				  return;
+			}
+
 			/* Write 8-bit status value */
 			Endpoint_Write_8(DFU_Status);
 
@@ -517,6 +523,12 @@ void EVENT_USB_Device_ControlRequest(void)
 		case DFU_REQ_GETSTATE:
 			Endpoint_ClearSETUP();
 
+			while (!(Endpoint_IsINReady()))
+			{
+				if (USB_DeviceState == DEVICE_STATE_Unattached)
+				  return;
+			}
+
 			/* Write the current device state to the endpoint */
 			Endpoint_Write_8(DFU_State);
 
diff --git a/Bootloaders/Printer/BootloaderPrinter.c b/Bootloaders/Printer/BootloaderPrinter.c
index 9a6a8c27f..c459e031a 100644
--- a/Bootloaders/Printer/BootloaderPrinter.c
+++ b/Bootloaders/Printer/BootloaderPrinter.c
@@ -380,6 +380,13 @@ void EVENT_USB_Device_ControlRequest(void)
 					"CLS:PRINTER";
 
 				Endpoint_ClearSETUP();
+
+				while (!(Endpoint_IsINReady()))
+				{
+					if (USB_DeviceState == DEVICE_STATE_Unattached)
+					  return;
+				}
+
 				Endpoint_Write_16_BE(sizeof(PrinterIDString));
 				Endpoint_Write_Control_Stream_LE(PrinterIDString, strlen(PrinterIDString));
 				Endpoint_ClearStatusStage();
@@ -390,6 +397,13 @@ void EVENT_USB_Device_ControlRequest(void)
 			if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
 			{
 				Endpoint_ClearSETUP();
+
+				while (!(Endpoint_IsINReady()))
+				{
+					if (USB_DeviceState == DEVICE_STATE_Unattached)
+					  return;
+				}
+
 				Endpoint_Write_8(PRNT_PORTSTATUS_NOTERROR | PRNT_PORTSTATUS_SELECT);
 				Endpoint_ClearStatusStage();
 			}
diff --git a/LUFA/DoxygenPages/ChangeLog.txt b/LUFA/DoxygenPages/ChangeLog.txt
index cd4310a26..e7615fdfc 100644
--- a/LUFA/DoxygenPages/ChangeLog.txt
+++ b/LUFA/DoxygenPages/ChangeLog.txt
@@ -24,6 +24,7 @@
   *     unknown SCSI command
   *   - Fixed incorrect HID report descriptor generated for 16-bit axis ranges by the HID_DESCRIPTOR_MOUSE() and HID_DESCRIPTOR_JOYSTICK()
   *     macros (thanks to Armory)
+  *   - Fixed race condition in the DFU class bootloader causing failed device reprogramming in some circumstances (thanks to Luis Mendes)
   *
   *  \section Sec_ChangeLog130303 Version 130303
   *  <b>New:</b>
-- 
GitLab