3 Copyright (C) Dean Camera, 2019.
5 dean [at] fourwalledcubicle [dot] com
10 Copyright 2019 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 disclaims 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
38 #include "RNDISClassHost.h"
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 RNDISInterfaceInfo
->Config
.DataINPipe
.Size
= le16_to_cpu(DataINEndpoint
->EndpointSize
);
105 RNDISInterfaceInfo
->Config
.DataINPipe
.EndpointAddress
= DataINEndpoint
->EndpointAddress
;
106 RNDISInterfaceInfo
->Config
.DataINPipe
.Type
= EP_TYPE_BULK
;
108 RNDISInterfaceInfo
->Config
.DataOUTPipe
.Size
= le16_to_cpu(DataOUTEndpoint
->EndpointSize
);
109 RNDISInterfaceInfo
->Config
.DataOUTPipe
.EndpointAddress
= DataOUTEndpoint
->EndpointAddress
;
110 RNDISInterfaceInfo
->Config
.DataOUTPipe
.Type
= EP_TYPE_BULK
;
112 RNDISInterfaceInfo
->Config
.NotificationPipe
.Size
= le16_to_cpu(NotificationEndpoint
->EndpointSize
);
113 RNDISInterfaceInfo
->Config
.NotificationPipe
.EndpointAddress
= NotificationEndpoint
->EndpointAddress
;
114 RNDISInterfaceInfo
->Config
.NotificationPipe
.Type
= EP_TYPE_INTERRUPT
;
116 if (!(Pipe_ConfigurePipeTable(&RNDISInterfaceInfo
->Config
.DataINPipe
, 1)))
117 return RNDIS_ENUMERROR_PipeConfigurationFailed
;
119 if (!(Pipe_ConfigurePipeTable(&RNDISInterfaceInfo
->Config
.DataOUTPipe
, 1)))
120 return RNDIS_ENUMERROR_PipeConfigurationFailed
;
122 if (!(Pipe_ConfigurePipeTable(&RNDISInterfaceInfo
->Config
.NotificationPipe
, 1)))
123 return RNDIS_ENUMERROR_PipeConfigurationFailed
;
125 RNDISInterfaceInfo
->State
.ControlInterfaceNumber
= RNDISControlInterface
->InterfaceNumber
;
126 RNDISInterfaceInfo
->State
.IsActive
= true;
128 return RNDIS_ENUMERROR_NoError
;
131 static uint8_t DCOMP_RNDIS_Host_NextRNDISControlInterface(void* const CurrentDescriptor
)
133 USB_Descriptor_Header_t
* Header
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Header_t
);
135 if (Header
->Type
== DTYPE_Interface
)
137 USB_Descriptor_Interface_t
* Interface
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Interface_t
);
139 if ((Interface
->Class
== CDC_CSCP_CDCClass
) &&
140 (Interface
->SubClass
== CDC_CSCP_ACMSubclass
) &&
141 (Interface
->Protocol
== CDC_CSCP_VendorSpecificProtocol
))
143 return DESCRIPTOR_SEARCH_Found
;
147 return DESCRIPTOR_SEARCH_NotFound
;
150 static uint8_t DCOMP_RNDIS_Host_NextRNDISDataInterface(void* const CurrentDescriptor
)
152 USB_Descriptor_Header_t
* Header
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Header_t
);
154 if (Header
->Type
== DTYPE_Interface
)
156 USB_Descriptor_Interface_t
* Interface
= DESCRIPTOR_PCAST(CurrentDescriptor
,
157 USB_Descriptor_Interface_t
);
159 if ((Interface
->Class
== CDC_CSCP_CDCDataClass
) &&
160 (Interface
->SubClass
== CDC_CSCP_NoDataSubclass
) &&
161 (Interface
->Protocol
== CDC_CSCP_NoDataProtocol
))
163 return DESCRIPTOR_SEARCH_Found
;
167 return DESCRIPTOR_SEARCH_NotFound
;
170 static uint8_t DCOMP_RNDIS_Host_NextRNDISInterfaceEndpoint(void* const CurrentDescriptor
)
172 USB_Descriptor_Header_t
* Header
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Header_t
);
174 if (Header
->Type
== DTYPE_Endpoint
)
176 USB_Descriptor_Endpoint_t
* Endpoint
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Endpoint_t
);
178 uint8_t EndpointType
= (Endpoint
->Attributes
& EP_TYPE_MASK
);
180 if (((EndpointType
== EP_TYPE_BULK
) || (EndpointType
== EP_TYPE_INTERRUPT
)) &&
181 !(Pipe_IsEndpointBound(Endpoint
->EndpointAddress
)))
183 return DESCRIPTOR_SEARCH_Found
;
186 else if (Header
->Type
== DTYPE_Interface
)
188 return DESCRIPTOR_SEARCH_Fail
;
191 return DESCRIPTOR_SEARCH_NotFound
;
194 static uint8_t RNDIS_SendEncapsulatedCommand(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
,
196 const uint16_t Length
)
198 USB_ControlRequest
= (USB_Request_Header_t
)
200 .bmRequestType
= (REQDIR_HOSTTODEVICE
| REQTYPE_CLASS
| REQREC_INTERFACE
),
201 .bRequest
= RNDIS_REQ_SendEncapsulatedCommand
,
203 .wIndex
= RNDISInterfaceInfo
->State
.ControlInterfaceNumber
,
207 Pipe_SelectPipe(PIPE_CONTROLPIPE
);
209 return USB_Host_SendControlRequest(Buffer
);
212 static uint8_t RNDIS_GetEncapsulatedResponse(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
,
214 const uint16_t Length
)
216 USB_ControlRequest
= (USB_Request_Header_t
)
218 .bmRequestType
= (REQDIR_DEVICETOHOST
| REQTYPE_CLASS
| REQREC_INTERFACE
),
219 .bRequest
= RNDIS_REQ_GetEncapsulatedResponse
,
221 .wIndex
= RNDISInterfaceInfo
->State
.ControlInterfaceNumber
,
225 Pipe_SelectPipe(PIPE_CONTROLPIPE
);
227 return USB_Host_SendControlRequest(Buffer
);
230 uint8_t RNDIS_Host_SendKeepAlive(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
)
234 RNDIS_KeepAlive_Message_t KeepAliveMessage
;
235 RNDIS_KeepAlive_Complete_t KeepAliveMessageResponse
;
237 KeepAliveMessage
.MessageType
= CPU_TO_LE32(REMOTE_NDIS_KEEPALIVE_MSG
);
238 KeepAliveMessage
.MessageLength
= CPU_TO_LE32(sizeof(RNDIS_KeepAlive_Message_t
));
239 KeepAliveMessage
.RequestId
= cpu_to_le32(RNDISInterfaceInfo
->State
.RequestID
++);
241 if ((ErrorCode
= RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo
, &KeepAliveMessage
,
242 sizeof(RNDIS_KeepAlive_Message_t
))) != HOST_SENDCONTROL_Successful
)
247 if ((ErrorCode
= RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo
, &KeepAliveMessageResponse
,
248 sizeof(RNDIS_KeepAlive_Complete_t
))) != HOST_SENDCONTROL_Successful
)
253 return HOST_SENDCONTROL_Successful
;
256 uint8_t RNDIS_Host_InitializeDevice(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
)
260 RNDIS_Initialize_Message_t InitMessage
;
261 RNDIS_Initialize_Complete_t InitMessageResponse
;
263 InitMessage
.MessageType
= CPU_TO_LE32(REMOTE_NDIS_INITIALIZE_MSG
);
264 InitMessage
.MessageLength
= CPU_TO_LE32(sizeof(RNDIS_Initialize_Message_t
));
265 InitMessage
.RequestId
= cpu_to_le32(RNDISInterfaceInfo
->State
.RequestID
++);
267 InitMessage
.MajorVersion
= CPU_TO_LE32(REMOTE_NDIS_VERSION_MAJOR
);
268 InitMessage
.MinorVersion
= CPU_TO_LE32(REMOTE_NDIS_VERSION_MINOR
);
269 InitMessage
.MaxTransferSize
= cpu_to_le32(RNDISInterfaceInfo
->Config
.HostMaxPacketSize
);
271 if ((ErrorCode
= RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo
, &InitMessage
,
272 sizeof(RNDIS_Initialize_Message_t
))) != HOST_SENDCONTROL_Successful
)
277 if ((ErrorCode
= RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo
, &InitMessageResponse
,
278 sizeof(RNDIS_Initialize_Complete_t
))) != HOST_SENDCONTROL_Successful
)
283 if (InitMessageResponse
.Status
!= CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS
))
284 return RNDIS_ERROR_LOGICAL_CMD_FAILED
;
286 RNDISInterfaceInfo
->State
.DeviceMaxPacketSize
= le32_to_cpu(InitMessageResponse
.MaxTransferSize
);
288 return HOST_SENDCONTROL_Successful
;
291 uint8_t RNDIS_Host_SetRNDISProperty(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
,
294 const uint16_t Length
)
300 RNDIS_Set_Message_t SetMessage
;
301 uint8_t ContiguousBuffer
[Length
];
304 RNDIS_Set_Complete_t SetMessageResponse
;
306 SetMessageData
.SetMessage
.MessageType
= CPU_TO_LE32(REMOTE_NDIS_SET_MSG
);
307 SetMessageData
.SetMessage
.MessageLength
= cpu_to_le32(sizeof(RNDIS_Set_Message_t
) + Length
);
308 SetMessageData
.SetMessage
.RequestId
= cpu_to_le32(RNDISInterfaceInfo
->State
.RequestID
++);
310 SetMessageData
.SetMessage
.Oid
= cpu_to_le32(Oid
);
311 SetMessageData
.SetMessage
.InformationBufferLength
= cpu_to_le32(Length
);
312 SetMessageData
.SetMessage
.InformationBufferOffset
= CPU_TO_LE32(sizeof(RNDIS_Set_Message_t
) - sizeof(RNDIS_Message_Header_t
));
313 SetMessageData
.SetMessage
.DeviceVcHandle
= CPU_TO_LE32(0);
315 memcpy(&SetMessageData
.ContiguousBuffer
, Buffer
, Length
);
317 if ((ErrorCode
= RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo
, &SetMessageData
,
318 (sizeof(RNDIS_Set_Message_t
) + Length
))) != HOST_SENDCONTROL_Successful
)
323 if ((ErrorCode
= RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo
, &SetMessageResponse
,
324 sizeof(RNDIS_Set_Complete_t
))) != HOST_SENDCONTROL_Successful
)
329 if (SetMessageResponse
.Status
!= CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS
))
330 return RNDIS_ERROR_LOGICAL_CMD_FAILED
;
332 return HOST_SENDCONTROL_Successful
;
335 uint8_t RNDIS_Host_QueryRNDISProperty(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
,
338 const uint16_t MaxLength
)
342 RNDIS_Query_Message_t QueryMessage
;
346 RNDIS_Query_Complete_t QueryMessageResponse
;
347 uint8_t ContiguousBuffer
[MaxLength
];
348 } QueryMessageResponseData
;
350 QueryMessage
.MessageType
= CPU_TO_LE32(REMOTE_NDIS_QUERY_MSG
);
351 QueryMessage
.MessageLength
= CPU_TO_LE32(sizeof(RNDIS_Query_Message_t
));
352 QueryMessage
.RequestId
= cpu_to_le32(RNDISInterfaceInfo
->State
.RequestID
++);
354 QueryMessage
.Oid
= cpu_to_le32(Oid
);
355 QueryMessage
.InformationBufferLength
= CPU_TO_LE32(0);
356 QueryMessage
.InformationBufferOffset
= CPU_TO_LE32(0);
357 QueryMessage
.DeviceVcHandle
= CPU_TO_LE32(0);
359 if ((ErrorCode
= RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo
, &QueryMessage
,
360 sizeof(RNDIS_Query_Message_t
))) != HOST_SENDCONTROL_Successful
)
365 if ((ErrorCode
= RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo
, &QueryMessageResponseData
,
366 sizeof(QueryMessageResponseData
))) != HOST_SENDCONTROL_Successful
)
371 if (QueryMessageResponseData
.QueryMessageResponse
.Status
!= CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS
))
372 return RNDIS_ERROR_LOGICAL_CMD_FAILED
;
374 memcpy(Buffer
, &QueryMessageResponseData
.ContiguousBuffer
, MaxLength
);
376 return HOST_SENDCONTROL_Successful
;
379 bool RNDIS_Host_IsPacketReceived(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
)
383 if ((USB_HostState
!= HOST_STATE_Configured
) || !(RNDISInterfaceInfo
->State
.IsActive
))
386 Pipe_SelectPipe(RNDISInterfaceInfo
->Config
.DataINPipe
.Address
);
389 PacketWaiting
= Pipe_IsINReceived();
392 return PacketWaiting
;
395 uint8_t RNDIS_Host_ReadPacket(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
,
397 uint16_t* const PacketLength
)
401 if ((USB_HostState
!= HOST_STATE_Configured
) || !(RNDISInterfaceInfo
->State
.IsActive
))
402 return PIPE_READYWAIT_DeviceDisconnected
;
404 Pipe_SelectPipe(RNDISInterfaceInfo
->Config
.DataINPipe
.Address
);
407 if (!(Pipe_IsReadWriteAllowed()))
409 if (Pipe_IsINReceived())
414 return PIPE_RWSTREAM_NoError
;
417 RNDIS_Packet_Message_t DeviceMessage
;
419 if ((ErrorCode
= Pipe_Read_Stream_LE(&DeviceMessage
, sizeof(RNDIS_Packet_Message_t
),
420 NULL
)) != PIPE_RWSTREAM_NoError
)
425 *PacketLength
= (uint16_t)le32_to_cpu(DeviceMessage
.DataLength
);
427 Pipe_Discard_Stream(le32_to_cpu(DeviceMessage
.DataOffset
) -
428 (sizeof(RNDIS_Packet_Message_t
) - sizeof(RNDIS_Message_Header_t
)),
431 Pipe_Read_Stream_LE(Buffer
, *PacketLength
, NULL
);
433 if (!(Pipe_BytesInPipe()))
438 return PIPE_RWSTREAM_NoError
;
441 uint8_t RNDIS_Host_SendPacket(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
,
443 const uint16_t PacketLength
)
447 if ((USB_HostState
!= HOST_STATE_Configured
) || !(RNDISInterfaceInfo
->State
.IsActive
))
448 return PIPE_READYWAIT_DeviceDisconnected
;
450 RNDIS_Packet_Message_t DeviceMessage
;
452 memset(&DeviceMessage
, 0, sizeof(RNDIS_Packet_Message_t
));
453 DeviceMessage
.MessageType
= CPU_TO_LE32(REMOTE_NDIS_PACKET_MSG
);
454 DeviceMessage
.MessageLength
= CPU_TO_LE32(sizeof(RNDIS_Packet_Message_t
) + PacketLength
);
455 DeviceMessage
.DataOffset
= CPU_TO_LE32(sizeof(RNDIS_Packet_Message_t
) - sizeof(RNDIS_Message_Header_t
));
456 DeviceMessage
.DataLength
= cpu_to_le32(PacketLength
);
458 Pipe_SelectPipe(RNDISInterfaceInfo
->Config
.DataOUTPipe
.Address
);
461 if ((ErrorCode
= Pipe_Write_Stream_LE(&DeviceMessage
, sizeof(RNDIS_Packet_Message_t
),
462 NULL
)) != PIPE_RWSTREAM_NoError
)
467 Pipe_Write_Stream_LE(Buffer
, PacketLength
, NULL
);
472 return PIPE_RWSTREAM_NoError
;