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_DIR_MASK
) == ENDPOINT_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            
= le16_to_cpu(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            
= le16_to_cpu(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            
= le16_to_cpu(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
); 
 245         return USB_Host_SendControlRequest(Buffer
); 
 248 static uint8_t RNDIS_GetEncapsulatedResponse(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
, 
 250                                              const uint16_t Length
) 
 252         USB_ControlRequest 
= (USB_Request_Header_t
) 
 254                         .bmRequestType 
= (REQDIR_DEVICETOHOST 
| REQTYPE_CLASS 
| REQREC_INTERFACE
), 
 255                         .bRequest      
= RNDIS_REQ_GetEncapsulatedResponse
, 
 257                         .wIndex        
= RNDISInterfaceInfo
->State
.ControlInterfaceNumber
, 
 261         Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
 263         return USB_Host_SendControlRequest(Buffer
); 
 266 uint8_t RNDIS_Host_SendKeepAlive(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
) 
 270         RNDIS_KeepAlive_Message_t  KeepAliveMessage
; 
 271         RNDIS_KeepAlive_Complete_t KeepAliveMessageResponse
; 
 273         KeepAliveMessage
.MessageType     
= CPU_TO_LE32(REMOTE_NDIS_KEEPALIVE_MSG
); 
 274         KeepAliveMessage
.MessageLength   
= CPU_TO_LE32(sizeof(RNDIS_KeepAlive_Message_t
)); 
 275         KeepAliveMessage
.RequestId       
= cpu_to_le32(RNDISInterfaceInfo
->State
.RequestID
++); 
 277         if ((ErrorCode 
= RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo
, &KeepAliveMessage
, 
 278                                                        sizeof(RNDIS_KeepAlive_Message_t
))) != HOST_SENDCONTROL_Successful
) 
 283         if ((ErrorCode 
= RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo
, &KeepAliveMessageResponse
, 
 284                                                        sizeof(RNDIS_KeepAlive_Complete_t
))) != HOST_SENDCONTROL_Successful
) 
 289         return HOST_SENDCONTROL_Successful
; 
 292 uint8_t RNDIS_Host_InitializeDevice(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
) 
 296         RNDIS_Initialize_Message_t  InitMessage
; 
 297         RNDIS_Initialize_Complete_t InitMessageResponse
; 
 299         InitMessage
.MessageType     
= CPU_TO_LE32(REMOTE_NDIS_INITIALIZE_MSG
); 
 300         InitMessage
.MessageLength   
= CPU_TO_LE32(sizeof(RNDIS_Initialize_Message_t
)); 
 301         InitMessage
.RequestId       
= cpu_to_le32(RNDISInterfaceInfo
->State
.RequestID
++); 
 303         InitMessage
.MajorVersion    
= CPU_TO_LE32(REMOTE_NDIS_VERSION_MAJOR
); 
 304         InitMessage
.MinorVersion    
= CPU_TO_LE32(REMOTE_NDIS_VERSION_MINOR
); 
 305         InitMessage
.MaxTransferSize 
= cpu_to_le32(RNDISInterfaceInfo
->Config
.HostMaxPacketSize
); 
 307         if ((ErrorCode 
= RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo
, &InitMessage
, 
 308                                                        sizeof(RNDIS_Initialize_Message_t
))) != HOST_SENDCONTROL_Successful
) 
 313         if ((ErrorCode 
= RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo
, &InitMessageResponse
, 
 314                                                        sizeof(RNDIS_Initialize_Complete_t
))) != HOST_SENDCONTROL_Successful
) 
 319         if (InitMessageResponse
.Status 
!= CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS
)) 
 320           return RNDIS_ERROR_LOGICAL_CMD_FAILED
; 
 322         RNDISInterfaceInfo
->State
.DeviceMaxPacketSize 
= le32_to_cpu(InitMessageResponse
.MaxTransferSize
); 
 324         return HOST_SENDCONTROL_Successful
; 
 327 uint8_t RNDIS_Host_SetRNDISProperty(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
, 
 330                                     const uint16_t Length
) 
 336                 RNDIS_Set_Message_t SetMessage
; 
 337                 uint8_t             ContiguousBuffer
[Length
]; 
 340         RNDIS_Set_Complete_t SetMessageResponse
; 
 342         SetMessageData
.SetMessage
.MessageType    
= CPU_TO_LE32(REMOTE_NDIS_SET_MSG
); 
 343         SetMessageData
.SetMessage
.MessageLength  
= cpu_to_le32(sizeof(RNDIS_Set_Message_t
) + Length
); 
 344         SetMessageData
.SetMessage
.RequestId      
= cpu_to_le32(RNDISInterfaceInfo
->State
.RequestID
++); 
 346         SetMessageData
.SetMessage
.Oid            
= cpu_to_le32(Oid
); 
 347         SetMessageData
.SetMessage
.InformationBufferLength 
= cpu_to_le32(Length
); 
 348         SetMessageData
.SetMessage
.InformationBufferOffset 
= CPU_TO_LE32(sizeof(RNDIS_Set_Message_t
) - sizeof(RNDIS_Message_Header_t
)); 
 349         SetMessageData
.SetMessage
.DeviceVcHandle 
= CPU_TO_LE32(0); 
 351         memcpy(&SetMessageData
.ContiguousBuffer
, Buffer
, Length
); 
 353         if ((ErrorCode 
= RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo
, &SetMessageData
, 
 354                                                        SetMessageData
.SetMessage
.MessageLength
)) != HOST_SENDCONTROL_Successful
) 
 359         if ((ErrorCode 
= RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo
, &SetMessageResponse
, 
 360                                                        sizeof(RNDIS_Set_Complete_t
))) != HOST_SENDCONTROL_Successful
) 
 365         if (SetMessageResponse
.Status 
!= CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS
)) 
 366           return RNDIS_ERROR_LOGICAL_CMD_FAILED
; 
 368         return HOST_SENDCONTROL_Successful
; 
 371 uint8_t RNDIS_Host_QueryRNDISProperty(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
, 
 374                                       const uint16_t MaxLength
) 
 378         RNDIS_Query_Message_t QueryMessage
; 
 382                 RNDIS_Query_Complete_t QueryMessageResponse
; 
 383                 uint8_t                ContiguousBuffer
[MaxLength
]; 
 384         } QueryMessageResponseData
; 
 386         QueryMessage
.MessageType    
= CPU_TO_LE32(REMOTE_NDIS_QUERY_MSG
); 
 387         QueryMessage
.MessageLength  
= CPU_TO_LE32(sizeof(RNDIS_Query_Message_t
)); 
 388         QueryMessage
.RequestId      
= cpu_to_le32(RNDISInterfaceInfo
->State
.RequestID
++); 
 390         QueryMessage
.Oid            
= cpu_to_le32(Oid
); 
 391         QueryMessage
.InformationBufferLength 
= CPU_TO_LE32(0); 
 392         QueryMessage
.InformationBufferOffset 
= CPU_TO_LE32(0); 
 393         QueryMessage
.DeviceVcHandle 
= CPU_TO_LE32(0); 
 395         if ((ErrorCode 
= RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo
, &QueryMessage
, 
 396                                                        sizeof(RNDIS_Query_Message_t
))) != HOST_SENDCONTROL_Successful
) 
 401         if ((ErrorCode 
= RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo
, &QueryMessageResponseData
, 
 402                                                        sizeof(QueryMessageResponseData
))) != HOST_SENDCONTROL_Successful
) 
 407         if (QueryMessageResponseData
.QueryMessageResponse
.Status 
!= CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS
)) 
 408           return RNDIS_ERROR_LOGICAL_CMD_FAILED
; 
 410         memcpy(Buffer
, &QueryMessageResponseData
.ContiguousBuffer
, MaxLength
); 
 412         return HOST_SENDCONTROL_Successful
; 
 415 bool RNDIS_Host_IsPacketReceived(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
) 
 419         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(RNDISInterfaceInfo
->State
.IsActive
)) 
 422         Pipe_SelectPipe(RNDISInterfaceInfo
->Config
.DataINPipeNumber
); 
 425         PacketWaiting 
= Pipe_IsINReceived(); 
 428         return PacketWaiting
; 
 431 uint8_t RNDIS_Host_ReadPacket(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
, 
 433                               uint16_t* const PacketLength
) 
 437         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(RNDISInterfaceInfo
->State
.IsActive
)) 
 438           return PIPE_READYWAIT_DeviceDisconnected
; 
 440         Pipe_SelectPipe(RNDISInterfaceInfo
->Config
.DataINPipeNumber
); 
 443         if (!(Pipe_IsReadWriteAllowed())) 
 445                 if (Pipe_IsINReceived()) 
 450                 return PIPE_RWSTREAM_NoError
; 
 453         RNDIS_Packet_Message_t DeviceMessage
; 
 455         if ((ErrorCode 
= Pipe_Read_Stream_LE(&DeviceMessage
, sizeof(RNDIS_Packet_Message_t
), 
 456                                              NULL
)) != PIPE_RWSTREAM_NoError
) 
 461         *PacketLength 
= (uint16_t)le32_to_cpu(DeviceMessage
.DataLength
); 
 463         Pipe_Discard_Stream(DeviceMessage
.DataOffset 
- 
 464                             (sizeof(RNDIS_Packet_Message_t
) - sizeof(RNDIS_Message_Header_t
)), 
 467         Pipe_Read_Stream_LE(Buffer
, *PacketLength
, NULL
); 
 469         if (!(Pipe_BytesInPipe())) 
 474         return PIPE_RWSTREAM_NoError
; 
 477 uint8_t RNDIS_Host_SendPacket(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
, 
 479                               const uint16_t PacketLength
) 
 483         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(RNDISInterfaceInfo
->State
.IsActive
)) 
 484           return PIPE_READYWAIT_DeviceDisconnected
; 
 486         RNDIS_Packet_Message_t DeviceMessage
; 
 488         memset(&DeviceMessage
, 0, sizeof(RNDIS_Packet_Message_t
)); 
 489         DeviceMessage
.MessageType   
= CPU_TO_LE32(REMOTE_NDIS_PACKET_MSG
); 
 490         DeviceMessage
.MessageLength 
= CPU_TO_LE32(sizeof(RNDIS_Packet_Message_t
) + PacketLength
); 
 491         DeviceMessage
.DataOffset    
= CPU_TO_LE32(sizeof(RNDIS_Packet_Message_t
) - sizeof(RNDIS_Message_Header_t
)); 
 492         DeviceMessage
.DataLength    
= cpu_to_le32(PacketLength
); 
 494         Pipe_SelectPipe(RNDISInterfaceInfo
->Config
.DataOUTPipeNumber
); 
 497         if ((ErrorCode 
= Pipe_Write_Stream_LE(&DeviceMessage
, sizeof(RNDIS_Packet_Message_t
), 
 498                                               NULL
)) != PIPE_RWSTREAM_NoError
) 
 503         Pipe_Write_Stream_LE(Buffer
, PacketLength
, NULL
); 
 508         return PIPE_RWSTREAM_NoError
;