diff --git a/Demos/Host/LowLevel/MassStorageHost/Lib/MassStoreCommands.c b/Demos/Host/LowLevel/MassStorageHost/Lib/MassStoreCommands.c
index 0d8a231f2e364b5c18f278344d3a323e73841237..c86e51b0c57b6c070dd304a662e2458c86eb27e9 100644
--- a/Demos/Host/LowLevel/MassStorageHost/Lib/MassStoreCommands.c
+++ b/Demos/Host/LowLevel/MassStorageHost/Lib/MassStoreCommands.c
@@ -110,20 +110,23 @@ static uint8_t MassStore_SendCommand(CommandBlockWrapper_t* const SCSICommandBlo
  */
 static uint8_t MassStore_WaitForDataReceived(void)
 {
-	uint16_t TimeoutMSRem = COMMAND_DATA_TIMEOUT_MS;
+	uint16_t TimeoutMSRem        = COMMAND_DATA_TIMEOUT_MS;
+	uint16_t PreviousFrameNumber = USB_Host_GetFrameNumber();
 
 	/* Select the IN data pipe for data reception */
 	Pipe_SelectPipe(MASS_STORE_DATA_IN_PIPE);
 	Pipe_Unfreeze();
-
+	
 	/* Wait until data received in the IN pipe */
 	while (!(Pipe_IsINReceived()))
 	{
+		uint16_t CurrentFrameNumber = USB_Host_GetFrameNumber();
+		
 		/* Check to see if a new frame has been issued (1ms elapsed) */
-		if (USB_INT_HasOccurred(USB_INT_HSOFI))
+		if (CurrentFrameNumber != PreviousFrameNumber)
 		{
-			/* Clear the flag and decrement the timeout period counter */
-			USB_INT_Clear(USB_INT_HSOFI);
+			/* Save the new frame number and decrement the timeout period */
+			PreviousFrameNumber = CurrentFrameNumber;
 			TimeoutMSRem--;
 
 			/* Check to see if the timeout period for the command has elapsed */
diff --git a/Demos/Host/LowLevel/StillImageHost/Lib/StillImageCommands.c b/Demos/Host/LowLevel/StillImageHost/Lib/StillImageCommands.c
index a99a95680b61909b68a46cac818c84d233650fd6..861f55b5dee35f8eff6dec67f5bc031e715e517d 100644
--- a/Demos/Host/LowLevel/StillImageHost/Lib/StillImageCommands.c
+++ b/Demos/Host/LowLevel/StillImageHost/Lib/StillImageCommands.c
@@ -108,28 +108,28 @@ uint8_t SImage_ReceiveEventHeader(void)
  */
 uint8_t SImage_ReceiveBlockHeader(void)
 {
-	uint16_t TimeoutMSRem = COMMAND_DATA_TIMEOUT_MS;
+	uint16_t TimeoutMSRem        = COMMAND_DATA_TIMEOUT_MS;
+	uint16_t PreviousFrameNumber = USB_Host_GetFrameNumber();
 
 	/* Unfreeze the data IN pipe */
 	Pipe_SelectPipe(SIMAGE_DATA_IN_PIPE);
 	Pipe_Unfreeze();
 	
 	/* Wait until data received on the IN pipe */
-	while (!(Pipe_IsReadWriteAllowed()))
+	while (!(Pipe_IsINReceived()))
 	{
+		uint16_t CurrentFrameNumber = USB_Host_GetFrameNumber();
+
 		/* Check to see if a new frame has been issued (1ms elapsed) */
-		if (USB_INT_HasOccurred(USB_INT_HSOFI))
+		if (CurrentFrameNumber != PreviousFrameNumber)
 		{
-			/* Clear the flag and decrement the timeout period counter */
-			USB_INT_Clear(USB_INT_HSOFI);
+			/* Save the new frame number and decrement the timeout period */
+			PreviousFrameNumber = CurrentFrameNumber;
 			TimeoutMSRem--;
 
 			/* Check to see if the timeout period for the command has elapsed */
 			if (!(TimeoutMSRem))
-			{
-				/* Return error code */
-				return PIPE_RWSTREAM_Timeout;
-			}
+			  return PIPE_RWSTREAM_Timeout;
 		}
 		
 		Pipe_Freeze();
diff --git a/LUFA/Drivers/USB/Class/Host/MassStorage.c b/LUFA/Drivers/USB/Class/Host/MassStorage.c
index 14b7741db313582052d4ba22606ed059a46368c0..dfa954c5c5537b643cbb9c72ffa67cf9620d1d7a 100644
--- a/LUFA/Drivers/USB/Class/Host/MassStorage.c
+++ b/LUFA/Drivers/USB/Class/Host/MassStorage.c
@@ -166,19 +166,21 @@ static uint8_t MS_Host_SendCommand(USB_ClassInfo_MS_Host_t* const MSInterfaceInf
 
 static uint8_t MS_Host_WaitForDataReceived(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo)
 {
-	uint16_t TimeoutMSRem = COMMAND_DATA_TIMEOUT_MS;
+	uint16_t TimeoutMSRem        = COMMAND_DATA_TIMEOUT_MS;
+	uint16_t PreviousFrameNumber = USB_Host_GetFrameNumber();
 
 	Pipe_SelectPipe(MSInterfaceInfo->Config.DataINPipeNumber);
 	Pipe_Unfreeze();
 
 	while (!(Pipe_IsINReceived()))
 	{
-		if (USB_INT_HasOccurred(USB_INT_HSOFI))
+		uint16_t CurrentFrameNumber = USB_Host_GetFrameNumber();
+		
+		if (CurrentFrameNumber != PreviousFrameNumber)
 		{
-			USB_INT_Clear(USB_INT_HSOFI);
-			TimeoutMSRem--;
+			PreviousFrameNumber = CurrentFrameNumber;
 
-			if (!(TimeoutMSRem))
+			if (!(TimeoutMSRem--))
 			  return PIPE_RWSTREAM_Timeout;
 		}
 	
diff --git a/LUFA/Drivers/USB/Class/Host/StillImage.c b/LUFA/Drivers/USB/Class/Host/StillImage.c
index 42c3feca626e6caa118a47f9ebc8e7ae0ed773ab..e08fc76af31b7b129fc889afc35ca9e02e577f38 100644
--- a/LUFA/Drivers/USB/Class/Host/StillImage.c
+++ b/LUFA/Drivers/USB/Class/Host/StillImage.c
@@ -179,7 +179,8 @@ uint8_t SImage_Host_SendBlockHeader(USB_ClassInfo_SI_Host_t* const SIInterfaceIn
 uint8_t SImage_Host_ReceiveBlockHeader(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,
                                        SI_PIMA_Container_t* const PIMAHeader)
 {
-	uint16_t TimeoutMSRem = COMMAND_DATA_TIMEOUT_MS;
+	uint16_t TimeoutMSRem        = COMMAND_DATA_TIMEOUT_MS;
+	uint16_t PreviousFrameNumber = USB_Host_GetFrameNumber();
 
 	if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
 	  return PIPE_RWSTREAM_DeviceDisconnected;
@@ -187,17 +188,16 @@ uint8_t SImage_Host_ReceiveBlockHeader(USB_ClassInfo_SI_Host_t* const SIInterfac
 	Pipe_SelectPipe(SIInterfaceInfo->Config.DataINPipeNumber);
 	Pipe_Unfreeze();
 	
-	while (!(Pipe_IsReadWriteAllowed()))
+	while (!(Pipe_IsINReceived()))
 	{
-		if (USB_INT_HasOccurred(USB_INT_HSOFI))
+		uint16_t CurrentFrameNumber = USB_Host_GetFrameNumber();
+		
+		if (CurrentFrameNumber != PreviousFrameNumber)
 		{
-			USB_INT_Clear(USB_INT_HSOFI);
-			TimeoutMSRem--;
+			PreviousFrameNumber = CurrentFrameNumber;
 
-			if (!(TimeoutMSRem))
-			{
-				return PIPE_RWSTREAM_Timeout;
-			}
+			if (!(TimeoutMSRem--))
+			  return PIPE_RWSTREAM_Timeout;
 		}
 		
 		Pipe_Freeze();
diff --git a/LUFA/Drivers/USB/HighLevel/Events.h b/LUFA/Drivers/USB/HighLevel/Events.h
index 5c295b61fc212be1e861815151b58b72dda9ff08..ae7debbb73071658209d54ec31b223ca41ad51bd 100644
--- a/LUFA/Drivers/USB/HighLevel/Events.h
+++ b/LUFA/Drivers/USB/HighLevel/Events.h
@@ -180,6 +180,23 @@
 			 */
 			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 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 AVR in device mode and the device is connected
 			 *  to a host, beginning the enumeration process, measured by a rising level on the AVR's VBUS pin.
 			 *
@@ -339,6 +356,7 @@
 					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)
diff --git a/LUFA/Drivers/USB/LowLevel/Device.h b/LUFA/Drivers/USB/LowLevel/Device.h
index 17984c719f83a8d39353a8c84b78677b2d935fa0..300793612576e0350c9203d5d8c7f9cd8f47867d 100644
--- a/LUFA/Drivers/USB/LowLevel/Device.h
+++ b/LUFA/Drivers/USB/LowLevel/Device.h
@@ -140,6 +140,14 @@
 			};
 			
 		/* 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.
+			 */
+			static inline uint16_t USB_Device_GetFrameNumber(void)
+			{
+				return UDFNUM;
+			}
+		
 			/** 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.
diff --git a/LUFA/Drivers/USB/LowLevel/Endpoint.c b/LUFA/Drivers/USB/LowLevel/Endpoint.c
index 4b2d1c059b2657267a1bfb06db0d35f17884bedc..fdb6c7469ecfbbdc34e7b86e714ab167af411f8a 100644
--- a/LUFA/Drivers/USB/LowLevel/Endpoint.c
+++ b/LUFA/Drivers/USB/LowLevel/Endpoint.c
@@ -142,6 +142,8 @@ uint8_t Endpoint_WaitUntilReady(void)
 	uint16_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS;
 	#endif
 
+	uint16_t PreviousFrameNumber = USB_Device_GetFrameNumber();
+
 	for (;;)
 	{
 		if (Endpoint_GetEndpointDirection() == ENDPOINT_DIR_IN)
@@ -161,10 +163,12 @@ uint8_t Endpoint_WaitUntilReady(void)
 		  return ENDPOINT_READYWAIT_BusSuspended;
 		else if (Endpoint_IsStalled())
 		  return ENDPOINT_READYWAIT_EndpointStalled;
-			  
-		if (USB_INT_HasOccurred(USB_INT_SOFI))
+
+		uint16_t CurrentFrameNumber = USB_Device_GetFrameNumber();
+
+		if (CurrentFrameNumber != PreviousFrameNumber)
 		{
-			USB_INT_Clear(USB_INT_SOFI);
+			PreviousFrameNumber = CurrentFrameNumber;
 
 			if (!(TimeoutMSRem--))
 			  return ENDPOINT_READYWAIT_Timeout;
diff --git a/LUFA/Drivers/USB/LowLevel/Host.c b/LUFA/Drivers/USB/LowLevel/Host.c
index 5b7a714babb8772f8ac2dbf9a683393fb0d03c68..2b66e28b4b7cf783d98622a78aba5bff862907a7 100644
--- a/LUFA/Drivers/USB/LowLevel/Host.c
+++ b/LUFA/Drivers/USB/LowLevel/Host.c
@@ -194,16 +194,19 @@ void USB_Host_ProcessNextHostState(void)
 
 uint8_t USB_Host_WaitMS(uint8_t MS)
 {
-	bool    BusSuspended = USB_Host_IsBusSuspended();
-	uint8_t ErrorCode    = HOST_WAITERROR_Successful;
+	bool     BusSuspended        = USB_Host_IsBusSuspended();
+	uint8_t  ErrorCode           = HOST_WAITERROR_Successful;
+	uint16_t PreviousFrameNumber = USB_Host_GetFrameNumber();
 	
 	USB_Host_ResumeBus();
 
 	while (MS)
 	{
-		if (USB_INT_HasOccurred(USB_INT_HSOFI))
+		uint16_t CurrentFrameNumber = USB_Host_GetFrameNumber();
+
+		if (CurrentFrameNumber != PreviousFrameNumber)
 		{
-			USB_INT_Clear(USB_INT_HSOFI);
+			PreviousFrameNumber = CurrentFrameNumber;
 			MS--;
 		}
 					
@@ -245,11 +248,13 @@ static void USB_Host_ResetDevice(void)
 	
 	USB_Host_ResetBus();
 	while (!(USB_Host_IsBusResetComplete()));
-
 	USB_Host_ResumeBus();
 
-	USB_INT_Clear(USB_INT_HSOFI);
+	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,
@@ -267,6 +272,9 @@ static void USB_Host_ResetDevice(void)
 		_delay_ms(1);
 	}
 
+	if (HSOFIEnabled)
+	  USB_INT_Enable(USB_INT_HSOFI);
+
 	if (BusSuspended)
 	  USB_Host_SuspendBus();
 
diff --git a/LUFA/Drivers/USB/LowLevel/Host.h b/LUFA/Drivers/USB/LowLevel/Host.h
index 8623c4ec6b254381261b2324418c727efedec8b2..40f630e845f29706aefac4e65da16084f310ce6e 100644
--- a/LUFA/Drivers/USB/LowLevel/Host.h
+++ b/LUFA/Drivers/USB/LowLevel/Host.h
@@ -245,6 +245,33 @@
 			};
 
 		/* 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.
+			 */
+			static inline uint16_t USB_Host_GetFrameNumber(void)
+			{
+				return UHFNUM;
+			}
+			
+			/** 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.
+			 */
+			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.
+			 */
+			static inline void USB_Host_DisableSOFEvents(void) ATTR_ALWAYS_INLINE;
+			static inline void USB_Host_DisableSOFEvents(void)
+			{
+				USB_INT_Disable(USB_INT_HSOFI);
+			}
+
 			/** 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).
 			 *
diff --git a/LUFA/Drivers/USB/LowLevel/Pipe.c b/LUFA/Drivers/USB/LowLevel/Pipe.c
index a8eb50f639a1b2db8c6764e01688e99be7403bdd..5f1090245b13c8478a4073c1ac11aadf51ef5c84 100644
--- a/LUFA/Drivers/USB/LowLevel/Pipe.c
+++ b/LUFA/Drivers/USB/LowLevel/Pipe.c
@@ -133,6 +133,8 @@ uint8_t Pipe_WaitUntilReady(void)
 	#else
 	uint16_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS;
 	#endif
+
+	uint16_t PreviousFrameNumber = USB_Host_GetFrameNumber();
 	
 	for (;;)
 	{
@@ -151,10 +153,12 @@ uint8_t Pipe_WaitUntilReady(void)
 		  return PIPE_READYWAIT_PipeStalled;
 		else if (USB_HostState == HOST_STATE_Unattached)
 		  return PIPE_READYWAIT_DeviceDisconnected;
-			  
-		if (USB_INT_HasOccurred(USB_INT_HSOFI))
+
+		uint16_t CurrentFrameNumber = USB_Host_GetFrameNumber();
+
+		if (CurrentFrameNumber != PreviousFrameNumber)
 		{
-			USB_INT_Clear(USB_INT_HSOFI);
+			PreviousFrameNumber = CurrentFrameNumber;
 
 			if (!(TimeoutMSRem--))
 			  return PIPE_READYWAIT_Timeout;
diff --git a/LUFA/Drivers/USB/LowLevel/USBInterrupt.c b/LUFA/Drivers/USB/LowLevel/USBInterrupt.c
index 1c6d6caa79e6765854ea3748d78afbfe84aa25ef..36541cf7fa6654e4802c7bb4a5151e5810aeaaae 100644
--- a/LUFA/Drivers/USB/LowLevel/USBInterrupt.c
+++ b/LUFA/Drivers/USB/LowLevel/USBInterrupt.c
@@ -209,6 +209,13 @@ ISR(USB_GEN_vect, ISR_BLOCK)
 
 		USB_ResetInterface();
 	}
+
+	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 defined(USB_CAN_BE_BOTH)
diff --git a/LUFA/ManPages/ChangeLog.txt b/LUFA/ManPages/ChangeLog.txt
index 0467e2815de65bf48f4098cb22dd5bd3bf17e07c..9a801b400d0c96a2478ca7c600a0010c035b0b4e 100644
--- a/LUFA/ManPages/ChangeLog.txt
+++ b/LUFA/ManPages/ChangeLog.txt
@@ -13,6 +13,9 @@
   *  - Moved the Pipe and Endpoint stream related code to two new USB library core source files EndpointStream.c and PipeStream.c
   *  - Added board hardware driver support for the Olimex AVR-USB-162 development board (thanks to Steve Fawcett)
   *  - Added board hardware driver support for the USBFOO development board
+  *  - Added new USB_Device_GetFrameNumber() and USB_Host_GetFrameNumber() functions to retrieve the current USB frame number
+  *  - Added new USB_Host_EnableSOFEvents(), USB_Host_DisableSOFEvents() and EVENT_USB_Host_StartOfFrame() for the user application
+  *    handling of USB Start of Frame events while in USB Host mode
   *
   *  <b>Changed:</b>
   *  - Removed complicated logic for the Endpoint_ConfigureEndpoint() function to use inlined or function called versions
@@ -29,6 +32,8 @@
   *  - Changed the signature of the CALLBACK_USB_GetDescriptor() callback function so that the descriptor pointer is const, to remove
   *    the need for extra casting inside the callback (thanks to Jonathan Kollasch)
   *  - Reduced HOST_DEVICE_SETTLE_DELAY_MS to 1000ms down from 1500ms to improve device compatibility while in USB Host mode
+  *  - Changed over all demos, drivers and internal functions to use the current frame number over the Start of Frame flag where possible
+  *    to free up the Start of Frame flag for interrupt use in the user application
   *
   *  <b>Fixed:</b>
   *  - Fixed USB_GetHIDReportItemInfo() function modifying the given report item's data when the report item does not exist