3      Copyright (C) Dean Camera, 2012. 
   5   dean [at] fourwalledcubicle [dot] com 
  10   Copyright 2012  Dean Camera (dean [at] fourwalledcubicle [dot] com) 
  12   Permission to use, copy, modify, distribute, and sell this 
  13   software and its documentation for any purpose is hereby granted 
  14   without fee, provided that the above copyright notice appear in 
  15   all copies and that both that the copyright notice and this 
  16   permission notice and warranty disclaimer appear in supporting 
  17   documentation, and that the name of the author not be used in 
  18   advertising or publicity pertaining to distribution of the 
  19   software without specific, written prior permission. 
  21   The author disclaim all warranties with regard to this 
  22   software, including all implied warranties of merchantability 
  23   and fitness.  In no event shall the author be liable for any 
  24   special, indirect or consequential damages or any damages 
  25   whatsoever resulting from loss of use, data or profits, whether 
  26   in an action of contract, negligence or other tortious action, 
  27   arising out of or in connection with the use or performance of 
  33  *  RNDIS Device commands, to issue RNDIS commands to the device for 
  34  *  the control and data transfer between the host and RNDIS device. 
  37 #include "RNDISCommands.h" 
  39 /** Current RNDIS Request ID, for associating sent commands with received data */ 
  40 uint32_t RequestID 
= 0; 
  43 /** Function to send the given encapsulated RNDIS command to the device. 
  45  *  \param[in] Buffer  Source command data buffer to send to the device 
  46  *  \param[in] Length   Number of bytes to send 
  48  *  \return A value from the USB_Host_SendControlErrorCodes_t enum 
  50 uint8_t RNDIS_SendEncapsulatedCommand(void* const Buffer
, 
  51                                       const uint16_t Length
) 
  53         USB_ControlRequest 
= (USB_Request_Header_t
) 
  55                         .bmRequestType 
= (REQDIR_HOSTTODEVICE 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
  56                         .bRequest      
= RNDIS_REQ_SendEncapsulatedCommand
, 
  62         /* Select the control pipe for the request transfer */ 
  63         Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
  65         return USB_Host_SendControlRequest(Buffer
); 
  68 /** Function to receive the given encapsulated RNDIS response from the device. 
  70  *  \param[out] Buffer  Destination command data buffer to write read data from the device to 
  71  *  \param[in] Length   Number of bytes to read 
  73  *  \return A value from the USB_Host_SendControlErrorCodes_t enum 
  75 uint8_t RNDIS_GetEncapsulatedResponse(void* const Buffer
, 
  76                                       const uint16_t Length
) 
  78         USB_ControlRequest 
= (USB_Request_Header_t
) 
  80                         .bmRequestType 
= (REQDIR_DEVICETOHOST 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
  81                         .bRequest      
= RNDIS_REQ_GetEncapsulatedResponse
, 
  87         /* Select the control pipe for the request transfer */ 
  88         Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
  90         return USB_Host_SendControlRequest(Buffer
); 
  93 /** Sends a RNDIS KEEPALIVE command to the device, to ensure that it does not enter standby mode after periods 
  96  *  \return A value from the USB_Host_SendControlErrorCodes_t enum or RNDIS_COMMAND_FAILED if the device returned a 
  97  *          logical command failure 
  99 uint8_t RNDIS_SendKeepAlive(void) 
 103         RNDIS_KeepAlive_Message_t  KeepAliveMessage
; 
 104         RNDIS_KeepAlive_Complete_t KeepAliveMessageResponse
; 
 106         KeepAliveMessage
.MessageType     
= REMOTE_NDIS_KEEPALIVE_MSG
; 
 107         KeepAliveMessage
.MessageLength   
= sizeof(RNDIS_KeepAlive_Message_t
); 
 108         KeepAliveMessage
.RequestId       
= RequestID
++; 
 110         if ((ErrorCode 
= RNDIS_SendEncapsulatedCommand(&KeepAliveMessage
, 
 111                                                        sizeof(RNDIS_KeepAlive_Message_t
))) != HOST_SENDCONTROL_Successful
) 
 116         if ((ErrorCode 
= RNDIS_GetEncapsulatedResponse(&KeepAliveMessageResponse
, 
 117                                                        sizeof(RNDIS_KeepAlive_Complete_t
))) != HOST_SENDCONTROL_Successful
) 
 122         return HOST_SENDCONTROL_Successful
; 
 125 /** Initializes the attached RNDIS device's RNDIS interface. 
 127  *  \param[in] HostMaxPacketSize  Size of the packet buffer on the host 
 128  *  \param[out] DeviceMaxPacketSize   Pointer to where the packet buffer size of the device is to be stored 
 130  *  \return A value from the USB_Host_SendControlErrorCodes_t enum or RNDIS_COMMAND_FAILED if the device returned a 
 131  *          logical command failure 
 133 uint8_t RNDIS_InitializeDevice(const uint16_t HostMaxPacketSize
, 
 134                                uint16_t* const DeviceMaxPacketSize
) 
 138         RNDIS_Initialize_Message_t  InitMessage
; 
 139         RNDIS_Initialize_Complete_t InitMessageResponse
; 
 141         InitMessage
.MessageType     
= REMOTE_NDIS_INITIALIZE_MSG
; 
 142         InitMessage
.MessageLength   
= sizeof(RNDIS_Initialize_Message_t
); 
 143         InitMessage
.RequestId       
= RequestID
++; 
 145         InitMessage
.MajorVersion    
= REMOTE_NDIS_VERSION_MAJOR
; 
 146         InitMessage
.MinorVersion    
= REMOTE_NDIS_VERSION_MINOR
; 
 147         InitMessage
.MaxTransferSize 
= HostMaxPacketSize
; 
 149         if ((ErrorCode 
= RNDIS_SendEncapsulatedCommand(&InitMessage
, 
 150                                                        sizeof(RNDIS_Initialize_Message_t
))) != HOST_SENDCONTROL_Successful
) 
 155         if ((ErrorCode 
= RNDIS_GetEncapsulatedResponse(&InitMessageResponse
, 
 156                                                        sizeof(RNDIS_Initialize_Complete_t
))) != HOST_SENDCONTROL_Successful
) 
 161         if (InitMessageResponse
.Status 
!= REMOTE_NDIS_STATUS_SUCCESS
) 
 162           return RNDIS_COMMAND_FAILED
; 
 164         *DeviceMaxPacketSize 
= InitMessageResponse
.MaxTransferSize
; 
 166         return HOST_SENDCONTROL_Successful
; 
 169 /** Sets a given RNDIS property of an attached RNDIS device. 
 171  *  \param[in] Oid  OID number of the parameter to set 
 172  *  \param[in] Buffer  Pointer to where the property data is to be sourced from 
 173  *  \param[in] Length  Length in bytes of the property data to sent to the device 
 175  *  \return A value from the USB_Host_SendControlErrorCodes_t enum or RNDIS_COMMAND_FAILED if the device returned a 
 176  *          logical command failure 
 178 uint8_t RNDIS_SetRNDISProperty(const uint32_t Oid
, 
 180                                const uint16_t Length
) 
 186                 RNDIS_Set_Message_t SetMessage
; 
 187                 uint8_t             ContiguousBuffer
[Length
]; 
 190         RNDIS_Set_Complete_t SetMessageResponse
; 
 192         SetMessageData
.SetMessage
.MessageType    
= REMOTE_NDIS_SET_MSG
; 
 193         SetMessageData
.SetMessage
.MessageLength  
= sizeof(RNDIS_Set_Message_t
) + Length
; 
 194         SetMessageData
.SetMessage
.RequestId      
= RequestID
++; 
 196         SetMessageData
.SetMessage
.Oid            
= Oid
; 
 197         SetMessageData
.SetMessage
.InformationBufferLength 
= Length
; 
 198         SetMessageData
.SetMessage
.InformationBufferOffset 
= (sizeof(RNDIS_Set_Message_t
) - sizeof(RNDIS_Message_Header_t
)); 
 199         SetMessageData
.SetMessage
.DeviceVcHandle 
= 0; 
 201         memcpy(&SetMessageData
.ContiguousBuffer
, Buffer
, Length
); 
 203         if ((ErrorCode 
= RNDIS_SendEncapsulatedCommand(&SetMessageData
, 
 204                                                        SetMessageData
.SetMessage
.MessageLength
)) != HOST_SENDCONTROL_Successful
) 
 209         if ((ErrorCode 
= RNDIS_GetEncapsulatedResponse(&SetMessageResponse
, 
 210                                                        sizeof(RNDIS_Set_Complete_t
))) != HOST_SENDCONTROL_Successful
) 
 215         if (SetMessageResponse
.Status 
!= REMOTE_NDIS_STATUS_SUCCESS
) 
 216           return RNDIS_COMMAND_FAILED
; 
 218         return HOST_SENDCONTROL_Successful
; 
 221 /** Gets a given RNDIS property of an attached RNDIS device. 
 223  *  \param[in] Oid  OID number of the parameter to get 
 224  *  \param[in] Buffer  Pointer to where the property data is to be written to 
 225  *  \param[in] MaxLength  Length in bytes of the destination buffer size 
 227  *  \return A value from the USB_Host_SendControlErrorCodes_t enum or RNDIS_COMMAND_FAILED if the device returned a 
 228  *          logical command failure 
 230 uint8_t RNDIS_QueryRNDISProperty(const uint32_t Oid
, 
 232                                  const uint16_t MaxLength
) 
 236         RNDIS_Query_Message_t QueryMessage
; 
 240                 RNDIS_Query_Complete_t QueryMessageResponse
; 
 241                 uint8_t                ContiguousBuffer
[MaxLength
]; 
 242         } QueryMessageResponseData
; 
 244         QueryMessage
.MessageType    
= REMOTE_NDIS_QUERY_MSG
; 
 245         QueryMessage
.MessageLength  
= sizeof(RNDIS_Query_Message_t
); 
 246         QueryMessage
.RequestId      
= RequestID
++; 
 248         QueryMessage
.Oid            
= Oid
; 
 249         QueryMessage
.InformationBufferLength 
= 0; 
 250         QueryMessage
.InformationBufferOffset 
= 0; 
 251         QueryMessage
.DeviceVcHandle 
= 0; 
 253         if ((ErrorCode 
= RNDIS_SendEncapsulatedCommand(&QueryMessage
, 
 254                                                        sizeof(RNDIS_Query_Message_t
))) != HOST_SENDCONTROL_Successful
) 
 259         if ((ErrorCode 
= RNDIS_GetEncapsulatedResponse(&QueryMessageResponseData
, 
 260                                                        sizeof(QueryMessageResponseData
))) != HOST_SENDCONTROL_Successful
) 
 265         if (QueryMessageResponseData
.QueryMessageResponse
.Status 
!= REMOTE_NDIS_STATUS_SUCCESS
) 
 266           return RNDIS_COMMAND_FAILED
; 
 268         memcpy(Buffer
, &QueryMessageResponseData
.ContiguousBuffer
, MaxLength
); 
 270         return HOST_SENDCONTROL_Successful
; 
 273 /** Retrieves the size of a received packet, discarding the remainder of the RNDIS packet header to leave only the 
 274  *  packet contents for processing by the host. 
 276  *  \param[out] PacketLength  Size of the packet currently in the pipe 
 278  *  \return A value from the Pipe_Stream_RW_ErrorCodes_t enum 
 280 uint8_t RNDIS_GetPacketLength(uint16_t* const PacketLength
) 
 284         Pipe_SelectPipe(RNDIS_DATA_IN_PIPE
); 
 285         Pipe_SetPipeToken(PIPE_TOKEN_IN
); 
 288         if (!(Pipe_IsReadWriteAllowed())) 
 292                 return PIPE_RWSTREAM_NoError
; 
 295         RNDIS_Packet_Message_t DeviceMessage
; 
 297         if ((ErrorCode 
= Pipe_Read_Stream_LE(&DeviceMessage
, sizeof(RNDIS_Packet_Message_t
), NULL
)) != PIPE_RWSTREAM_NoError
) 
 302         *PacketLength 
= (uint16_t)DeviceMessage
.DataLength
; 
 304         Pipe_Discard_Stream(DeviceMessage
.DataOffset 
- (sizeof(RNDIS_Packet_Message_t
) - sizeof(RNDIS_Message_Header_t
)), 
 309         return PIPE_RWSTREAM_NoError
;