#include "RNDISEthernet.h"
+/** Message buffer for RNDIS messages processed by the RNDIS device class driver. */
+static uint8_t RNDIS_Message_Buffer[192];
+
+/** Global to store the incoming frame from the host before it is processed by the device. */
+static Ethernet_Frame_Info_t FrameIN;
+
+/** Global to store the outgoing frame created in the device before it is sent to the host. */
+static Ethernet_Frame_Info_t FrameOUT;
+
/** LUFA RNDIS Class driver interface configuration and state information. This structure is
* passed to all RNDIS Class driver functions, so that multiple instances of the same class
* within a device can be differentiated from one another.
},
.AdapterVendorDescription = "LUFA RNDIS Demo Adapter",
.AdapterMACAddress = {ADAPTER_MAC_ADDRESS},
+ .MessageBuffer = RNDIS_Message_Buffer,
+ .MessageBufferLength = sizeof(RNDIS_Message_Buffer),
},
};
-/** Global to store the incoming frame from the host before it is processed by the device. */
-static Ethernet_Frame_Info_t FrameIN;
-
-/** Global to store the outgoing frame created in the device before it is sent to the host. */
-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.
if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
{
Endpoint_ClearSETUP();
- Endpoint_Read_Control_Stream_LE(RNDISInterfaceInfo->State.RNDISMessageBuffer, USB_ControlRequest.wLength);
+ Endpoint_Read_Control_Stream_LE(RNDISInterfaceInfo->Config.MessageBuffer, USB_ControlRequest.wLength);
Endpoint_ClearIN();
RNDIS_Device_ProcessRNDISControlMessage(RNDISInterfaceInfo);
case RNDIS_REQ_GetEncapsulatedResponse:
if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
{
- RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
+ RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)RNDISInterfaceInfo->Config.MessageBuffer;
if (!(MessageHeader->MessageLength))
{
- RNDISInterfaceInfo->State.RNDISMessageBuffer[0] = 0;
- MessageHeader->MessageLength = CPU_TO_LE32(1);
+ RNDISInterfaceInfo->Config.MessageBuffer[0] = 0;
+ MessageHeader->MessageLength = CPU_TO_LE32(1);
}
Endpoint_ClearSETUP();
- Endpoint_Write_Control_Stream_LE(RNDISInterfaceInfo->State.RNDISMessageBuffer, le32_to_cpu(MessageHeader->MessageLength));
+ Endpoint_Write_Control_Stream_LE(RNDISInterfaceInfo->Config.MessageBuffer, le32_to_cpu(MessageHeader->MessageLength));
Endpoint_ClearOUT();
MessageHeader->MessageLength = CPU_TO_LE32(0);
RNDISInterfaceInfo->Config.DataOUTEndpoint.Type = EP_TYPE_BULK;
RNDISInterfaceInfo->Config.NotificationEndpoint.Type = EP_TYPE_INTERRUPT;
+ if (RNDISInterfaceInfo->Config.MessageBuffer == NULL)
+ return false;
+
+ if (RNDISInterfaceInfo->Config.MessageBufferLength < RNDIS_DEVICE_MIN_MESSAGE_BUFFER_LENGTH)
+ return false;
+
if (!(Endpoint_ConfigureEndpointTable(&RNDISInterfaceInfo->Config.DataINEndpoint, 1)))
return false;
/* Note: Only a single buffer is used for both the received message and its response to save SRAM. Because of
this, response bytes should be filled in order so that they do not clobber unread data in the buffer. */
- RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
+ RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)RNDISInterfaceInfo->Config.MessageBuffer;
switch (le32_to_cpu(MessageHeader->MessageType))
{
RNDISInterfaceInfo->State.ResponseReady = true;
RNDIS_Initialize_Message_t* INITIALIZE_Message =
- (RNDIS_Initialize_Message_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
+ (RNDIS_Initialize_Message_t*)RNDISInterfaceInfo->Config.MessageBuffer;
RNDIS_Initialize_Complete_t* INITIALIZE_Response =
- (RNDIS_Initialize_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
+ (RNDIS_Initialize_Complete_t*)RNDISInterfaceInfo->Config.MessageBuffer;
INITIALIZE_Response->MessageType = CPU_TO_LE32(REMOTE_NDIS_INITIALIZE_CMPLT);
INITIALIZE_Response->MessageLength = CPU_TO_LE32(sizeof(RNDIS_Initialize_Complete_t));
case REMOTE_NDIS_QUERY_MSG:
RNDISInterfaceInfo->State.ResponseReady = true;
- RNDIS_Query_Message_t* QUERY_Message = (RNDIS_Query_Message_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
- RNDIS_Query_Complete_t* QUERY_Response = (RNDIS_Query_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
+ RNDIS_Query_Message_t* QUERY_Message = (RNDIS_Query_Message_t*)RNDISInterfaceInfo->Config.MessageBuffer;
+ RNDIS_Query_Complete_t* QUERY_Response = (RNDIS_Query_Complete_t*)RNDISInterfaceInfo->Config.MessageBuffer;
uint32_t Query_Oid = CPU_TO_LE32(QUERY_Message->Oid);
- void* QueryData = &RNDISInterfaceInfo->State.RNDISMessageBuffer[sizeof(RNDIS_Message_Header_t) +
- le32_to_cpu(QUERY_Message->InformationBufferOffset)];
- void* ResponseData = &RNDISInterfaceInfo->State.RNDISMessageBuffer[sizeof(RNDIS_Query_Complete_t)];
+ void* QueryData = &RNDISInterfaceInfo->Config.MessageBuffer[sizeof(RNDIS_Message_Header_t) +
+ le32_to_cpu(QUERY_Message->InformationBufferOffset)];
+ void* ResponseData = &RNDISInterfaceInfo->Config.MessageBuffer[sizeof(RNDIS_Query_Complete_t)];
uint16_t ResponseSize;
QUERY_Response->MessageType = CPU_TO_LE32(REMOTE_NDIS_QUERY_CMPLT);
case REMOTE_NDIS_SET_MSG:
RNDISInterfaceInfo->State.ResponseReady = true;
- RNDIS_Set_Message_t* SET_Message = (RNDIS_Set_Message_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
- RNDIS_Set_Complete_t* SET_Response = (RNDIS_Set_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
+ RNDIS_Set_Message_t* SET_Message = (RNDIS_Set_Message_t*)RNDISInterfaceInfo->Config.MessageBuffer;
+ RNDIS_Set_Complete_t* SET_Response = (RNDIS_Set_Complete_t*)RNDISInterfaceInfo->Config.MessageBuffer;
uint32_t SET_Oid = le32_to_cpu(SET_Message->Oid);
SET_Response->MessageType = CPU_TO_LE32(REMOTE_NDIS_SET_CMPLT);
SET_Response->MessageLength = CPU_TO_LE32(sizeof(RNDIS_Set_Complete_t));
SET_Response->RequestId = SET_Message->RequestId;
- void* SetData = &RNDISInterfaceInfo->State.RNDISMessageBuffer[sizeof(RNDIS_Message_Header_t) +
+ void* SetData = &RNDISInterfaceInfo->Config.MessageBuffer[sizeof(RNDIS_Message_Header_t) +
le32_to_cpu(SET_Message->InformationBufferOffset)];
SET_Response->Status = RNDIS_Device_ProcessNDISSet(RNDISInterfaceInfo, SET_Oid, SetData,
case REMOTE_NDIS_RESET_MSG:
RNDISInterfaceInfo->State.ResponseReady = true;
- RNDIS_Reset_Complete_t* RESET_Response = (RNDIS_Reset_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
+ RNDIS_Reset_Complete_t* RESET_Response = (RNDIS_Reset_Complete_t*)RNDISInterfaceInfo->Config.MessageBuffer;
RESET_Response->MessageType = CPU_TO_LE32(REMOTE_NDIS_RESET_CMPLT);
RESET_Response->MessageLength = CPU_TO_LE32(sizeof(RNDIS_Reset_Complete_t));
RNDISInterfaceInfo->State.ResponseReady = true;
RNDIS_KeepAlive_Message_t* KEEPALIVE_Message =
- (RNDIS_KeepAlive_Message_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
+ (RNDIS_KeepAlive_Message_t*)RNDISInterfaceInfo->Config.MessageBuffer;
RNDIS_KeepAlive_Complete_t* KEEPALIVE_Response =
- (RNDIS_KeepAlive_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
+ (RNDIS_KeepAlive_Complete_t*)RNDISInterfaceInfo->Config.MessageBuffer;
KEEPALIVE_Response->MessageType = CPU_TO_LE32(REMOTE_NDIS_KEEPALIVE_CMPLT);
KEEPALIVE_Response->MessageLength = CPU_TO_LE32(sizeof(RNDIS_KeepAlive_Complete_t));
*ResponseSize = sizeof(uint32_t);
/* Indicate maximum overall buffer (Ethernet frame and RNDIS header) the adapter can handle */
- *((uint32_t*)ResponseData) = CPU_TO_LE32(RNDIS_MESSAGE_BUFFER_SIZE + ETHERNET_FRAME_SIZE_MAX);
+ *((uint32_t*)ResponseData) = CPU_TO_LE32(RNDISInterfaceInfo->Config.MessageBufferLength + ETHERNET_FRAME_SIZE_MAX);
return true;
default:
char* AdapterVendorDescription; /**< String description of the adapter vendor. */
MAC_Address_t AdapterMACAddress; /**< MAC address of the adapter. */
+
+ uint8_t* MessageBuffer; /**< Buffer where RNDIS messages can be stored by the internal driver. This
+ * should be at least 132 bytes in length for minimal functionality. */
+ uint16_t MessageBufferLength; /**< Length in bytes of the \ref MessageBuffer RNDIS buffer. */
} Config; /**< Config data for the USB class interface within the device. All elements in this section
* <b>must</b> be set or the interface will fail to enumerate and operate correctly.
*/
struct
{
- uint8_t RNDISMessageBuffer[RNDIS_MESSAGE_BUFFER_SIZE]; /**< Buffer to hold RNDIS messages to and from the host,
- * managed by the class driver.
- */
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. */
/* Private Interface - For use in library only: */
#if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define RNDIS_DEVICE_MIN_MESSAGE_BUFFER_LENGTH sizeof(AdapterSupportedOIDList) + sizeof(RNDIS_Query_Complete_t)
+
/* Function Prototypes: */
#if defined(__INCLUDE_FROM_RNDIS_DEVICE_C)
static void RNDIS_Device_ProcessRNDISControlMessage(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)