3      Copyright (C) Dean Camera, 2011. 
   5   dean [at] fourwalledcubicle [dot] com 
  10   Copyright 2011  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 
  31 #define  __INCLUDE_FROM_USB_DRIVER 
  32 #include "../../HighLevel/USBMode.h" 
  33 #if defined(USB_CAN_BE_HOST) 
  35 #define  __INCLUDE_FROM_RNDIS_DRIVER 
  36 #define  __INCLUDE_FROM_RNDIS_HOST_C 
  39 uint8_t RNDIS_Host_ConfigurePipes(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
, 
  40                                   uint16_t ConfigDescriptorSize
, 
  41                                   void* ConfigDescriptorData
) 
  43         USB_Descriptor_Endpoint_t
*  DataINEndpoint        
= NULL
; 
  44         USB_Descriptor_Endpoint_t
*  DataOUTEndpoint       
= NULL
; 
  45         USB_Descriptor_Endpoint_t
*  NotificationEndpoint  
= NULL
; 
  46         USB_Descriptor_Interface_t
* RNDISControlInterface 
= NULL
; 
  48         memset(&RNDISInterfaceInfo
->State
, 0x00, sizeof(RNDISInterfaceInfo
->State
)); 
  50         if (DESCRIPTOR_TYPE(ConfigDescriptorData
) != DTYPE_Configuration
) 
  51           return RNDIS_ENUMERROR_InvalidConfigDescriptor
; 
  53         RNDISControlInterface 
= DESCRIPTOR_PCAST(ConfigDescriptorData
, USB_Descriptor_Interface_t
); 
  55         while (!(DataINEndpoint
) || !(DataOUTEndpoint
) || !(NotificationEndpoint
)) 
  57                 if (!(RNDISControlInterface
) || 
  58                     USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
, 
  59                                               DCOMP_RNDIS_Host_NextRNDISInterfaceEndpoint
) != DESCRIPTOR_SEARCH_COMP_Found
) 
  61                         if (NotificationEndpoint
) 
  63                                 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
, 
  64                                                                                           DCOMP_RNDIS_Host_NextRNDISDataInterface
) != DESCRIPTOR_SEARCH_COMP_Found
) 
  66                                         return RNDIS_ENUMERROR_NoCompatibleInterfaceFound
; 
  69                                 DataINEndpoint  
= NULL
; 
  70                                 DataOUTEndpoint 
= NULL
; 
  74                                 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
, 
  75                                                                                           DCOMP_RNDIS_Host_NextRNDISControlInterface
) != DESCRIPTOR_SEARCH_COMP_Found
) 
  77                                         return RNDIS_ENUMERROR_NoCompatibleInterfaceFound
; 
  80                                 RNDISControlInterface 
= DESCRIPTOR_PCAST(ConfigDescriptorData
, USB_Descriptor_Interface_t
); 
  82                                 NotificationEndpoint 
= NULL
; 
  88                 USB_Descriptor_Endpoint_t
* EndpointData 
= DESCRIPTOR_PCAST(ConfigDescriptorData
, USB_Descriptor_Endpoint_t
); 
  90                 if (EndpointData
->EndpointAddress 
& ENDPOINT_DESCRIPTOR_DIR_IN
) 
  92                         if ((EndpointData
->Attributes 
& EP_TYPE_MASK
) == EP_TYPE_INTERRUPT
) 
  93                           NotificationEndpoint 
= EndpointData
; 
  95                           DataINEndpoint 
= EndpointData
; 
  99                         DataOUTEndpoint 
= EndpointData
; 
 103         for (uint8_t PipeNum 
= 1; PipeNum 
< PIPE_TOTAL_PIPES
; PipeNum
++) 
 108                 uint8_t  EndpointAddress
; 
 109                 uint8_t  InterruptPeriod
; 
 112                 if (PipeNum 
== RNDISInterfaceInfo
->Config
.DataINPipeNumber
) 
 114                         Size            
= DataINEndpoint
->EndpointSize
; 
 115                         EndpointAddress 
= DataINEndpoint
->EndpointAddress
; 
 116                         Token           
= PIPE_TOKEN_IN
; 
 118                         DoubleBanked    
= RNDISInterfaceInfo
->Config
.DataINPipeDoubleBank
; 
 121                         RNDISInterfaceInfo
->State
.DataINPipeSize 
= DataINEndpoint
->EndpointSize
; 
 123                 else if (PipeNum 
== RNDISInterfaceInfo
->Config
.DataOUTPipeNumber
) 
 125                         Size            
= DataOUTEndpoint
->EndpointSize
; 
 126                         EndpointAddress 
= DataOUTEndpoint
->EndpointAddress
; 
 127                         Token           
= PIPE_TOKEN_OUT
; 
 129                         DoubleBanked    
= RNDISInterfaceInfo
->Config
.DataOUTPipeDoubleBank
; 
 132                         RNDISInterfaceInfo
->State
.DataOUTPipeSize 
= DataOUTEndpoint
->EndpointSize
; 
 134                 else if (PipeNum 
== RNDISInterfaceInfo
->Config
.NotificationPipeNumber
) 
 136                         Size            
= NotificationEndpoint
->EndpointSize
; 
 137                         EndpointAddress 
= NotificationEndpoint
->EndpointAddress
; 
 138                         Token           
= PIPE_TOKEN_IN
; 
 139                         Type            
= EP_TYPE_INTERRUPT
; 
 140                         DoubleBanked    
= RNDISInterfaceInfo
->Config
.NotificationPipeDoubleBank
; 
 141                         InterruptPeriod 
= NotificationEndpoint
->PollingIntervalMS
; 
 143                         RNDISInterfaceInfo
->State
.NotificationPipeSize 
= NotificationEndpoint
->EndpointSize
; 
 150                 if (!(Pipe_ConfigurePipe(PipeNum
, Type
, Token
, EndpointAddress
, Size
, 
 151                                          DoubleBanked ? PIPE_BANK_DOUBLE 
: PIPE_BANK_SINGLE
))) 
 153                         return CDC_ENUMERROR_PipeConfigurationFailed
; 
 157                   Pipe_SetInterruptPeriod(InterruptPeriod
); 
 160         RNDISInterfaceInfo
->State
.ControlInterfaceNumber 
= RNDISControlInterface
->InterfaceNumber
; 
 161         RNDISInterfaceInfo
->State
.IsActive 
= true; 
 163         return RNDIS_ENUMERROR_NoError
; 
 166 static uint8_t DCOMP_RNDIS_Host_NextRNDISControlInterface(void* const CurrentDescriptor
) 
 168         USB_Descriptor_Header_t
* Header 
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Header_t
); 
 170         if (Header
->Type 
== DTYPE_Interface
) 
 172                 USB_Descriptor_Interface_t
* Interface 
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Interface_t
); 
 174                 if ((Interface
->Class    
== CDC_CSCP_CDCClass
)    && 
 175                     (Interface
->SubClass 
== CDC_CSCP_ACMSubclass
) && 
 176                     (Interface
->Protocol 
== CDC_CSCP_VendorSpecificProtocol
)) 
 178                         return DESCRIPTOR_SEARCH_Found
; 
 182         return DESCRIPTOR_SEARCH_NotFound
; 
 185 static uint8_t DCOMP_RNDIS_Host_NextRNDISDataInterface(void* const CurrentDescriptor
) 
 187         USB_Descriptor_Header_t
* Header 
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Header_t
); 
 189         if (Header
->Type 
== DTYPE_Interface
) 
 191                 USB_Descriptor_Interface_t
* Interface 
= DESCRIPTOR_PCAST(CurrentDescriptor
, 
 192                                                                          USB_Descriptor_Interface_t
); 
 194                 if ((Interface
->Class    
== CDC_CSCP_CDCDataClass
)   && 
 195                     (Interface
->SubClass 
== CDC_CSCP_NoDataSubclass
) && 
 196                     (Interface
->Protocol 
== CDC_CSCP_NoDataProtocol
)) 
 198                         return DESCRIPTOR_SEARCH_Found
; 
 202         return DESCRIPTOR_SEARCH_NotFound
; 
 205 static uint8_t DCOMP_RNDIS_Host_NextRNDISInterfaceEndpoint(void* const CurrentDescriptor
) 
 207         USB_Descriptor_Header_t
* Header 
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Header_t
); 
 209         if (Header
->Type 
== DTYPE_Endpoint
) 
 211                 USB_Descriptor_Endpoint_t
* Endpoint 
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Endpoint_t
); 
 213                 uint8_t EndpointType 
= (Endpoint
->Attributes 
& EP_TYPE_MASK
); 
 215                 if (((EndpointType 
== EP_TYPE_BULK
) || (EndpointType 
== EP_TYPE_INTERRUPT
)) && 
 216                     !(Pipe_IsEndpointBound(Endpoint
->EndpointAddress
))) 
 218                         return DESCRIPTOR_SEARCH_Found
; 
 221         else if (Header
->Type 
== DTYPE_Interface
) 
 223                 return DESCRIPTOR_SEARCH_Fail
; 
 226         return DESCRIPTOR_SEARCH_NotFound
; 
 229 static uint8_t RNDIS_SendEncapsulatedCommand(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
, 
 231                                              const uint16_t Length
) 
 233         USB_ControlRequest 
= (USB_Request_Header_t
) 
 235                         .bmRequestType 
= (REQDIR_HOSTTODEVICE 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
 236                         .bRequest      
= RNDIS_REQ_SendEncapsulatedCommand
, 
 238                         .wIndex        
= RNDISInterfaceInfo
->State
.ControlInterfaceNumber
, 
 242         Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
 243         return USB_Host_SendControlRequest(Buffer
); 
 246 static uint8_t RNDIS_GetEncapsulatedResponse(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
, 
 248                                              const uint16_t Length
) 
 250         USB_ControlRequest 
= (USB_Request_Header_t
) 
 252                         .bmRequestType 
= (REQDIR_DEVICETOHOST 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
 253                         .bRequest      
= RNDIS_REQ_GetEncapsulatedResponse
, 
 255                         .wIndex        
= RNDISInterfaceInfo
->State
.ControlInterfaceNumber
, 
 259         Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
 260         return USB_Host_SendControlRequest(Buffer
); 
 263 uint8_t RNDIS_Host_SendKeepAlive(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
) 
 267         RNDIS_KeepAlive_Message_t  KeepAliveMessage
; 
 268         RNDIS_KeepAlive_Complete_t KeepAliveMessageResponse
; 
 270         KeepAliveMessage
.MessageType     
= REMOTE_NDIS_KEEPALIVE_MSG
; 
 271         KeepAliveMessage
.MessageLength   
= sizeof(RNDIS_KeepAlive_Message_t
); 
 272         KeepAliveMessage
.RequestId       
= RNDISInterfaceInfo
->State
.RequestID
++; 
 274         if ((ErrorCode 
= RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo
, &KeepAliveMessage
, 
 275                                                        sizeof(RNDIS_KeepAlive_Message_t
))) != HOST_SENDCONTROL_Successful
) 
 280         if ((ErrorCode 
= RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo
, &KeepAliveMessageResponse
, 
 281                                                        sizeof(RNDIS_KeepAlive_Complete_t
))) != HOST_SENDCONTROL_Successful
) 
 286         return HOST_SENDCONTROL_Successful
; 
 289 uint8_t RNDIS_Host_InitializeDevice(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
) 
 293         RNDIS_Initialize_Message_t  InitMessage
; 
 294         RNDIS_Initialize_Complete_t InitMessageResponse
; 
 296         InitMessage
.MessageType     
= REMOTE_NDIS_INITIALIZE_MSG
; 
 297         InitMessage
.MessageLength   
= sizeof(RNDIS_Initialize_Message_t
); 
 298         InitMessage
.RequestId       
= RNDISInterfaceInfo
->State
.RequestID
++; 
 300         InitMessage
.MajorVersion    
= REMOTE_NDIS_VERSION_MAJOR
; 
 301         InitMessage
.MinorVersion    
= REMOTE_NDIS_VERSION_MINOR
; 
 302         InitMessage
.MaxTransferSize 
= RNDISInterfaceInfo
->Config
.HostMaxPacketSize
; 
 304         if ((ErrorCode 
= RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo
, &InitMessage
, 
 305                                                        sizeof(RNDIS_Initialize_Message_t
))) != HOST_SENDCONTROL_Successful
) 
 310         if ((ErrorCode 
= RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo
, &InitMessageResponse
, 
 311                                                        sizeof(RNDIS_Initialize_Complete_t
))) != HOST_SENDCONTROL_Successful
) 
 316         if (InitMessageResponse
.Status 
!= REMOTE_NDIS_STATUS_SUCCESS
) 
 317           return RNDIS_COMMAND_FAILED
; 
 319         RNDISInterfaceInfo
->State
.DeviceMaxPacketSize 
= InitMessageResponse
.MaxTransferSize
; 
 321         return HOST_SENDCONTROL_Successful
; 
 324 uint8_t RNDIS_Host_SetRNDISProperty(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
, 
 327                                     const uint16_t Length
) 
 333                 RNDIS_Set_Message_t SetMessage
; 
 334                 uint8_t             ContiguousBuffer
[Length
]; 
 337         RNDIS_Set_Complete_t SetMessageResponse
; 
 339         SetMessageData
.SetMessage
.MessageType    
= REMOTE_NDIS_SET_MSG
; 
 340         SetMessageData
.SetMessage
.MessageLength  
= sizeof(RNDIS_Set_Message_t
) + Length
; 
 341         SetMessageData
.SetMessage
.RequestId      
= RNDISInterfaceInfo
->State
.RequestID
++; 
 343         SetMessageData
.SetMessage
.Oid            
= Oid
; 
 344         SetMessageData
.SetMessage
.InformationBufferLength 
= Length
; 
 345         SetMessageData
.SetMessage
.InformationBufferOffset 
= (sizeof(RNDIS_Set_Message_t
) - sizeof(RNDIS_Message_Header_t
)); 
 346         SetMessageData
.SetMessage
.DeviceVcHandle 
= 0; 
 348         memcpy(&SetMessageData
.ContiguousBuffer
, Buffer
, Length
); 
 350         if ((ErrorCode 
= RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo
, &SetMessageData
, 
 351                                                        SetMessageData
.SetMessage
.MessageLength
)) != HOST_SENDCONTROL_Successful
) 
 356         if ((ErrorCode 
= RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo
, &SetMessageResponse
, 
 357                                                        sizeof(RNDIS_Set_Complete_t
))) != HOST_SENDCONTROL_Successful
) 
 362         if (SetMessageResponse
.Status 
!= REMOTE_NDIS_STATUS_SUCCESS
) 
 363           return RNDIS_COMMAND_FAILED
; 
 365         return HOST_SENDCONTROL_Successful
; 
 368 uint8_t RNDIS_Host_QueryRNDISProperty(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
, 
 371                                       const uint16_t MaxLength
) 
 375         RNDIS_Query_Message_t QueryMessage
; 
 379                 RNDIS_Query_Complete_t QueryMessageResponse
; 
 380                 uint8_t                ContiguousBuffer
[MaxLength
]; 
 381         } QueryMessageResponseData
; 
 383         QueryMessage
.MessageType    
= REMOTE_NDIS_QUERY_MSG
; 
 384         QueryMessage
.MessageLength  
= sizeof(RNDIS_Query_Message_t
); 
 385         QueryMessage
.RequestId      
= RNDISInterfaceInfo
->State
.RequestID
++; 
 387         QueryMessage
.Oid            
= Oid
; 
 388         QueryMessage
.InformationBufferLength 
= 0; 
 389         QueryMessage
.InformationBufferOffset 
= 0; 
 390         QueryMessage
.DeviceVcHandle 
= 0; 
 392         if ((ErrorCode 
= RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo
, &QueryMessage
, 
 393                                                        sizeof(RNDIS_Query_Message_t
))) != HOST_SENDCONTROL_Successful
) 
 398         if ((ErrorCode 
= RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo
, &QueryMessageResponseData
, 
 399                                                        sizeof(QueryMessageResponseData
))) != HOST_SENDCONTROL_Successful
) 
 404         if (QueryMessageResponseData
.QueryMessageResponse
.Status 
!= REMOTE_NDIS_STATUS_SUCCESS
) 
 405           return RNDIS_COMMAND_FAILED
; 
 407         memcpy(Buffer
, &QueryMessageResponseData
.ContiguousBuffer
, MaxLength
); 
 409         return HOST_SENDCONTROL_Successful
; 
 412 bool RNDIS_Host_IsPacketReceived(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
) 
 416         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(RNDISInterfaceInfo
->State
.IsActive
)) 
 419         Pipe_SelectPipe(RNDISInterfaceInfo
->Config
.DataINPipeNumber
); 
 422         PacketWaiting 
= Pipe_IsINReceived(); 
 425         return PacketWaiting
; 
 428 uint8_t RNDIS_Host_ReadPacket(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
, 
 430                               uint16_t* const PacketLength
) 
 434         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(RNDISInterfaceInfo
->State
.IsActive
)) 
 435           return PIPE_READYWAIT_DeviceDisconnected
; 
 437         Pipe_SelectPipe(RNDISInterfaceInfo
->Config
.DataINPipeNumber
); 
 440         if (!(Pipe_IsReadWriteAllowed())) 
 442                 if (Pipe_IsINReceived()) 
 447                 return PIPE_RWSTREAM_NoError
; 
 450         RNDIS_Packet_Message_t DeviceMessage
; 
 452         if ((ErrorCode 
= Pipe_Read_Stream_LE(&DeviceMessage
, sizeof(RNDIS_Packet_Message_t
), 
 453                                              NO_STREAM_CALLBACK
)) != PIPE_RWSTREAM_NoError
) 
 458         *PacketLength 
= (uint16_t)DeviceMessage
.DataLength
; 
 460         Pipe_Discard_Stream(DeviceMessage
.DataOffset 
- (sizeof(RNDIS_Packet_Message_t
) - sizeof(RNDIS_Message_Header_t
)), 
 463         Pipe_Read_Stream_LE(Buffer
, *PacketLength
, NO_STREAM_CALLBACK
); 
 465         if (!(Pipe_BytesInPipe())) 
 470         return PIPE_RWSTREAM_NoError
; 
 473 uint8_t RNDIS_Host_SendPacket(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
, 
 475                               const uint16_t PacketLength
) 
 479         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(RNDISInterfaceInfo
->State
.IsActive
)) 
 480           return PIPE_READYWAIT_DeviceDisconnected
; 
 482         RNDIS_Packet_Message_t DeviceMessage
; 
 484         memset(&DeviceMessage
, 0, sizeof(RNDIS_Packet_Message_t
)); 
 485         DeviceMessage
.MessageType   
= REMOTE_NDIS_PACKET_MSG
; 
 486         DeviceMessage
.MessageLength 
= (sizeof(RNDIS_Packet_Message_t
) + PacketLength
); 
 487         DeviceMessage
.DataOffset    
= (sizeof(RNDIS_Packet_Message_t
) - sizeof(RNDIS_Message_Header_t
)); 
 488         DeviceMessage
.DataLength    
= PacketLength
; 
 490         Pipe_SelectPipe(RNDISInterfaceInfo
->Config
.DataOUTPipeNumber
); 
 493         if ((ErrorCode 
= Pipe_Write_Stream_LE(&DeviceMessage
, sizeof(RNDIS_Packet_Message_t
), 
 494                                               NO_STREAM_CALLBACK
)) != PIPE_RWSTREAM_NoError
) 
 499         Pipe_Write_Stream_LE(Buffer
, PacketLength
, NO_STREAM_CALLBACK
); 
 504         return PIPE_RWSTREAM_NoError
;