3      Copyright (C) Dean Camera, 2010. 
   5   dean [at] fourwalledcubicle [dot] com 
   6       www.fourwalledcubicle.com 
  10   Copyright 2010  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* Buffer
, uint16_t Length
) 
  52         USB_ControlRequest 
= (USB_Request_Header_t
) 
  54                         .bmRequestType 
= (REQDIR_HOSTTODEVICE 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
  55                         .bRequest      
= REQ_SendEncapsulatedCommand
, 
  61         /* Select the control pipe for the request transfer */ 
  62         Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
  64         return USB_Host_SendControlRequest(Buffer
); 
  67 /** Function to receive the given encapsulated RNDIS response from the device. 
  69  *  \param[out] Buffer  Destination command data buffer to write read data from the device to 
  70  *  \param[in] Length   Number of bytes to read 
  72  *  \return A value from the USB_Host_SendControlErrorCodes_t enum 
  74 uint8_t RNDIS_GetEncapsulatedResponse(void* Buffer
, uint16_t Length
) 
  76         USB_ControlRequest 
= (USB_Request_Header_t
) 
  78                         .bmRequestType 
= (REQDIR_DEVICETOHOST 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
  79                         .bRequest      
= REQ_GetEncapsulatedResponse
, 
  85         /* Select the control pipe for the request transfer */ 
  86         Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
  88         return USB_Host_SendControlRequest(Buffer
); 
  91 /** Sends a RNDIS KEEPALIVE command to the device, to ensure that it does not enter standby mode after periods 
  94  *  \return A value from the USB_Host_SendControlErrorCodes_t enum or RNDIS_COMMAND_FAILED if the device returned a 
  95  *          logical command failure 
  97 uint8_t RNDIS_SendKeepAlive(void) 
 101         RNDIS_KeepAlive_Message_t  KeepAliveMessage
; 
 102         RNDIS_KeepAlive_Complete_t KeepAliveMessageResponse
; 
 104         KeepAliveMessage
.MessageType     
= REMOTE_NDIS_KEEPALIVE_MSG
; 
 105         KeepAliveMessage
.MessageLength   
= sizeof(RNDIS_KeepAlive_Message_t
); 
 106         KeepAliveMessage
.RequestId       
= RequestID
++; 
 108         if ((ErrorCode 
= RNDIS_SendEncapsulatedCommand(&KeepAliveMessage
, 
 109                                                        sizeof(RNDIS_KeepAlive_Message_t
))) != HOST_SENDCONTROL_Successful
) 
 114         if ((ErrorCode 
= RNDIS_GetEncapsulatedResponse(&KeepAliveMessageResponse
, 
 115                                                        sizeof(RNDIS_KeepAlive_Complete_t
))) != HOST_SENDCONTROL_Successful
) 
 120         return HOST_SENDCONTROL_Successful
; 
 123 /** Initializes the attached RNDIS device's RNDIS interface. 
 125  *  \param[in] HostMaxPacketSize  Size of the packet buffer on the host 
 126  *  \param[out] DeviceMaxPacketSize   Pointer to where the packet buffer size of the device is to be stored 
 128  *  \return A value from the USB_Host_SendControlErrorCodes_t enum or RNDIS_COMMAND_FAILED if the device returned a 
 129  *          logical command failure 
 131 uint8_t RNDIS_InitializeDevice(uint16_t HostMaxPacketSize
, uint16_t* DeviceMaxPacketSize
) 
 135         RNDIS_Initialize_Message_t  InitMessage
; 
 136         RNDIS_Initialize_Complete_t InitMessageResponse
; 
 138         InitMessage
.MessageType     
= REMOTE_NDIS_INITIALIZE_MSG
; 
 139         InitMessage
.MessageLength   
= sizeof(RNDIS_Initialize_Message_t
); 
 140         InitMessage
.RequestId       
= RequestID
++; 
 142         InitMessage
.MajorVersion    
= REMOTE_NDIS_VERSION_MAJOR
; 
 143         InitMessage
.MinorVersion    
= REMOTE_NDIS_VERSION_MINOR
; 
 144         InitMessage
.MaxTransferSize 
= HostMaxPacketSize
; 
 146         if ((ErrorCode 
= RNDIS_SendEncapsulatedCommand(&InitMessage
, 
 147                                                        sizeof(RNDIS_Initialize_Message_t
))) != HOST_SENDCONTROL_Successful
) 
 152         if ((ErrorCode 
= RNDIS_GetEncapsulatedResponse(&InitMessageResponse
, 
 153                                                        sizeof(RNDIS_Initialize_Complete_t
))) != HOST_SENDCONTROL_Successful
) 
 158         if (InitMessageResponse
.Status 
!= REMOTE_NDIS_STATUS_SUCCESS
) 
 159           return RNDIS_COMMAND_FAILED
; 
 161         *DeviceMaxPacketSize 
= InitMessageResponse
.MaxTransferSize
; 
 163         return HOST_SENDCONTROL_Successful
; 
 166 /** Sets a given RNDIS property of an attached RNDIS device. 
 168  *  \param[in] Oid  OID number of the parameter to set 
 169  *  \param[in] Buffer  Pointer to where the property data is to be sourced from 
 170  *  \param[in] Length  Length in bytes of the property data to sent to the device 
 172  *  \return A value from the USB_Host_SendControlErrorCodes_t enum or RNDIS_COMMAND_FAILED if the device returned a 
 173  *          logical command failure 
 175 uint8_t RNDIS_SetRNDISProperty(uint32_t Oid
, void* Buffer
, uint16_t Length
) 
 181                 RNDIS_Set_Message_t SetMessage
; 
 182                 uint8_t             ContigiousBuffer
[Length
]; 
 185         RNDIS_Set_Complete_t SetMessageResponse
; 
 187         SetMessageData
.SetMessage
.MessageType    
= REMOTE_NDIS_SET_MSG
; 
 188         SetMessageData
.SetMessage
.MessageLength  
= sizeof(RNDIS_Set_Message_t
) + Length
; 
 189         SetMessageData
.SetMessage
.RequestId      
= RequestID
++; 
 191         SetMessageData
.SetMessage
.Oid            
= Oid
; 
 192         SetMessageData
.SetMessage
.InformationBufferLength 
= Length
; 
 193         SetMessageData
.SetMessage
.InformationBufferOffset 
= (sizeof(RNDIS_Set_Message_t
) - sizeof(RNDIS_Message_Header_t
)); 
 194         SetMessageData
.SetMessage
.DeviceVcHandle 
= 0; 
 196         memcpy(&SetMessageData
.ContigiousBuffer
, Buffer
, Length
); 
 198         if ((ErrorCode 
= RNDIS_SendEncapsulatedCommand(&SetMessageData
, 
 199                                                        SetMessageData
.SetMessage
.MessageLength
)) != HOST_SENDCONTROL_Successful
) 
 204         if ((ErrorCode 
= RNDIS_GetEncapsulatedResponse(&SetMessageResponse
, 
 205                                                        sizeof(RNDIS_Set_Complete_t
))) != HOST_SENDCONTROL_Successful
) 
 210         if (SetMessageResponse
.Status 
!= REMOTE_NDIS_STATUS_SUCCESS
) 
 211           return RNDIS_COMMAND_FAILED
; 
 213         return HOST_SENDCONTROL_Successful
; 
 216 /** Gets a given RNDIS property of an attached RNDIS device. 
 218  *  \param[in] Oid  OID number of the parameter to get 
 219  *  \param[in] Buffer  Pointer to where the property data is to be written to 
 220  *  \param[in] MaxLength  Length in bytes of the destination buffer size 
 222  *  \return A value from the USB_Host_SendControlErrorCodes_t enum or RNDIS_COMMAND_FAILED if the device returned a 
 223  *          logical command failure 
 225 uint8_t RNDIS_QueryRNDISProperty(uint32_t Oid
, void* Buffer
, uint16_t MaxLength
) 
 229         RNDIS_Query_Message_t QueryMessage
; 
 233                 RNDIS_Query_Complete_t QueryMessageResponse
; 
 234                 uint8_t                ContigiousBuffer
[MaxLength
]; 
 235         } QueryMessageResponseData
; 
 237         QueryMessage
.MessageType    
= REMOTE_NDIS_QUERY_MSG
; 
 238         QueryMessage
.MessageLength  
= sizeof(RNDIS_Query_Message_t
); 
 239         QueryMessage
.RequestId      
= RequestID
++; 
 241         QueryMessage
.Oid            
= Oid
; 
 242         QueryMessage
.InformationBufferLength 
= 0; 
 243         QueryMessage
.InformationBufferOffset 
= 0; 
 244         QueryMessage
.DeviceVcHandle 
= 0; 
 246         if ((ErrorCode 
= RNDIS_SendEncapsulatedCommand(&QueryMessage
, 
 247                                                        sizeof(RNDIS_Query_Message_t
))) != HOST_SENDCONTROL_Successful
) 
 252         if ((ErrorCode 
= RNDIS_GetEncapsulatedResponse(&QueryMessageResponseData
, 
 253                                                        sizeof(QueryMessageResponseData
))) != HOST_SENDCONTROL_Successful
) 
 258         if (QueryMessageResponseData
.QueryMessageResponse
.Status 
!= REMOTE_NDIS_STATUS_SUCCESS
) 
 259           return RNDIS_COMMAND_FAILED
; 
 261         memcpy(Buffer
, &QueryMessageResponseData
.ContigiousBuffer
, MaxLength
); 
 263         return HOST_SENDCONTROL_Successful
; 
 266 /** Retrieves the size of a received packet, discarding the remainder of the RNDIS packet header to leave only the 
 267  *  packet contents for processing by the host. 
 269  *  \param[out] PacketLength  Size of the packet currently in the pipe 
 271  *  \return A value from the Pipe_Stream_RW_ErrorCodes_t enum 
 273 uint8_t RNDIS_GetPacketLength(uint16_t* PacketLength
) 
 277         Pipe_SelectPipe(RNDIS_DATAPIPE_IN
); 
 278         Pipe_SetPipeToken(PIPE_TOKEN_IN
); 
 281         if (!(Pipe_IsReadWriteAllowed())) 
 285                 return PIPE_RWSTREAM_NoError
; 
 288         RNDIS_Packet_Message_t DeviceMessage
; 
 290         if ((ErrorCode 
= Pipe_Read_Stream_LE(&DeviceMessage
, sizeof(RNDIS_Packet_Message_t
))) != PIPE_RWSTREAM_NoError
) 
 295         *PacketLength 
= (uint16_t)DeviceMessage
.DataLength
; 
 297         Pipe_Discard_Stream(DeviceMessage
.DataOffset 
- (sizeof(RNDIS_Packet_Message_t
) - sizeof(RNDIS_Message_Header_t
))); 
 301         return PIPE_RWSTREAM_NoError
;