-  Permission to use, copy, modify, distribute, and sell this 
+  Permission to use, copy, modify, distribute, and sell this
-  permission notice and warranty disclaimer appear in supporting 
-  documentation, and that the name of the author not be used in 
-  advertising or publicity pertaining to distribution of the 
+  permission notice and warranty disclaimer appear in supporting
+  documentation, and that the name of the author not be used in
+  advertising or publicity pertaining to distribution of the
   software, including all implied warranties of merchantability
   and fitness.  In no event shall the author be liable for any
   special, indirect or consequential damages or any damages
   software, including all implied warranties of merchantability
   and fitness.  In no event shall the author be liable for any
   special, indirect or consequential damages or any damages
  *  RNDIS command handler functions. This handles RNDIS commands according to
  *  the Microsoft RNDIS specification, creating a USB Ethernet network adapter.
  */
  *  RNDIS command handler functions. This handles RNDIS commands according to
  *  the Microsoft RNDIS specification, creating a USB Ethernet network adapter.
  */
 #define  INCLUDE_FROM_RNDIS_C
 #include "RNDIS.h"
 
 /** Physical MAC address of the network adapter, which becomes the MAC address of the host for packets sent to the adapter. */
 #define  INCLUDE_FROM_RNDIS_C
 #include "RNDIS.h"
 
 /** Physical MAC address of the network adapter, which becomes the MAC address of the host for packets sent to the adapter. */
 
 /** Vendor description of the adapter. This is overridden by the INF file required to install the appropriate RNDIS drivers for
  *  the device, but may still be used by the OS in some circumstances.
  */
 
 /** Vendor description of the adapter. This is overridden by the INF file required to install the appropriate RNDIS drivers for
  *  the device, but may still be used by the OS in some circumstances.
  */
 
 /** List of RNDIS OID commands supported by this adapter. */
 static const uint32_t PROGMEM AdapterSupportedOIDList[]  =
 
 /** List of RNDIS OID commands supported by this adapter. */
 static const uint32_t PROGMEM AdapterSupportedOIDList[]  =
 /** Indicates if a RNDIS message response is ready to be sent back to the host. */
 bool                    ResponseReady               = false;
 
 /** Indicates if a RNDIS message response is ready to be sent back to the host. */
 bool                    ResponseReady               = false;
 
 uint8_t                 CurrRNDISState              = RNDIS_Uninitialized;
 
 /** Current Ethernet packet filter mask. This is non-zero when the adapter is initialized, or zero when disabled. */
 uint8_t                 CurrRNDISState              = RNDIS_Uninitialized;
 
 /** Current Ethernet packet filter mask. This is non-zero when the adapter is initialized, or zero when disabled. */
                        RNDIS_Initialize_Message_t*  INITIALIZE_Message  = (RNDIS_Initialize_Message_t*)&RNDISMessageBuffer;
                        RNDIS_Initialize_Complete_t* INITIALIZE_Response = (RNDIS_Initialize_Complete_t*)&RNDISMessageBuffer;
                        RNDIS_Initialize_Message_t*  INITIALIZE_Message  = (RNDIS_Initialize_Message_t*)&RNDISMessageBuffer;
                        RNDIS_Initialize_Complete_t* INITIALIZE_Response = (RNDIS_Initialize_Complete_t*)&RNDISMessageBuffer;
                        INITIALIZE_Response->MessageType           = REMOTE_NDIS_INITIALIZE_CMPLT;
                        INITIALIZE_Response->MessageLength         = sizeof(RNDIS_Initialize_Complete_t);
                        INITIALIZE_Response->RequestId             = INITIALIZE_Message->RequestId;
                        INITIALIZE_Response->Status                = REMOTE_NDIS_STATUS_SUCCESS;
                        INITIALIZE_Response->MessageType           = REMOTE_NDIS_INITIALIZE_CMPLT;
                        INITIALIZE_Response->MessageLength         = sizeof(RNDIS_Initialize_Complete_t);
                        INITIALIZE_Response->RequestId             = INITIALIZE_Message->RequestId;
                        INITIALIZE_Response->Status                = REMOTE_NDIS_STATUS_SUCCESS;
                        INITIALIZE_Response->DeviceFlags           = REMOTE_NDIS_DF_CONNECTIONLESS;
                        INITIALIZE_Response->Medium                = REMOTE_NDIS_MEDIUM_802_3;
                        INITIALIZE_Response->MaxPacketsPerTransfer = 1;
                        INITIALIZE_Response->DeviceFlags           = REMOTE_NDIS_DF_CONNECTIONLESS;
                        INITIALIZE_Response->Medium                = REMOTE_NDIS_MEDIUM_802_3;
                        INITIALIZE_Response->MaxPacketsPerTransfer = 1;
                        INITIALIZE_Response->PacketAlignmentFactor = 0;
                        INITIALIZE_Response->AFListOffset          = 0;
                        INITIALIZE_Response->AFListSize            = 0;
                        INITIALIZE_Response->PacketAlignmentFactor = 0;
                        INITIALIZE_Response->AFListOffset          = 0;
                        INITIALIZE_Response->AFListSize            = 0;
                        break;
                case REMOTE_NDIS_HALT_MSG:
                        /* Halt the adapter, reset the adapter state - note that no response should be returned when completed */
                        break;
                case REMOTE_NDIS_HALT_MSG:
                        /* Halt the adapter, reset the adapter state - note that no response should be returned when completed */
                        RNDIS_Query_Message_t*  QUERY_Message  = (RNDIS_Query_Message_t*)&RNDISMessageBuffer;
                        RNDIS_Query_Complete_t* QUERY_Response = (RNDIS_Query_Complete_t*)&RNDISMessageBuffer;
                        uint32_t                Query_Oid      = QUERY_Message->Oid;
                        RNDIS_Query_Message_t*  QUERY_Message  = (RNDIS_Query_Message_t*)&RNDISMessageBuffer;
                        RNDIS_Query_Complete_t* QUERY_Response = (RNDIS_Query_Complete_t*)&RNDISMessageBuffer;
                        uint32_t                Query_Oid      = QUERY_Message->Oid;
                        void*     QueryData                 = &RNDISMessageBuffer[sizeof(RNDIS_Message_Header_t) +
                                                                                  QUERY_Message->InformationBufferOffset];
                        void*     QueryData                 = &RNDISMessageBuffer[sizeof(RNDIS_Message_Header_t) +
                                                                                  QUERY_Message->InformationBufferOffset];
                        uint16_t  ResponseSize;
 
                        QUERY_Response->MessageType         = REMOTE_NDIS_QUERY_CMPLT;
                        QUERY_Response->MessageLength       = sizeof(RNDIS_Query_Complete_t);
                        uint16_t  ResponseSize;
 
                        QUERY_Response->MessageType         = REMOTE_NDIS_QUERY_CMPLT;
                        QUERY_Response->MessageLength       = sizeof(RNDIS_Query_Complete_t);
                        if (ProcessNDISQuery(Query_Oid, QueryData, QUERY_Message->InformationBufferLength,
                                             ResponseData, &ResponseSize))
                        {
                                QUERY_Response->Status                  = REMOTE_NDIS_STATUS_SUCCESS;
                                QUERY_Response->MessageLength          += ResponseSize;
                        if (ProcessNDISQuery(Query_Oid, QueryData, QUERY_Message->InformationBufferLength,
                                             ResponseData, &ResponseSize))
                        {
                                QUERY_Response->Status                  = REMOTE_NDIS_STATUS_SUCCESS;
                                QUERY_Response->MessageLength          += ResponseSize;
                                QUERY_Response->InformationBufferLength = ResponseSize;
                                QUERY_Response->InformationBufferOffset = (sizeof(RNDIS_Query_Complete_t) - sizeof(RNDIS_Message_Header_t));
                        }
                        else
                                QUERY_Response->InformationBufferLength = ResponseSize;
                                QUERY_Response->InformationBufferOffset = (sizeof(RNDIS_Query_Complete_t) - sizeof(RNDIS_Message_Header_t));
                        }
                        else
                                QUERY_Response->Status                  = REMOTE_NDIS_STATUS_NOT_SUPPORTED;
 
                                QUERY_Response->InformationBufferLength = 0;
                                QUERY_Response->InformationBufferOffset = 0;
                        }
                                QUERY_Response->Status                  = REMOTE_NDIS_STATUS_NOT_SUPPORTED;
 
                                QUERY_Response->InformationBufferLength = 0;
                                QUERY_Response->InformationBufferOffset = 0;
                        }
                        break;
                case REMOTE_NDIS_SET_MSG:
                        /* Request to set a parameter of the adapter, specified as an OID token */
                        break;
                case REMOTE_NDIS_SET_MSG:
                        /* Request to set a parameter of the adapter, specified as an OID token */
                        RNDIS_Set_Message_t*  SET_Message  = (RNDIS_Set_Message_t*)&RNDISMessageBuffer;
                        RNDIS_Set_Complete_t* SET_Response = (RNDIS_Set_Complete_t*)&RNDISMessageBuffer;
                        uint32_t              SET_Oid      = SET_Message->Oid;
                        RNDIS_Set_Message_t*  SET_Message  = (RNDIS_Set_Message_t*)&RNDISMessageBuffer;
                        RNDIS_Set_Complete_t* SET_Response = (RNDIS_Set_Complete_t*)&RNDISMessageBuffer;
                        uint32_t              SET_Oid      = SET_Message->Oid;
 
                        void* SetData                   = &RNDISMessageBuffer[sizeof(RNDIS_Message_Header_t) +
                                                                              SET_Message->InformationBufferOffset];
 
                        void* SetData                   = &RNDISMessageBuffer[sizeof(RNDIS_Message_Header_t) +
                                                                              SET_Message->InformationBufferOffset];
                        if (ProcessNDISSet(SET_Oid, SetData, SET_Message->InformationBufferLength))
                          SET_Response->Status        = REMOTE_NDIS_STATUS_SUCCESS;
                        else
                        if (ProcessNDISSet(SET_Oid, SetData, SET_Message->InformationBufferLength))
                          SET_Response->Status        = REMOTE_NDIS_STATUS_SUCCESS;
                        else
                        RNDIS_Reset_Complete_t* RESET_Response = (RNDIS_Reset_Complete_t*)&RNDISMessageBuffer;
 
                        RESET_Response->MessageType         = REMOTE_NDIS_RESET_CMPLT;
                        RNDIS_Reset_Complete_t* RESET_Response = (RNDIS_Reset_Complete_t*)&RNDISMessageBuffer;
 
                        RESET_Response->MessageType         = REMOTE_NDIS_RESET_CMPLT;
                        break;
                case REMOTE_NDIS_KEEPALIVE_MSG:
                        /* Keep alive message sent to the adapter every 5 seconds when idle to ensure it is still responding */
                        break;
                case REMOTE_NDIS_KEEPALIVE_MSG:
                        /* Keep alive message sent to the adapter every 5 seconds when idle to ensure it is still responding */
                        RNDIS_KeepAlive_Message_t*  KEEPALIVE_Message  = (RNDIS_KeepAlive_Message_t*)&RNDISMessageBuffer;
                        RNDIS_KeepAlive_Complete_t* KEEPALIVE_Response = (RNDIS_KeepAlive_Complete_t*)&RNDISMessageBuffer;
 
                        RNDIS_KeepAlive_Message_t*  KEEPALIVE_Message  = (RNDIS_KeepAlive_Message_t*)&RNDISMessageBuffer;
                        RNDIS_KeepAlive_Complete_t* KEEPALIVE_Response = (RNDIS_KeepAlive_Complete_t*)&RNDISMessageBuffer;
 
                        KEEPALIVE_Response->MessageLength   = sizeof(RNDIS_KeepAlive_Complete_t);
                        KEEPALIVE_Response->RequestId       = KEEPALIVE_Message->RequestId;
                        KEEPALIVE_Response->Status          = REMOTE_NDIS_STATUS_SUCCESS;
                        KEEPALIVE_Response->MessageLength   = sizeof(RNDIS_KeepAlive_Complete_t);
                        KEEPALIVE_Response->RequestId       = KEEPALIVE_Message->RequestId;
                        KEEPALIVE_Response->Status          = REMOTE_NDIS_STATUS_SUCCESS;
  *  \param[out] ResponseData  Pointer to the start of the query response inside the RNDIS message buffer
  *  \param[out] ResponseSize  Pointer to the size in bytes of the response data being sent to the host
  *
  *  \param[out] ResponseData  Pointer to the start of the query response inside the RNDIS message buffer
  *  \param[out] ResponseSize  Pointer to the size in bytes of the response data being sent to the host
  *
  */
 static bool ProcessNDISQuery(const uint32_t OId, void* QueryData, uint16_t QuerySize,
                              void* ResponseData, uint16_t* ResponseSize)
  */
 static bool ProcessNDISQuery(const uint32_t OId, void* QueryData, uint16_t QuerySize,
                              void* ResponseData, uint16_t* ResponseSize)
                        /* Copy the list of supported NDIS OID tokens to the response buffer */
                        memcpy_P(ResponseData, AdapterSupportedOIDList, sizeof(AdapterSupportedOIDList));
                        /* Copy the list of supported NDIS OID tokens to the response buffer */
                        memcpy_P(ResponseData, AdapterSupportedOIDList, sizeof(AdapterSupportedOIDList));
                        return true;
                case OID_GEN_MEDIA_SUPPORTED:
                case OID_GEN_MEDIA_IN_USE:
                        *ResponseSize = sizeof(uint32_t);
                        return true;
                case OID_GEN_MEDIA_SUPPORTED:
                case OID_GEN_MEDIA_IN_USE:
                        *ResponseSize = sizeof(uint32_t);
                        /* Indicate 802.3 (Ethernet) supported by the adapter */
                        *((uint32_t*)ResponseData) = REMOTE_NDIS_MEDIUM_802_3;
                        /* Indicate 802.3 (Ethernet) supported by the adapter */
                        *((uint32_t*)ResponseData) = REMOTE_NDIS_MEDIUM_802_3;
                        /* Vendor ID 0x0xFFFFFF is reserved for vendors who have not purchased a NDIS VID */
                        *((uint32_t*)ResponseData) = 0x00FFFFFF;
                        /* Vendor ID 0x0xFFFFFF is reserved for vendors who have not purchased a NDIS VID */
                        *((uint32_t*)ResponseData) = 0x00FFFFFF;
                        return true;
                case OID_GEN_MAXIMUM_FRAME_SIZE:
                case OID_GEN_TRANSMIT_BLOCK_SIZE:
                case OID_GEN_RECEIVE_BLOCK_SIZE:
                        *ResponseSize = sizeof(uint32_t);
                        return true;
                case OID_GEN_MAXIMUM_FRAME_SIZE:
                case OID_GEN_TRANSMIT_BLOCK_SIZE:
                case OID_GEN_RECEIVE_BLOCK_SIZE:
                        *ResponseSize = sizeof(uint32_t);
                        /* Indicate that the maximum frame size is the size of the ethernet frame buffer */
                        *((uint32_t*)ResponseData) = ETHERNET_FRAME_SIZE_MAX;
                        /* Indicate that the maximum frame size is the size of the ethernet frame buffer */
                        *((uint32_t*)ResponseData) = ETHERNET_FRAME_SIZE_MAX;
                        /* Copy vendor description string to the response buffer */
                        memcpy_P(ResponseData, AdapterVendorDescription, sizeof(AdapterVendorDescription));
                        /* Copy vendor description string to the response buffer */
                        memcpy_P(ResponseData, AdapterVendorDescription, sizeof(AdapterVendorDescription));
                        /* Always indicate that the adapter is connected to a network */
                        *((uint32_t*)ResponseData) = REMOTE_NDIS_MEDIA_STATE_CONNECTED;
                        /* Always indicate that the adapter is connected to a network */
                        *((uint32_t*)ResponseData) = REMOTE_NDIS_MEDIA_STATE_CONNECTED;
                case OID_802_3_PERMANENT_ADDRESS:
                case OID_802_3_CURRENT_ADDRESS:
                        *ResponseSize = sizeof(MAC_Address_t);
                case OID_802_3_PERMANENT_ADDRESS:
                case OID_802_3_CURRENT_ADDRESS:
                        *ResponseSize = sizeof(MAC_Address_t);
                        /* Copy over the fixed adapter MAC to the response buffer */
                        memcpy_P(ResponseData, &AdapterMACAddress, sizeof(MAC_Address_t));
 
                        return true;
                case OID_802_3_MAXIMUM_LIST_SIZE:
                        *ResponseSize = sizeof(uint32_t);
                        /* Copy over the fixed adapter MAC to the response buffer */
                        memcpy_P(ResponseData, &AdapterMACAddress, sizeof(MAC_Address_t));
 
                        return true;
                case OID_802_3_MAXIMUM_LIST_SIZE:
                        *ResponseSize = sizeof(uint32_t);
                case OID_802_3_XMIT_ONE_COLLISION:
                case OID_802_3_XMIT_MORE_COLLISIONS:
                        *ResponseSize = sizeof(uint32_t);
                case OID_802_3_XMIT_ONE_COLLISION:
                case OID_802_3_XMIT_MORE_COLLISIONS:
                        *ResponseSize = sizeof(uint32_t);
                        /* Indicate maximum overall buffer (Ethernet frame and RNDIS header) the adapter can handle */
                        *((uint32_t*)ResponseData) = (sizeof(RNDISMessageBuffer) + ETHERNET_FRAME_SIZE_MAX);
                        /* Indicate maximum overall buffer (Ethernet frame and RNDIS header) the adapter can handle */
                        *((uint32_t*)ResponseData) = (sizeof(RNDISMessageBuffer) + ETHERNET_FRAME_SIZE_MAX);
  *  as an OID value.
  *
  *  \param[in] OId      OId value of the parameter being set
  *  \param[in] SetData  Pointer to the parameter value in the RNDIS message buffer
  *  \param[in] SetSize  Size in bytes of the parameter value being sent by the host
  *
  *  as an OID value.
  *
  *  \param[in] OId      OId value of the parameter being set
  *  \param[in] SetData  Pointer to the parameter value in the RNDIS message buffer
  *  \param[in] SetSize  Size in bytes of the parameter value being sent by the host
  *
                case OID_GEN_CURRENT_PACKET_FILTER:
                        /* Save the packet filter mask in case the host queries it again later */
                        CurrPacketFilter = *((uint32_t*)SetData);
                case OID_GEN_CURRENT_PACKET_FILTER:
                        /* Save the packet filter mask in case the host queries it again later */
                        CurrPacketFilter = *((uint32_t*)SetData);
                        /* Set the RNDIS state to initialized if the packet filter is non-zero */
                        CurrRNDISState = ((CurrPacketFilter) ? RNDIS_Data_Initialized : RNDIS_Data_Initialized);
                        /* Set the RNDIS state to initialized if the packet filter is non-zero */
                        CurrRNDISState = ((CurrPacketFilter) ? RNDIS_Data_Initialized : RNDIS_Data_Initialized);