diff --git a/Demos/Device/ClassDriver/RNDISEthernet/Lib/Ethernet.c b/Demos/Device/ClassDriver/RNDISEthernet/Lib/Ethernet.c
index 918b627a56..dacbdbf89c 100644
--- a/Demos/Device/ClassDriver/RNDISEthernet/Lib/Ethernet.c
+++ b/Demos/Device/ClassDriver/RNDISEthernet/Lib/Ethernet.c
@@ -96,7 +96,6 @@ void Ethernet_ProcessPacket(Ethernet_Frame_Info_t* const FrameIN,
 
 			/* Set the response length in the buffer and indicate that a response is ready to be sent */
 			FrameOUT->FrameLength           = (sizeof(Ethernet_Frame_Header_t) + RetSize);
-			FrameOUT->FrameInBuffer         = true;
 		}
 	}
 
@@ -104,7 +103,7 @@ void Ethernet_ProcessPacket(Ethernet_Frame_Info_t* const FrameIN,
 	if (RetSize != NO_PROCESS)
 	{
 		/* Clear the frame buffer */
-		FrameIN->FrameInBuffer = false;
+		FrameIN->FrameLength = 0;
 	}
 }
 
diff --git a/Demos/Device/ClassDriver/RNDISEthernet/Lib/TCP.c b/Demos/Device/ClassDriver/RNDISEthernet/Lib/TCP.c
index a748289a28..f6354f5093 100644
--- a/Demos/Device/ClassDriver/RNDISEthernet/Lib/TCP.c
+++ b/Demos/Device/ClassDriver/RNDISEthernet/Lib/TCP.c
@@ -55,7 +55,8 @@ TCP_ConnectionState_t  ConnectionStateTable[MAX_TCP_CONNECTIONS];
  *  level. If an application produces a response, this task constructs the appropriate Ethernet frame and places it into the Ethernet OUT
  *  buffer for later transmission.
  */
-void TCP_TCPTask(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)
+void TCP_TCPTask(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo,
+		         Ethernet_Frame_Info_t* const FrameOUT)
 {
 	/* Run each application in sequence, to process incoming and generate outgoing packets */
 	for (uint8_t CSTableEntry = 0; CSTableEntry < MAX_TCP_CONNECTIONS; CSTableEntry++)
@@ -73,11 +74,8 @@ void TCP_TCPTask(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)
 		}
 	}
 
-	/* Get pointer to the output frame info struct for convenience */
-	Ethernet_Frame_Info_t* FrameOUT = &RNDISInterfaceInfo->State.FrameOUT;
-
 	/* Bail out early if there is already a frame waiting to be sent in the Ethernet OUT buffer */
-	if (FrameOUT->FrameInBuffer)
+	if (FrameOUT->FrameLength)
 	  return;
 
 	/* Send response packets from each application as the TCP packet buffers are filled by the applications */
@@ -147,7 +145,6 @@ void TCP_TCPTask(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)
 
 			/* Set the response length in the buffer and indicate that a response is ready to be sent */
 			FrameOUT->FrameLength           = PacketSize;
-			FrameOUT->FrameInBuffer         = true;
 
 			ConnectionStateTable[CSTableEntry].Info.Buffer.Ready = false;
 
diff --git a/Demos/Device/ClassDriver/RNDISEthernet/Lib/TCP.h b/Demos/Device/ClassDriver/RNDISEthernet/Lib/TCP.h
index cbb3c6eece..aad63a4fec 100644
--- a/Demos/Device/ClassDriver/RNDISEthernet/Lib/TCP.h
+++ b/Demos/Device/ClassDriver/RNDISEthernet/Lib/TCP.h
@@ -228,7 +228,8 @@
 		} TCP_Header_t;
 
 	/* Function Prototypes: */
-		void                  TCP_TCPTask(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo);
+		void                  TCP_TCPTask(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo,
+		                                  Ethernet_Frame_Info_t* const FrameOUT);
 		void                  TCP_Init(void);
 		bool                  TCP_SetPortState(const uint16_t Port,
 		                                       const uint8_t State,
diff --git a/Demos/Device/ClassDriver/RNDISEthernet/RNDISEthernet.c b/Demos/Device/ClassDriver/RNDISEthernet/RNDISEthernet.c
index e14f3f1de6..dc9682a05f 100644
--- a/Demos/Device/ClassDriver/RNDISEthernet/RNDISEthernet.c
+++ b/Demos/Device/ClassDriver/RNDISEthernet/RNDISEthernet.c
@@ -63,6 +63,8 @@ USB_ClassInfo_RNDIS_Device_t Ethernet_RNDIS_Interface =
 			},
 	};
 
+static Ethernet_Frame_Info_t FrameIN;
+static Ethernet_Frame_Info_t FrameOUT;
 
 /** Main program entry point. This routine contains the overall program flow, including initial
  *  setup of all components and the main program loop.
@@ -79,14 +81,23 @@ int main(void)
 
 	for (;;)
 	{
-		if (Ethernet_RNDIS_Interface.State.FrameIN.FrameInBuffer)
+		if (RNDIS_Device_IsPacketReceived(&Ethernet_RNDIS_Interface))
 		{
 			LEDs_SetAllLEDs(LEDMASK_USB_BUSY);
-			Ethernet_ProcessPacket(&Ethernet_RNDIS_Interface.State.FrameIN, &Ethernet_RNDIS_Interface.State.FrameOUT);
+			
+			RNDIS_Device_ReadPacket(&Ethernet_RNDIS_Interface, &FrameIN.FrameData, &FrameIN.FrameLength);
+			Ethernet_ProcessPacket(&FrameIN, &FrameOUT);
+			
+			if (FrameOUT.FrameLength)
+			{
+				RNDIS_Device_SendPacket(&Ethernet_RNDIS_Interface, &FrameOUT.FrameData, FrameOUT.FrameLength);				
+				FrameOUT.FrameLength = 0;
+			}
+			
 			LEDs_SetAllLEDs(LEDMASK_USB_READY);
 		}
 
-		TCP_TCPTask(&Ethernet_RNDIS_Interface);
+		TCP_TCPTask(&Ethernet_RNDIS_Interface, &FrameOUT);
 
 		RNDIS_Device_USBTask(&Ethernet_RNDIS_Interface);
 		USB_USBTask();
diff --git a/Demos/Device/LowLevel/RNDISEthernet/Lib/Ethernet.c b/Demos/Device/LowLevel/RNDISEthernet/Lib/Ethernet.c
index 488db76885..1e66cf03f5 100644
--- a/Demos/Device/LowLevel/RNDISEthernet/Lib/Ethernet.c
+++ b/Demos/Device/LowLevel/RNDISEthernet/Lib/Ethernet.c
@@ -100,7 +100,6 @@ void Ethernet_ProcessPacket(void)
 
 			/* Set the response length in the buffer and indicate that a response is ready to be sent */
 			FrameOUT.FrameLength            = (sizeof(Ethernet_Frame_Header_t) + RetSize);
-			FrameOUT.FrameInBuffer          = true;
 		}
 	}
 
@@ -108,7 +107,7 @@ void Ethernet_ProcessPacket(void)
 	if (RetSize != NO_PROCESS)
 	{
 		/* Clear the frame buffer */
-		FrameIN.FrameInBuffer = false;
+		FrameIN.FrameLength = 0;
 	}
 }
 
diff --git a/Demos/Device/LowLevel/RNDISEthernet/Lib/TCP.c b/Demos/Device/LowLevel/RNDISEthernet/Lib/TCP.c
index c773a64444..97c1355b2f 100644
--- a/Demos/Device/LowLevel/RNDISEthernet/Lib/TCP.c
+++ b/Demos/Device/LowLevel/RNDISEthernet/Lib/TCP.c
@@ -74,7 +74,7 @@ void TCP_Task(void)
 	}
 
 	/* Bail out early if there is already a frame waiting to be sent in the Ethernet OUT buffer */
-	if (FrameOUT.FrameInBuffer)
+	if (FrameOUT.FrameLength)
 	  return;
 
 	/* Send response packets from each application as the TCP packet buffers are filled by the applications */
@@ -144,7 +144,6 @@ void TCP_Task(void)
 
 			/* Set the response length in the buffer and indicate that a response is ready to be sent */
 			FrameOUT.FrameLength            = PacketSize;
-			FrameOUT.FrameInBuffer          = true;
 
 			ConnectionStateTable[CSTableEntry].Info.Buffer.Ready = false;
 
diff --git a/Demos/Device/LowLevel/RNDISEthernet/RNDISEthernet.c b/Demos/Device/LowLevel/RNDISEthernet/RNDISEthernet.c
index cc5f9e3022..9ad26dd2f6 100644
--- a/Demos/Device/LowLevel/RNDISEthernet/RNDISEthernet.c
+++ b/Demos/Device/LowLevel/RNDISEthernet/RNDISEthernet.c
@@ -204,7 +204,7 @@ void RNDIS_Task(void)
 		Endpoint_SelectEndpoint(CDC_RX_EPNUM);
 
 		/* Check if the data OUT endpoint contains data, and that the IN buffer is empty */
-		if (Endpoint_IsOUTReceived() && !(FrameIN.FrameInBuffer))
+		if (Endpoint_IsOUTReceived() && !(FrameIN.FrameLength))
 		{
 			/* Read in the packet message header */
 			Endpoint_Read_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_Packet_Message_t), NULL);
@@ -224,16 +224,13 @@ void RNDIS_Task(void)
 
 			/* Store the size of the Ethernet frame */
 			FrameIN.FrameLength = RNDISPacketHeader.DataLength;
-
-			/* Indicate Ethernet IN buffer full */
-			FrameIN.FrameInBuffer = true;
 		}
 
 		/* Select the data IN endpoint */
 		Endpoint_SelectEndpoint(CDC_TX_EPNUM);
 
 		/* Check if the data IN endpoint is ready for more data, and that the IN buffer is full */
-		if (Endpoint_IsINReady() && FrameOUT.FrameInBuffer)
+		if (Endpoint_IsINReady() && FrameOUT.FrameLength)
 		{
 			/* Clear the packet header with all 0s so that the relevant fields can be filled */
 			memset(&RNDISPacketHeader, 0, sizeof(RNDIS_Packet_Message_t));
@@ -254,7 +251,7 @@ void RNDIS_Task(void)
 			Endpoint_ClearIN();
 
 			/* Indicate Ethernet OUT buffer no longer full */
-			FrameOUT.FrameInBuffer = false;
+			FrameOUT.FrameLength = 0;
 		}
 	}
 }
@@ -273,7 +270,7 @@ void Ethernet_Task(void)
 	  return;
 
 	/* Check if a frame has been written to the IN frame buffer */
-	if (FrameIN.FrameInBuffer)
+	if (FrameIN.FrameLength)
 	{
 		/* Indicate packet processing started */
 		LEDs_SetAllLEDs(LEDMASK_USB_BUSY);
diff --git a/LUFA.pnproj b/LUFA.pnproj
index 28e972ed69..0d335d0e70 100644
--- a/LUFA.pnproj
+++ b/LUFA.pnproj
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/LUFA/Drivers/USB/Class/Common/RNDIS.h b/LUFA/Drivers/USB/Class/Common/RNDIS.h
index f98fc6d81d..0ca50d5af9 100644
--- a/LUFA/Drivers/USB/Class/Common/RNDIS.h
+++ b/LUFA/Drivers/USB/Class/Common/RNDIS.h
@@ -68,6 +68,9 @@
 		#endif
 
 	/* Macros: */
+		/** Additional error code for RNDIS functions when a device returns a logical command failure. */
+		#define RNDIS_ERROR_LOGICAL_CMD_FAILED        0x80
+
 		/** Implemented RNDIS Version Major. */
 		#define REMOTE_NDIS_VERSION_MAJOR             0x01
 
@@ -205,26 +208,26 @@
 		};
 
 	/* Type Defines: */
+		/** \brief Ethernet Frame Packet Information Structure.
+		 *
+		 *  Type define for an Ethernet frame buffer data and information structure. This can be used to conveniently
+		 *  store both the size and data in an Ethernet frame.
+		 */
+		typedef struct
+		{
+			uint8_t  FrameData[ETHERNET_FRAME_SIZE_MAX]; /**< Ethernet frame contents. */
+			uint16_t FrameLength; /**< Length in bytes of the Ethernet frame stored in the buffer. */
+		} Ethernet_Frame_Info_t;
+
 		/** \brief MAC Address Structure.
 		 *
 		 *  Type define for a physical MAC address of a device on a network.
 		 */
 		typedef struct
 		{
-			uint8_t       Octets[6]; /**< Individual bytes of a MAC address */
+			uint8_t Octets[6]; /**< Individual bytes of a MAC address */
 		} ATTR_PACKED MAC_Address_t;
 
-		/** \brief RNDIS Ethernet Frame Packet Information Structure.
-		 *
-		 *  Type define for an Ethernet frame buffer data and information structure.
-		 */
-		typedef struct
-		{
-			uint8_t       FrameData[ETHERNET_FRAME_SIZE_MAX]; /**< Ethernet frame contents. */
-			uint16_t      FrameLength; /**< Length in bytes of the Ethernet frame stored in the buffer. */
-			bool          FrameInBuffer; /**< Indicates if a frame is currently stored in the buffer. */
-		} ATTR_PACKED Ethernet_Frame_Info_t;
-
 		/** \brief RNDIS Common Message Header Structure.
 		 *
 		 *  Type define for a RNDIS message header, sent before RNDIS messages.
diff --git a/LUFA/Drivers/USB/Class/Device/RNDIS.c b/LUFA/Drivers/USB/Class/Device/RNDIS.c
index 616af5f7db..a9bbcfaba1 100644
--- a/LUFA/Drivers/USB/Class/Device/RNDIS.c
+++ b/LUFA/Drivers/USB/Class/Device/RNDIS.c
@@ -163,8 +163,6 @@ void RNDIS_Device_USBTask(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo
 	if (USB_DeviceState != DEVICE_STATE_Configured)
 	  return;
 
-	RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
-
 	Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.NotificationEndpointNumber);
 
 	if (Endpoint_IsINReady() && RNDISInterfaceInfo->State.ResponseReady)
@@ -184,50 +182,6 @@ void RNDIS_Device_USBTask(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo
 
 		RNDISInterfaceInfo->State.ResponseReady = false;
 	}
-
-	if ((RNDISInterfaceInfo->State.CurrRNDISState == RNDIS_Data_Initialized) && !(MessageHeader->MessageLength))
-	{
-		RNDIS_Packet_Message_t RNDISPacketHeader;
-
-		Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.DataOUTEndpointNumber);
-
-		if (Endpoint_IsOUTReceived() && !(RNDISInterfaceInfo->State.FrameIN.FrameInBuffer))
-		{
-			Endpoint_Read_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_Packet_Message_t), NULL);
-
-			if (RNDISPacketHeader.DataLength > ETHERNET_FRAME_SIZE_MAX)
-			{
-				Endpoint_StallTransaction();
-				return;
-			}
-
-			Endpoint_Read_Stream_LE(RNDISInterfaceInfo->State.FrameIN.FrameData, RNDISPacketHeader.DataLength, NULL);
-
-			Endpoint_ClearOUT();
-
-			RNDISInterfaceInfo->State.FrameIN.FrameLength = RNDISPacketHeader.DataLength;
-
-			RNDISInterfaceInfo->State.FrameIN.FrameInBuffer = true;
-		}
-
-		Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.DataINEndpointNumber);
-
-		if (Endpoint_IsINReady() && RNDISInterfaceInfo->State.FrameOUT.FrameInBuffer)
-		{
-			memset(&RNDISPacketHeader, 0, sizeof(RNDIS_Packet_Message_t));
-
-			RNDISPacketHeader.MessageType   = REMOTE_NDIS_PACKET_MSG;
-			RNDISPacketHeader.MessageLength = (sizeof(RNDIS_Packet_Message_t) + RNDISInterfaceInfo->State.FrameOUT.FrameLength);
-			RNDISPacketHeader.DataOffset    = (sizeof(RNDIS_Packet_Message_t) - sizeof(RNDIS_Message_Header_t));
-			RNDISPacketHeader.DataLength    = RNDISInterfaceInfo->State.FrameOUT.FrameLength;
-
-			Endpoint_Write_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_Packet_Message_t), NULL);
-			Endpoint_Write_Stream_LE(RNDISInterfaceInfo->State.FrameOUT.FrameData, RNDISPacketHeader.DataLength, NULL);
-			Endpoint_ClearIN();
-
-			RNDISInterfaceInfo->State.FrameOUT.FrameInBuffer = false;
-		}
-	}
 }
 
 void RNDIS_Device_ProcessRNDISControlMessage(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)
@@ -493,5 +447,85 @@ static bool RNDIS_Device_ProcessNDISSet(USB_ClassInfo_RNDIS_Device_t* const RNDI
 	}
 }
 
+bool RNDIS_Device_IsPacketReceived(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)
+{
+	if ((USB_DeviceState != DEVICE_STATE_Configured) ||
+	    (RNDISInterfaceInfo->State.CurrRNDISState != RNDIS_Data_Initialized))
+	{
+		return false;
+	}
+	
+	Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.DataOUTEndpointNumber);
+	return Endpoint_IsOUTReceived();
+}
+
+uint8_t RNDIS_Device_ReadPacket(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo,
+                                void* Buffer,
+                                uint16_t* const PacketLength)
+{
+	if ((USB_DeviceState != DEVICE_STATE_Configured) ||
+	    (RNDISInterfaceInfo->State.CurrRNDISState != RNDIS_Data_Initialized))
+	{
+		return ENDPOINT_RWSTREAM_DeviceDisconnected;
+	}
+	
+	Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.DataOUTEndpointNumber);
+	
+	*PacketLength = 0;
+
+	if (!(Endpoint_IsOUTReceived()))
+		return ENDPOINT_RWSTREAM_NoError;
+
+	RNDIS_Packet_Message_t RNDISPacketHeader;	
+	Endpoint_Read_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_Packet_Message_t), NULL);
+
+	if (RNDISPacketHeader.DataLength > ETHERNET_FRAME_SIZE_MAX)
+	{
+		Endpoint_StallTransaction();
+
+		return RNDIS_ERROR_LOGICAL_CMD_FAILED;
+	}
+	
+	*PacketLength = (uint16_t)RNDISPacketHeader.DataLength;
+
+	Endpoint_Read_Stream_LE(Buffer, RNDISPacketHeader.DataLength, NULL);
+	Endpoint_ClearOUT();
+	
+	return ENDPOINT_RWSTREAM_NoError;
+}
+
+uint8_t RNDIS_Device_SendPacket(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo,
+                                void* Buffer,
+                                const uint16_t PacketLength)
+{
+	uint8_t ErrorCode;
+
+	if ((USB_DeviceState != DEVICE_STATE_Configured) ||
+	    (RNDISInterfaceInfo->State.CurrRNDISState != RNDIS_Data_Initialized))
+	{
+		return ENDPOINT_RWSTREAM_DeviceDisconnected;
+	}
+	
+	Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.DataINEndpointNumber);
+
+	if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError)
+	  return ErrorCode;
+
+	RNDIS_Packet_Message_t RNDISPacketHeader;
+
+	memset(&RNDISPacketHeader, 0, sizeof(RNDIS_Packet_Message_t));
+
+	RNDISPacketHeader.MessageType   = REMOTE_NDIS_PACKET_MSG;
+	RNDISPacketHeader.MessageLength = (sizeof(RNDIS_Packet_Message_t) + PacketLength);
+	RNDISPacketHeader.DataOffset    = (sizeof(RNDIS_Packet_Message_t) - sizeof(RNDIS_Message_Header_t));
+	RNDISPacketHeader.DataLength    = PacketLength;
+
+	Endpoint_Write_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_Packet_Message_t), NULL);
+	Endpoint_Write_Stream_LE(Buffer, PacketLength, NULL);
+	Endpoint_ClearIN();
+
+	return ENDPOINT_RWSTREAM_NoError;
+}
+
 #endif
 
diff --git a/LUFA/Drivers/USB/Class/Device/RNDIS.h b/LUFA/Drivers/USB/Class/Device/RNDIS.h
index f53a8e01fe..734ceb3fd2 100644
--- a/LUFA/Drivers/USB/Class/Device/RNDIS.h
+++ b/LUFA/Drivers/USB/Class/Device/RNDIS.h
@@ -106,12 +106,6 @@
 					bool     ResponseReady; /**< Internal flag indicating if a RNDIS message is waiting to be returned to the host. */
 					uint8_t  CurrRNDISState; /**< Current RNDIS state of the adapter, a value from the \ref RNDIS_States_t enum. */
 					uint32_t CurrPacketFilter; /**< Current packet filter mode, used internally by the class driver. */
-					Ethernet_Frame_Info_t FrameIN; /**< Structure holding the last received Ethernet frame from the host, for user
-													*   processing.
-													*/
-					Ethernet_Frame_Info_t FrameOUT; /**< Structure holding the next Ethernet frame to send to the host, populated by the
-													 *   user application.
-													 */
 				} State; /**< State data for the USB class interface within the device. All elements in this section
 				          *   are reset to their defaults when the interface is enumerated.
 				          */
@@ -146,6 +140,48 @@
 			 */
 			void RNDIS_Device_USBTask(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
 
+			/** Determines if a packet is currently waiting for the device to read in and process.
+			 *
+			 *  \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or the
+			 *       call will fail.
+			 *
+			 *  \param[in,out] RNDISInterfaceInfo  Pointer to a structure containing an RNDIS Class configuration and state.
+			 *
+			 *  \return Boolean \c true if a packet is waiting to be read in by the host, \c false otherwise.
+			 */
+			bool RNDIS_Device_IsPacketReceived(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo);
+
+			/** Retrieves the next pending packet from the device, discarding the remainder of the RNDIS packet header to leave
+			 *  only the packet contents for processing by the device in the nominated buffer.
+			 *
+			 *  \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or the
+			 *       call will fail.
+			 *
+			 *  \param[in,out] RNDISInterfaceInfo  Pointer to a structure containing an RNDIS Class configuration and state.
+			 *  \param[out]    Buffer              Pointer to a buffer where the packer data is to be written to.
+			 *  \param[out]    PacketLength        Pointer to where the length in bytes of the read packet is to be stored.
+			 *
+			 *  \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
+			 */
+			uint8_t RNDIS_Device_ReadPacket(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo,
+											void* Buffer,
+											uint16_t* const PacketLength);
+
+			/** Sends the given packet to the attached RNDIS device, after adding a RNDIS packet message header.
+			 *
+			 *  \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or the
+			 *       call will fail.
+			 *
+			 *  \param[in,out] RNDISInterfaceInfo  Pointer to a structure containing an RNDIS Class configuration and state.
+			 *  \param[in]     Buffer              Pointer to a buffer where the packer data is to be read from.
+			 *  \param[in]     PacketLength        Length in bytes of the packet to send.
+			 *
+			 *  \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
+			 */
+			uint8_t RNDIS_Device_SendPacket(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo,
+											void* Buffer,
+											const uint16_t PacketLength);
+
 	/* Private Interface - For use in library only: */
 	#if !defined(__DOXYGEN__)
 		/* Function Prototypes: */
diff --git a/LUFA/Drivers/USB/Class/Host/RNDIS.c b/LUFA/Drivers/USB/Class/Host/RNDIS.c
index 23497574c9..a75adcc97d 100644
--- a/LUFA/Drivers/USB/Class/Host/RNDIS.c
+++ b/LUFA/Drivers/USB/Class/Host/RNDIS.c
@@ -315,7 +315,7 @@ uint8_t RNDIS_Host_InitializeDevice(USB_ClassInfo_RNDIS_Host_t* const RNDISInter
 	}
 
 	if (InitMessageResponse.Status != REMOTE_NDIS_STATUS_SUCCESS)
-	  return RNDIS_COMMAND_FAILED;
+	  return RNDIS_ERROR_LOGICAL_CMD_FAILED;
 
 	RNDISInterfaceInfo->State.DeviceMaxPacketSize = InitMessageResponse.MaxTransferSize;
 
@@ -361,7 +361,7 @@ uint8_t RNDIS_Host_SetRNDISProperty(USB_ClassInfo_RNDIS_Host_t* const RNDISInter
 	}
 
 	if (SetMessageResponse.Status != REMOTE_NDIS_STATUS_SUCCESS)
-	  return RNDIS_COMMAND_FAILED;
+	  return RNDIS_ERROR_LOGICAL_CMD_FAILED;
 
 	return HOST_SENDCONTROL_Successful;
 }
@@ -403,7 +403,7 @@ uint8_t RNDIS_Host_QueryRNDISProperty(USB_ClassInfo_RNDIS_Host_t* const RNDISInt
 	}
 
 	if (QueryMessageResponseData.QueryMessageResponse.Status != REMOTE_NDIS_STATUS_SUCCESS)
-	  return RNDIS_COMMAND_FAILED;
+	  return RNDIS_ERROR_LOGICAL_CMD_FAILED;
 
 	memcpy(Buffer, &QueryMessageResponseData.ContiguousBuffer, MaxLength);
 
@@ -458,7 +458,8 @@ uint8_t RNDIS_Host_ReadPacket(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceIn
 
 	*PacketLength = (uint16_t)DeviceMessage.DataLength;
 
-	Pipe_Discard_Stream(DeviceMessage.DataOffset - (sizeof(RNDIS_Packet_Message_t) - sizeof(RNDIS_Message_Header_t)),
+	Pipe_Discard_Stream(DeviceMessage.DataOffset -
+	                    (sizeof(RNDIS_Packet_Message_t) - sizeof(RNDIS_Message_Header_t)),
 	                    NULL);
 
 	Pipe_Read_Stream_LE(Buffer, *PacketLength, NULL);
diff --git a/LUFA/Drivers/USB/Class/Host/RNDIS.h b/LUFA/Drivers/USB/Class/Host/RNDIS.h
index 376cc59252..138466b1a7 100644
--- a/LUFA/Drivers/USB/Class/Host/RNDIS.h
+++ b/LUFA/Drivers/USB/Class/Host/RNDIS.h
@@ -124,10 +124,6 @@
 				RNDIS_ENUMERROR_PipeConfigurationFailed    = 3, /**< One or more pipes for the specified interface could not be configured correctly. */
 			};
 
-		/* Macros: */
-			/** Additional error code for RNDIS functions when a device returns a logical command failure. */
-			#define RNDIS_COMMAND_FAILED                  0xC0
-
 		/* Function Prototypes: */
 			/** Host interface configuration routine, to configure a given RNDIS host interface instance using the Configuration
 			 *  Descriptor read from an attached USB device. This function automatically updates the given RNDIS Host instance's
diff --git a/LUFA/ManPages/ChangeLog.txt b/LUFA/ManPages/ChangeLog.txt
index 237710d984..dd58c24dd6 100644
--- a/LUFA/ManPages/ChangeLog.txt
+++ b/LUFA/ManPages/ChangeLog.txt
@@ -29,6 +29,7 @@
   *   - Added new architecture independant functions to enable, disable, save and restore the Global Interrupt Enable flags
   *   - Added USE_LUFA_CONFIG_HEADER compile time option to include a LUFAConfig.h header in the user director for LUFA configuration
   *     tokens as an alternative to tokens defined in the project makefile
+  *   - Added new RNDIS Device Classs Driver packet send and receive functions
   *  - Library Applications:
   *   - Added ability to write protect Mass Storage disk write operations from the host OS
   *   - Added new MIDIToneGenerator project
diff --git a/LUFA/ManPages/MigrationInformation.txt b/LUFA/ManPages/MigrationInformation.txt
index 8d35bbd4c1..d3782d317d 100644
--- a/LUFA/ManPages/MigrationInformation.txt
+++ b/LUFA/ManPages/MigrationInformation.txt
@@ -51,6 +51,9 @@
  *      code using these functions should replace the previous function names with the new function names.
  *    - The Endpoint_*_DWord() functions have been renamed Endpoint_*_32() to ensure they are correct across all architectures. Existing
  *      code using these functions should replace the previous function names with the new function names.
+ *    - The Device mode RNDIS class driver no longer stores the incoming and outgoing packets in the class driver instance; the user is
+ *      now expected to manually define a storage location for the packet data. Packets must now be sent and received manually via a call
+ *      to \ref RNDIS_Device_ReadPacket() and/or \ref RNDIS_Device_WritePacket().
  *
  *  Host Mode
  *    - The Pipe stream functions now all require a \c BytesProcessed parameter instead of the previous callback parameter.