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 "../../Core/USBMode.h" 
  34 #if defined(USB_CAN_BE_HOST) 
  36 #define  __INCLUDE_FROM_RNDIS_DRIVER 
  37 #define  __INCLUDE_FROM_RNDIS_HOST_C 
  40 uint8_t RNDIS_Host_ConfigurePipes(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
, 
  41                                   uint16_t ConfigDescriptorSize
, 
  42                                   void* ConfigDescriptorData
) 
  44         USB_Descriptor_Endpoint_t
*  DataINEndpoint        
= NULL
; 
  45         USB_Descriptor_Endpoint_t
*  DataOUTEndpoint       
= NULL
; 
  46         USB_Descriptor_Endpoint_t
*  NotificationEndpoint  
= NULL
; 
  47         USB_Descriptor_Interface_t
* RNDISControlInterface 
= NULL
; 
  49         memset(&RNDISInterfaceInfo
->State
, 0x00, sizeof(RNDISInterfaceInfo
->State
)); 
  51         if (DESCRIPTOR_TYPE(ConfigDescriptorData
) != DTYPE_Configuration
) 
  52           return RNDIS_ENUMERROR_InvalidConfigDescriptor
; 
  54         RNDISControlInterface 
= DESCRIPTOR_PCAST(ConfigDescriptorData
, USB_Descriptor_Interface_t
); 
  56         while (!(DataINEndpoint
) || !(DataOUTEndpoint
) || !(NotificationEndpoint
)) 
  58                 if (!(RNDISControlInterface
) || 
  59                     USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
, 
  60                                               DCOMP_RNDIS_Host_NextRNDISInterfaceEndpoint
) != DESCRIPTOR_SEARCH_COMP_Found
) 
  62                         if (NotificationEndpoint
) 
  64                                 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
, 
  65                                                                                           DCOMP_RNDIS_Host_NextRNDISDataInterface
) != DESCRIPTOR_SEARCH_COMP_Found
) 
  67                                         return RNDIS_ENUMERROR_NoCompatibleInterfaceFound
; 
  70                                 DataINEndpoint  
= NULL
; 
  71                                 DataOUTEndpoint 
= NULL
; 
  75                                 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
, 
  76                                                                                           DCOMP_RNDIS_Host_NextRNDISControlInterface
) != DESCRIPTOR_SEARCH_COMP_Found
) 
  78                                         return RNDIS_ENUMERROR_NoCompatibleInterfaceFound
; 
  81                                 RNDISControlInterface 
= DESCRIPTOR_PCAST(ConfigDescriptorData
, USB_Descriptor_Interface_t
); 
  83                                 NotificationEndpoint 
= NULL
; 
  89                 USB_Descriptor_Endpoint_t
* EndpointData 
= DESCRIPTOR_PCAST(ConfigDescriptorData
, USB_Descriptor_Endpoint_t
); 
  91                 if (EndpointData
->EndpointAddress 
& ENDPOINT_DESCRIPTOR_DIR_IN
) 
  93                         if ((EndpointData
->Attributes 
& EP_TYPE_MASK
) == EP_TYPE_INTERRUPT
) 
  94                           NotificationEndpoint 
= EndpointData
; 
  96                           DataINEndpoint 
= EndpointData
; 
 100                         DataOUTEndpoint 
= EndpointData
; 
 104         for (uint8_t PipeNum 
= 1; PipeNum 
< PIPE_TOTAL_PIPES
; PipeNum
++) 
 109                 uint8_t  EndpointAddress
; 
 110                 uint8_t  InterruptPeriod
; 
 113                 if (PipeNum 
== RNDISInterfaceInfo
->Config
.DataINPipeNumber
) 
 115                         Size            
= DataINEndpoint
->EndpointSize
; 
 116                         EndpointAddress 
= DataINEndpoint
->EndpointAddress
; 
 117                         Token           
= PIPE_TOKEN_IN
; 
 119                         DoubleBanked    
= RNDISInterfaceInfo
->Config
.DataINPipeDoubleBank
; 
 122                         RNDISInterfaceInfo
->State
.DataINPipeSize 
= DataINEndpoint
->EndpointSize
; 
 124                 else if (PipeNum 
== RNDISInterfaceInfo
->Config
.DataOUTPipeNumber
) 
 126                         Size            
= DataOUTEndpoint
->EndpointSize
; 
 127                         EndpointAddress 
= DataOUTEndpoint
->EndpointAddress
; 
 128                         Token           
= PIPE_TOKEN_OUT
; 
 130                         DoubleBanked    
= RNDISInterfaceInfo
->Config
.DataOUTPipeDoubleBank
; 
 133                         RNDISInterfaceInfo
->State
.DataOUTPipeSize 
= DataOUTEndpoint
->EndpointSize
; 
 135                 else if (PipeNum 
== RNDISInterfaceInfo
->Config
.NotificationPipeNumber
) 
 137                         Size            
= NotificationEndpoint
->EndpointSize
; 
 138                         EndpointAddress 
= NotificationEndpoint
->EndpointAddress
; 
 139                         Token           
= PIPE_TOKEN_IN
; 
 140                         Type            
= EP_TYPE_INTERRUPT
; 
 141                         DoubleBanked    
= RNDISInterfaceInfo
->Config
.NotificationPipeDoubleBank
; 
 142                         InterruptPeriod 
= NotificationEndpoint
->PollingIntervalMS
; 
 144                         RNDISInterfaceInfo
->State
.NotificationPipeSize 
= NotificationEndpoint
->EndpointSize
; 
 151                 if (!(Pipe_ConfigurePipe(PipeNum
, Type
, Token
, EndpointAddress
, Size
, 
 152                                          DoubleBanked ? PIPE_BANK_DOUBLE 
: PIPE_BANK_SINGLE
))) 
 154                         return CDC_ENUMERROR_PipeConfigurationFailed
; 
 158                   Pipe_SetInterruptPeriod(InterruptPeriod
); 
 161         RNDISInterfaceInfo
->State
.ControlInterfaceNumber 
= RNDISControlInterface
->InterfaceNumber
; 
 162         RNDISInterfaceInfo
->State
.IsActive 
= true; 
 164         return RNDIS_ENUMERROR_NoError
; 
 167 static uint8_t DCOMP_RNDIS_Host_NextRNDISControlInterface(void* const CurrentDescriptor
) 
 169         USB_Descriptor_Header_t
* Header 
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Header_t
); 
 171         if (Header
->Type 
== DTYPE_Interface
) 
 173                 USB_Descriptor_Interface_t
* Interface 
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Interface_t
); 
 175                 if ((Interface
->Class    
== CDC_CSCP_CDCClass
)    && 
 176                     (Interface
->SubClass 
== CDC_CSCP_ACMSubclass
) && 
 177                     (Interface
->Protocol 
== CDC_CSCP_VendorSpecificProtocol
)) 
 179                         return DESCRIPTOR_SEARCH_Found
; 
 183         return DESCRIPTOR_SEARCH_NotFound
; 
 186 static uint8_t DCOMP_RNDIS_Host_NextRNDISDataInterface(void* const CurrentDescriptor
) 
 188         USB_Descriptor_Header_t
* Header 
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Header_t
); 
 190         if (Header
->Type 
== DTYPE_Interface
) 
 192                 USB_Descriptor_Interface_t
* Interface 
= DESCRIPTOR_PCAST(CurrentDescriptor
, 
 193                                                                          USB_Descriptor_Interface_t
); 
 195                 if ((Interface
->Class    
== CDC_CSCP_CDCDataClass
)   && 
 196                     (Interface
->SubClass 
== CDC_CSCP_NoDataSubclass
) && 
 197                     (Interface
->Protocol 
== CDC_CSCP_NoDataProtocol
)) 
 199                         return DESCRIPTOR_SEARCH_Found
; 
 203         return DESCRIPTOR_SEARCH_NotFound
; 
 206 static uint8_t DCOMP_RNDIS_Host_NextRNDISInterfaceEndpoint(void* const CurrentDescriptor
) 
 208         USB_Descriptor_Header_t
* Header 
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Header_t
); 
 210         if (Header
->Type 
== DTYPE_Endpoint
) 
 212                 USB_Descriptor_Endpoint_t
* Endpoint 
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Endpoint_t
); 
 214                 uint8_t EndpointType 
= (Endpoint
->Attributes 
& EP_TYPE_MASK
); 
 216                 if (((EndpointType 
== EP_TYPE_BULK
) || (EndpointType 
== EP_TYPE_INTERRUPT
)) && 
 217                     !(Pipe_IsEndpointBound(Endpoint
->EndpointAddress
))) 
 219                         return DESCRIPTOR_SEARCH_Found
; 
 222         else if (Header
->Type 
== DTYPE_Interface
) 
 224                 return DESCRIPTOR_SEARCH_Fail
; 
 227         return DESCRIPTOR_SEARCH_NotFound
; 
 230 static uint8_t RNDIS_SendEncapsulatedCommand(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
, 
 232                                              const uint16_t Length
) 
 234         USB_ControlRequest 
= (USB_Request_Header_t
) 
 236                         .bmRequestType 
= (REQDIR_HOSTTODEVICE 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
 237                         .bRequest      
= RNDIS_REQ_SendEncapsulatedCommand
, 
 239                         .wIndex        
= RNDISInterfaceInfo
->State
.ControlInterfaceNumber
, 
 243         Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
 244         return USB_Host_SendControlRequest(Buffer
); 
 247 static uint8_t RNDIS_GetEncapsulatedResponse(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
, 
 249                                              const uint16_t Length
) 
 251         USB_ControlRequest 
= (USB_Request_Header_t
) 
 253                         .bmRequestType 
= (REQDIR_DEVICETOHOST 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
 254                         .bRequest      
= RNDIS_REQ_GetEncapsulatedResponse
, 
 256                         .wIndex        
= RNDISInterfaceInfo
->State
.ControlInterfaceNumber
, 
 260         Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
 261         return USB_Host_SendControlRequest(Buffer
); 
 264 uint8_t RNDIS_Host_SendKeepAlive(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
) 
 268         RNDIS_KeepAlive_Message_t  KeepAliveMessage
; 
 269         RNDIS_KeepAlive_Complete_t KeepAliveMessageResponse
; 
 271         KeepAliveMessage
.MessageType     
= REMOTE_NDIS_KEEPALIVE_MSG
; 
 272         KeepAliveMessage
.MessageLength   
= sizeof(RNDIS_KeepAlive_Message_t
); 
 273         KeepAliveMessage
.RequestId       
= RNDISInterfaceInfo
->State
.RequestID
++; 
 275         if ((ErrorCode 
= RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo
, &KeepAliveMessage
, 
 276                                                        sizeof(RNDIS_KeepAlive_Message_t
))) != HOST_SENDCONTROL_Successful
) 
 281         if ((ErrorCode 
= RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo
, &KeepAliveMessageResponse
, 
 282                                                        sizeof(RNDIS_KeepAlive_Complete_t
))) != HOST_SENDCONTROL_Successful
) 
 287         return HOST_SENDCONTROL_Successful
; 
 290 uint8_t RNDIS_Host_InitializeDevice(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
) 
 294         RNDIS_Initialize_Message_t  InitMessage
; 
 295         RNDIS_Initialize_Complete_t InitMessageResponse
; 
 297         InitMessage
.MessageType     
= REMOTE_NDIS_INITIALIZE_MSG
; 
 298         InitMessage
.MessageLength   
= sizeof(RNDIS_Initialize_Message_t
); 
 299         InitMessage
.RequestId       
= RNDISInterfaceInfo
->State
.RequestID
++; 
 301         InitMessage
.MajorVersion    
= REMOTE_NDIS_VERSION_MAJOR
; 
 302         InitMessage
.MinorVersion    
= REMOTE_NDIS_VERSION_MINOR
; 
 303         InitMessage
.MaxTransferSize 
= RNDISInterfaceInfo
->Config
.HostMaxPacketSize
; 
 305         if ((ErrorCode 
= RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo
, &InitMessage
, 
 306                                                        sizeof(RNDIS_Initialize_Message_t
))) != HOST_SENDCONTROL_Successful
) 
 311         if ((ErrorCode 
= RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo
, &InitMessageResponse
, 
 312                                                        sizeof(RNDIS_Initialize_Complete_t
))) != HOST_SENDCONTROL_Successful
) 
 317         if (InitMessageResponse
.Status 
!= REMOTE_NDIS_STATUS_SUCCESS
) 
 318           return RNDIS_COMMAND_FAILED
; 
 320         RNDISInterfaceInfo
->State
.DeviceMaxPacketSize 
= InitMessageResponse
.MaxTransferSize
; 
 322         return HOST_SENDCONTROL_Successful
; 
 325 uint8_t RNDIS_Host_SetRNDISProperty(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
, 
 328                                     const uint16_t Length
) 
 334                 RNDIS_Set_Message_t SetMessage
; 
 335                 uint8_t             ContiguousBuffer
[Length
]; 
 338         RNDIS_Set_Complete_t SetMessageResponse
; 
 340         SetMessageData
.SetMessage
.MessageType    
= REMOTE_NDIS_SET_MSG
; 
 341         SetMessageData
.SetMessage
.MessageLength  
= sizeof(RNDIS_Set_Message_t
) + Length
; 
 342         SetMessageData
.SetMessage
.RequestId      
= RNDISInterfaceInfo
->State
.RequestID
++; 
 344         SetMessageData
.SetMessage
.Oid            
= Oid
; 
 345         SetMessageData
.SetMessage
.InformationBufferLength 
= Length
; 
 346         SetMessageData
.SetMessage
.InformationBufferOffset 
= (sizeof(RNDIS_Set_Message_t
) - sizeof(RNDIS_Message_Header_t
)); 
 347         SetMessageData
.SetMessage
.DeviceVcHandle 
= 0; 
 349         memcpy(&SetMessageData
.ContiguousBuffer
, Buffer
, Length
); 
 351         if ((ErrorCode 
= RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo
, &SetMessageData
, 
 352                                                        SetMessageData
.SetMessage
.MessageLength
)) != HOST_SENDCONTROL_Successful
) 
 357         if ((ErrorCode 
= RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo
, &SetMessageResponse
, 
 358                                                        sizeof(RNDIS_Set_Complete_t
))) != HOST_SENDCONTROL_Successful
) 
 363         if (SetMessageResponse
.Status 
!= REMOTE_NDIS_STATUS_SUCCESS
) 
 364           return RNDIS_COMMAND_FAILED
; 
 366         return HOST_SENDCONTROL_Successful
; 
 369 uint8_t RNDIS_Host_QueryRNDISProperty(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
, 
 372                                       const uint16_t MaxLength
) 
 376         RNDIS_Query_Message_t QueryMessage
; 
 380                 RNDIS_Query_Complete_t QueryMessageResponse
; 
 381                 uint8_t                ContiguousBuffer
[MaxLength
]; 
 382         } QueryMessageResponseData
; 
 384         QueryMessage
.MessageType    
= REMOTE_NDIS_QUERY_MSG
; 
 385         QueryMessage
.MessageLength  
= sizeof(RNDIS_Query_Message_t
); 
 386         QueryMessage
.RequestId      
= RNDISInterfaceInfo
->State
.RequestID
++; 
 388         QueryMessage
.Oid            
= Oid
; 
 389         QueryMessage
.InformationBufferLength 
= 0; 
 390         QueryMessage
.InformationBufferOffset 
= 0; 
 391         QueryMessage
.DeviceVcHandle 
= 0; 
 393         if ((ErrorCode 
= RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo
, &QueryMessage
, 
 394                                                        sizeof(RNDIS_Query_Message_t
))) != HOST_SENDCONTROL_Successful
) 
 399         if ((ErrorCode 
= RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo
, &QueryMessageResponseData
, 
 400                                                        sizeof(QueryMessageResponseData
))) != HOST_SENDCONTROL_Successful
) 
 405         if (QueryMessageResponseData
.QueryMessageResponse
.Status 
!= REMOTE_NDIS_STATUS_SUCCESS
) 
 406           return RNDIS_COMMAND_FAILED
; 
 408         memcpy(Buffer
, &QueryMessageResponseData
.ContiguousBuffer
, MaxLength
); 
 410         return HOST_SENDCONTROL_Successful
; 
 413 bool RNDIS_Host_IsPacketReceived(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
) 
 417         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(RNDISInterfaceInfo
->State
.IsActive
)) 
 420         Pipe_SelectPipe(RNDISInterfaceInfo
->Config
.DataINPipeNumber
); 
 423         PacketWaiting 
= Pipe_IsINReceived(); 
 426         return PacketWaiting
; 
 429 uint8_t RNDIS_Host_ReadPacket(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
, 
 431                               uint16_t* const PacketLength
) 
 435         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(RNDISInterfaceInfo
->State
.IsActive
)) 
 436           return PIPE_READYWAIT_DeviceDisconnected
; 
 438         Pipe_SelectPipe(RNDISInterfaceInfo
->Config
.DataINPipeNumber
); 
 441         if (!(Pipe_IsReadWriteAllowed())) 
 443                 if (Pipe_IsINReceived()) 
 448                 return PIPE_RWSTREAM_NoError
; 
 451         RNDIS_Packet_Message_t DeviceMessage
; 
 453         if ((ErrorCode 
= Pipe_Read_Stream_LE(&DeviceMessage
, sizeof(RNDIS_Packet_Message_t
), 
 454                                              NULL
)) != PIPE_RWSTREAM_NoError
) 
 459         *PacketLength 
= (uint16_t)DeviceMessage
.DataLength
; 
 461         Pipe_Discard_Stream(DeviceMessage
.DataOffset 
- (sizeof(RNDIS_Packet_Message_t
) - sizeof(RNDIS_Message_Header_t
)), 
 464         Pipe_Read_Stream_LE(Buffer
, *PacketLength
, NULL
); 
 466         if (!(Pipe_BytesInPipe())) 
 471         return PIPE_RWSTREAM_NoError
; 
 474 uint8_t RNDIS_Host_SendPacket(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
, 
 476                               const uint16_t PacketLength
) 
 480         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(RNDISInterfaceInfo
->State
.IsActive
)) 
 481           return PIPE_READYWAIT_DeviceDisconnected
; 
 483         RNDIS_Packet_Message_t DeviceMessage
; 
 485         memset(&DeviceMessage
, 0, sizeof(RNDIS_Packet_Message_t
)); 
 486         DeviceMessage
.MessageType   
= REMOTE_NDIS_PACKET_MSG
; 
 487         DeviceMessage
.MessageLength 
= (sizeof(RNDIS_Packet_Message_t
) + PacketLength
); 
 488         DeviceMessage
.DataOffset    
= (sizeof(RNDIS_Packet_Message_t
) - sizeof(RNDIS_Message_Header_t
)); 
 489         DeviceMessage
.DataLength    
= PacketLength
; 
 491         Pipe_SelectPipe(RNDISInterfaceInfo
->Config
.DataOUTPipeNumber
); 
 494         if ((ErrorCode 
= Pipe_Write_Stream_LE(&DeviceMessage
, sizeof(RNDIS_Packet_Message_t
), 
 495                                               NULL
)) != PIPE_RWSTREAM_NoError
) 
 500         Pipe_Write_Stream_LE(Buffer
, PacketLength
, NULL
); 
 505         return PIPE_RWSTREAM_NoError
;