3 Copyright (C) Dean Camera, 2021.
5 dean [at] fourwalledcubicle [dot] com
10 Copyright 2021 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_DEVICE)
36 #define __INCLUDE_FROM_RNDIS_DRIVER
37 #define __INCLUDE_FROM_RNDIS_DEVICE_C
38 #include "RNDISClassDevice.h"
40 static const uint32_t PROGMEM AdapterSupportedOIDList
[] =
42 CPU_TO_LE32(OID_GEN_SUPPORTED_LIST
),
43 CPU_TO_LE32(OID_GEN_PHYSICAL_MEDIUM
),
44 CPU_TO_LE32(OID_GEN_HARDWARE_STATUS
),
45 CPU_TO_LE32(OID_GEN_MEDIA_SUPPORTED
),
46 CPU_TO_LE32(OID_GEN_MEDIA_IN_USE
),
47 CPU_TO_LE32(OID_GEN_MAXIMUM_FRAME_SIZE
),
48 CPU_TO_LE32(OID_GEN_MAXIMUM_TOTAL_SIZE
),
49 CPU_TO_LE32(OID_GEN_LINK_SPEED
),
50 CPU_TO_LE32(OID_GEN_TRANSMIT_BLOCK_SIZE
),
51 CPU_TO_LE32(OID_GEN_RECEIVE_BLOCK_SIZE
),
52 CPU_TO_LE32(OID_GEN_VENDOR_ID
),
53 CPU_TO_LE32(OID_GEN_VENDOR_DESCRIPTION
),
54 CPU_TO_LE32(OID_GEN_CURRENT_PACKET_FILTER
),
55 CPU_TO_LE32(OID_GEN_MAXIMUM_TOTAL_SIZE
),
56 CPU_TO_LE32(OID_GEN_MEDIA_CONNECT_STATUS
),
57 CPU_TO_LE32(OID_GEN_XMIT_OK
),
58 CPU_TO_LE32(OID_GEN_RCV_OK
),
59 CPU_TO_LE32(OID_GEN_XMIT_ERROR
),
60 CPU_TO_LE32(OID_GEN_RCV_ERROR
),
61 CPU_TO_LE32(OID_GEN_RCV_NO_BUFFER
),
62 CPU_TO_LE32(OID_802_3_PERMANENT_ADDRESS
),
63 CPU_TO_LE32(OID_802_3_CURRENT_ADDRESS
),
64 CPU_TO_LE32(OID_802_3_MULTICAST_LIST
),
65 CPU_TO_LE32(OID_802_3_MAXIMUM_LIST_SIZE
),
66 CPU_TO_LE32(OID_802_3_RCV_ERROR_ALIGNMENT
),
67 CPU_TO_LE32(OID_802_3_XMIT_ONE_COLLISION
),
68 CPU_TO_LE32(OID_802_3_XMIT_MORE_COLLISIONS
),
71 void RNDIS_Device_ProcessControlRequest(USB_ClassInfo_RNDIS_Device_t
* const RNDISInterfaceInfo
)
73 if (!(Endpoint_IsSETUPReceived()))
76 if (USB_ControlRequest
.wIndex
!= RNDISInterfaceInfo
->Config
.ControlInterfaceNumber
)
79 switch (USB_ControlRequest
.bRequest
)
81 case RNDIS_REQ_SendEncapsulatedCommand
:
82 if (USB_ControlRequest
.bmRequestType
== (REQDIR_HOSTTODEVICE
| REQTYPE_CLASS
| REQREC_INTERFACE
))
84 if (USB_ControlRequest
.wLength
>= sizeof(RNDISInterfaceInfo
->Config
.MessageBuffer
))
87 Endpoint_ClearSETUP();
88 Endpoint_Read_Control_Stream_LE(RNDISInterfaceInfo
->Config
.MessageBuffer
, USB_ControlRequest
.wLength
);
91 RNDIS_Device_ProcessRNDISControlMessage(RNDISInterfaceInfo
);
95 case RNDIS_REQ_GetEncapsulatedResponse
:
96 if (USB_ControlRequest
.bmRequestType
== (REQDIR_DEVICETOHOST
| REQTYPE_CLASS
| REQREC_INTERFACE
))
98 RNDIS_Message_Header_t
* MessageHeader
= (RNDIS_Message_Header_t
*)RNDISInterfaceInfo
->Config
.MessageBuffer
;
100 if (!(MessageHeader
->MessageLength
))
102 RNDISInterfaceInfo
->Config
.MessageBuffer
[0] = 0;
103 MessageHeader
->MessageLength
= CPU_TO_LE32(1);
106 Endpoint_ClearSETUP();
107 Endpoint_Write_Control_Stream_LE(RNDISInterfaceInfo
->Config
.MessageBuffer
, le32_to_cpu(MessageHeader
->MessageLength
));
110 MessageHeader
->MessageLength
= CPU_TO_LE32(0);
117 bool RNDIS_Device_ConfigureEndpoints(USB_ClassInfo_RNDIS_Device_t
* const RNDISInterfaceInfo
)
119 memset(&RNDISInterfaceInfo
->State
, 0x00, sizeof(RNDISInterfaceInfo
->State
));
121 RNDISInterfaceInfo
->Config
.DataINEndpoint
.Type
= EP_TYPE_BULK
;
122 RNDISInterfaceInfo
->Config
.DataOUTEndpoint
.Type
= EP_TYPE_BULK
;
123 RNDISInterfaceInfo
->Config
.NotificationEndpoint
.Type
= EP_TYPE_INTERRUPT
;
125 if (RNDISInterfaceInfo
->Config
.MessageBuffer
== NULL
)
128 if (RNDISInterfaceInfo
->Config
.MessageBufferLength
< RNDIS_DEVICE_MIN_MESSAGE_BUFFER_LENGTH
)
131 if (!(Endpoint_ConfigureEndpointTable(&RNDISInterfaceInfo
->Config
.DataINEndpoint
, 1)))
134 if (!(Endpoint_ConfigureEndpointTable(&RNDISInterfaceInfo
->Config
.DataOUTEndpoint
, 1)))
137 if (!(Endpoint_ConfigureEndpointTable(&RNDISInterfaceInfo
->Config
.NotificationEndpoint
, 1)))
143 void RNDIS_Device_USBTask(USB_ClassInfo_RNDIS_Device_t
* const RNDISInterfaceInfo
)
145 if (USB_DeviceState
!= DEVICE_STATE_Configured
)
148 Endpoint_SelectEndpoint(RNDISInterfaceInfo
->Config
.NotificationEndpoint
.Address
);
150 if (Endpoint_IsINReady() && RNDISInterfaceInfo
->State
.ResponseReady
)
152 USB_Request_Header_t Notification
= (USB_Request_Header_t
)
154 .bmRequestType
= (REQDIR_DEVICETOHOST
| REQTYPE_CLASS
| REQREC_INTERFACE
),
155 .bRequest
= RNDIS_NOTIF_ResponseAvailable
,
156 .wValue
= CPU_TO_LE16(0),
157 .wIndex
= CPU_TO_LE16(0),
158 .wLength
= CPU_TO_LE16(0),
161 Endpoint_Write_Stream_LE(&Notification
, sizeof(USB_Request_Header_t
), NULL
);
165 RNDISInterfaceInfo
->State
.ResponseReady
= false;
169 void RNDIS_Device_ProcessRNDISControlMessage(USB_ClassInfo_RNDIS_Device_t
* const RNDISInterfaceInfo
)
171 /* Note: Only a single buffer is used for both the received message and its response to save SRAM. Because of
172 this, response bytes should be filled in order so that they do not clobber unread data in the buffer. */
174 RNDIS_Message_Header_t
* MessageHeader
= (RNDIS_Message_Header_t
*)RNDISInterfaceInfo
->Config
.MessageBuffer
;
176 switch (le32_to_cpu(MessageHeader
->MessageType
))
178 case REMOTE_NDIS_INITIALIZE_MSG
:
179 RNDISInterfaceInfo
->State
.ResponseReady
= true;
181 RNDIS_Initialize_Message_t
* INITIALIZE_Message
=
182 (RNDIS_Initialize_Message_t
*)RNDISInterfaceInfo
->Config
.MessageBuffer
;
183 RNDIS_Initialize_Complete_t
* INITIALIZE_Response
=
184 (RNDIS_Initialize_Complete_t
*)RNDISInterfaceInfo
->Config
.MessageBuffer
;
186 INITIALIZE_Response
->MessageType
= CPU_TO_LE32(REMOTE_NDIS_INITIALIZE_CMPLT
);
187 INITIALIZE_Response
->MessageLength
= CPU_TO_LE32(sizeof(RNDIS_Initialize_Complete_t
));
188 INITIALIZE_Response
->RequestId
= INITIALIZE_Message
->RequestId
;
189 INITIALIZE_Response
->Status
= CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS
);
191 INITIALIZE_Response
->MajorVersion
= CPU_TO_LE32(REMOTE_NDIS_VERSION_MAJOR
);
192 INITIALIZE_Response
->MinorVersion
= CPU_TO_LE32(REMOTE_NDIS_VERSION_MINOR
);
193 INITIALIZE_Response
->DeviceFlags
= CPU_TO_LE32(REMOTE_NDIS_DF_CONNECTIONLESS
);
194 INITIALIZE_Response
->Medium
= CPU_TO_LE32(REMOTE_NDIS_MEDIUM_802_3
);
195 INITIALIZE_Response
->MaxPacketsPerTransfer
= CPU_TO_LE32(1);
196 INITIALIZE_Response
->MaxTransferSize
= CPU_TO_LE32(sizeof(RNDIS_Packet_Message_t
) + ETHERNET_FRAME_SIZE_MAX
);
197 INITIALIZE_Response
->PacketAlignmentFactor
= CPU_TO_LE32(0);
198 INITIALIZE_Response
->AFListOffset
= CPU_TO_LE32(0);
199 INITIALIZE_Response
->AFListSize
= CPU_TO_LE32(0);
201 RNDISInterfaceInfo
->State
.CurrRNDISState
= RNDIS_Initialized
;
203 case REMOTE_NDIS_HALT_MSG
:
204 RNDISInterfaceInfo
->State
.ResponseReady
= false;
206 MessageHeader
->MessageLength
= CPU_TO_LE32(0);
208 RNDISInterfaceInfo
->State
.CurrRNDISState
= RNDIS_Uninitialized
;
210 case REMOTE_NDIS_QUERY_MSG
:
211 RNDISInterfaceInfo
->State
.ResponseReady
= true;
213 RNDIS_Query_Message_t
* QUERY_Message
= (RNDIS_Query_Message_t
*)RNDISInterfaceInfo
->Config
.MessageBuffer
;
214 RNDIS_Query_Complete_t
* QUERY_Response
= (RNDIS_Query_Complete_t
*)RNDISInterfaceInfo
->Config
.MessageBuffer
;
215 uint32_t Query_Oid
= CPU_TO_LE32(QUERY_Message
->Oid
);
217 void* QueryData
= &RNDISInterfaceInfo
->Config
.MessageBuffer
[sizeof(RNDIS_Message_Header_t
) +
218 le32_to_cpu(QUERY_Message
->InformationBufferOffset
)];
219 void* ResponseData
= &RNDISInterfaceInfo
->Config
.MessageBuffer
[sizeof(RNDIS_Query_Complete_t
)];
220 uint16_t ResponseSize
;
222 QUERY_Response
->MessageType
= CPU_TO_LE32(REMOTE_NDIS_QUERY_CMPLT
);
224 if (RNDIS_Device_ProcessNDISQuery(RNDISInterfaceInfo
, Query_Oid
, QueryData
, le32_to_cpu(QUERY_Message
->InformationBufferLength
),
225 ResponseData
, &ResponseSize
))
227 QUERY_Response
->Status
= CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS
);
228 QUERY_Response
->MessageLength
= cpu_to_le32(sizeof(RNDIS_Query_Complete_t
) + ResponseSize
);
230 QUERY_Response
->InformationBufferLength
= CPU_TO_LE32(ResponseSize
);
231 QUERY_Response
->InformationBufferOffset
= CPU_TO_LE32(sizeof(RNDIS_Query_Complete_t
) - sizeof(RNDIS_Message_Header_t
));
235 QUERY_Response
->Status
= CPU_TO_LE32(REMOTE_NDIS_STATUS_NOT_SUPPORTED
);
236 QUERY_Response
->MessageLength
= CPU_TO_LE32(sizeof(RNDIS_Query_Complete_t
));
238 QUERY_Response
->InformationBufferLength
= CPU_TO_LE32(0);
239 QUERY_Response
->InformationBufferOffset
= CPU_TO_LE32(0);
243 case REMOTE_NDIS_SET_MSG
:
244 RNDISInterfaceInfo
->State
.ResponseReady
= true;
246 RNDIS_Set_Message_t
* SET_Message
= (RNDIS_Set_Message_t
*)RNDISInterfaceInfo
->Config
.MessageBuffer
;
247 RNDIS_Set_Complete_t
* SET_Response
= (RNDIS_Set_Complete_t
*)RNDISInterfaceInfo
->Config
.MessageBuffer
;
248 uint32_t SET_Oid
= le32_to_cpu(SET_Message
->Oid
);
250 SET_Response
->MessageType
= CPU_TO_LE32(REMOTE_NDIS_SET_CMPLT
);
251 SET_Response
->MessageLength
= CPU_TO_LE32(sizeof(RNDIS_Set_Complete_t
));
252 SET_Response
->RequestId
= SET_Message
->RequestId
;
254 void* SetData
= &RNDISInterfaceInfo
->Config
.MessageBuffer
[sizeof(RNDIS_Message_Header_t
) +
255 le32_to_cpu(SET_Message
->InformationBufferOffset
)];
257 SET_Response
->Status
= RNDIS_Device_ProcessNDISSet(RNDISInterfaceInfo
, SET_Oid
, SetData
,
258 le32_to_cpu(SET_Message
->InformationBufferLength
)) ?
259 REMOTE_NDIS_STATUS_SUCCESS
: REMOTE_NDIS_STATUS_NOT_SUPPORTED
;
261 case REMOTE_NDIS_RESET_MSG
:
262 RNDISInterfaceInfo
->State
.ResponseReady
= true;
264 RNDIS_Reset_Complete_t
* RESET_Response
= (RNDIS_Reset_Complete_t
*)RNDISInterfaceInfo
->Config
.MessageBuffer
;
266 RESET_Response
->MessageType
= CPU_TO_LE32(REMOTE_NDIS_RESET_CMPLT
);
267 RESET_Response
->MessageLength
= CPU_TO_LE32(sizeof(RNDIS_Reset_Complete_t
));
268 RESET_Response
->Status
= CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS
);
269 RESET_Response
->AddressingReset
= CPU_TO_LE32(0);
272 case REMOTE_NDIS_KEEPALIVE_MSG
:
273 RNDISInterfaceInfo
->State
.ResponseReady
= true;
275 RNDIS_KeepAlive_Message_t
* KEEPALIVE_Message
=
276 (RNDIS_KeepAlive_Message_t
*)RNDISInterfaceInfo
->Config
.MessageBuffer
;
277 RNDIS_KeepAlive_Complete_t
* KEEPALIVE_Response
=
278 (RNDIS_KeepAlive_Complete_t
*)RNDISInterfaceInfo
->Config
.MessageBuffer
;
280 KEEPALIVE_Response
->MessageType
= CPU_TO_LE32(REMOTE_NDIS_KEEPALIVE_CMPLT
);
281 KEEPALIVE_Response
->MessageLength
= CPU_TO_LE32(sizeof(RNDIS_KeepAlive_Complete_t
));
282 KEEPALIVE_Response
->RequestId
= KEEPALIVE_Message
->RequestId
;
283 KEEPALIVE_Response
->Status
= CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS
);
289 static bool RNDIS_Device_ProcessNDISQuery(USB_ClassInfo_RNDIS_Device_t
* const RNDISInterfaceInfo
,
291 void* const QueryData
,
292 const uint16_t QuerySize
,
294 uint16_t* const ResponseSize
)
301 case OID_GEN_SUPPORTED_LIST
:
302 *ResponseSize
= sizeof(AdapterSupportedOIDList
);
304 memcpy_P(ResponseData
, AdapterSupportedOIDList
, sizeof(AdapterSupportedOIDList
));
307 case OID_GEN_PHYSICAL_MEDIUM
:
308 *ResponseSize
= sizeof(uint32_t);
310 /* Indicate that the device is a true ethernet link */
311 *((uint32_t*)ResponseData
) = CPU_TO_LE32(0);
314 case OID_GEN_HARDWARE_STATUS
:
315 *ResponseSize
= sizeof(uint32_t);
317 *((uint32_t*)ResponseData
) = CPU_TO_LE32(NDIS_HardwareStatus_Ready
);
320 case OID_GEN_MEDIA_SUPPORTED
:
321 case OID_GEN_MEDIA_IN_USE
:
322 *ResponseSize
= sizeof(uint32_t);
324 *((uint32_t*)ResponseData
) = CPU_TO_LE32(REMOTE_NDIS_MEDIUM_802_3
);
327 case OID_GEN_VENDOR_ID
:
328 *ResponseSize
= sizeof(uint32_t);
330 /* Vendor ID 0x0xFFFFFF is reserved for vendors who have not purchased a NDIS VID */
331 *((uint32_t*)ResponseData
) = CPU_TO_LE32(0x00FFFFFF);
334 case OID_GEN_MAXIMUM_FRAME_SIZE
:
335 case OID_GEN_TRANSMIT_BLOCK_SIZE
:
336 case OID_GEN_RECEIVE_BLOCK_SIZE
:
337 *ResponseSize
= sizeof(uint32_t);
339 *((uint32_t*)ResponseData
) = CPU_TO_LE32(ETHERNET_FRAME_SIZE_MAX
);
342 case OID_GEN_VENDOR_DESCRIPTION
:
343 *ResponseSize
= (strlen(RNDISInterfaceInfo
->Config
.AdapterVendorDescription
) + 1);
345 memcpy(ResponseData
, RNDISInterfaceInfo
->Config
.AdapterVendorDescription
, *ResponseSize
);
348 case OID_GEN_MEDIA_CONNECT_STATUS
:
349 *ResponseSize
= sizeof(uint32_t);
351 *((uint32_t*)ResponseData
) = CPU_TO_LE32(REMOTE_NDIS_MEDIA_STATE_CONNECTED
);
354 case OID_GEN_LINK_SPEED
:
355 *ResponseSize
= sizeof(uint32_t);
357 /* Indicate 10Mb/s link speed */
358 *((uint32_t*)ResponseData
) = CPU_TO_LE32(100000);
361 case OID_802_3_PERMANENT_ADDRESS
:
362 case OID_802_3_CURRENT_ADDRESS
:
363 *ResponseSize
= sizeof(MAC_Address_t
);
365 memcpy(ResponseData
, &RNDISInterfaceInfo
->Config
.AdapterMACAddress
, sizeof(MAC_Address_t
));
368 case OID_802_3_MAXIMUM_LIST_SIZE
:
369 *ResponseSize
= sizeof(uint32_t);
371 /* Indicate only one multicast address supported */
372 *((uint32_t*)ResponseData
) = CPU_TO_LE32(1);
375 case OID_GEN_CURRENT_PACKET_FILTER
:
376 *ResponseSize
= sizeof(uint32_t);
378 *((uint32_t*)ResponseData
) = cpu_to_le32(RNDISInterfaceInfo
->State
.CurrPacketFilter
);
381 case OID_GEN_XMIT_OK
:
383 case OID_GEN_XMIT_ERROR
:
384 case OID_GEN_RCV_ERROR
:
385 case OID_GEN_RCV_NO_BUFFER
:
386 case OID_802_3_RCV_ERROR_ALIGNMENT
:
387 case OID_802_3_XMIT_ONE_COLLISION
:
388 case OID_802_3_XMIT_MORE_COLLISIONS
:
389 *ResponseSize
= sizeof(uint32_t);
391 /* Unused statistic OIDs - always return 0 for each */
392 *((uint32_t*)ResponseData
) = CPU_TO_LE32(0);
395 case OID_GEN_MAXIMUM_TOTAL_SIZE
:
396 *ResponseSize
= sizeof(uint32_t);
398 /* Indicate maximum overall buffer (Ethernet frame and RNDIS header) the adapter can handle */
399 *((uint32_t*)ResponseData
) = CPU_TO_LE32(RNDISInterfaceInfo
->Config
.MessageBufferLength
+ ETHERNET_FRAME_SIZE_MAX
);
407 static bool RNDIS_Device_ProcessNDISSet(USB_ClassInfo_RNDIS_Device_t
* const RNDISInterfaceInfo
,
410 const uint16_t SetSize
)
416 case OID_GEN_CURRENT_PACKET_FILTER
:
417 RNDISInterfaceInfo
->State
.CurrPacketFilter
= le32_to_cpu(*((uint32_t*)SetData
));
418 RNDISInterfaceInfo
->State
.CurrRNDISState
= (RNDISInterfaceInfo
->State
.CurrPacketFilter
) ? RNDIS_Data_Initialized
: RNDIS_Initialized
;
421 case OID_802_3_MULTICAST_LIST
:
422 /* Do nothing - throw away the value from the host as it is unused */
430 bool RNDIS_Device_IsPacketReceived(USB_ClassInfo_RNDIS_Device_t
* const RNDISInterfaceInfo
)
432 if ((USB_DeviceState
!= DEVICE_STATE_Configured
) ||
433 (RNDISInterfaceInfo
->State
.CurrRNDISState
!= RNDIS_Data_Initialized
))
438 Endpoint_SelectEndpoint(RNDISInterfaceInfo
->Config
.DataOUTEndpoint
.Address
);
439 return Endpoint_IsOUTReceived();
442 uint8_t RNDIS_Device_ReadPacket(USB_ClassInfo_RNDIS_Device_t
* const RNDISInterfaceInfo
,
444 const uint16_t BufferSize
,
445 uint16_t* PacketLength
)
447 if ((USB_DeviceState
!= DEVICE_STATE_Configured
) ||
448 (RNDISInterfaceInfo
->State
.CurrRNDISState
!= RNDIS_Data_Initialized
))
450 return ENDPOINT_RWSTREAM_DeviceDisconnected
;
455 Endpoint_SelectEndpoint(RNDISInterfaceInfo
->Config
.DataOUTEndpoint
.Address
);
457 if (!(Endpoint_IsOUTReceived()))
458 return ENDPOINT_RWSTREAM_NoError
;
460 RNDIS_Packet_Message_t RNDISPacketHeader
;
461 Endpoint_Read_Stream_LE(&RNDISPacketHeader
, sizeof(RNDIS_Packet_Message_t
), NULL
);
463 if (le32_to_cpu(RNDISPacketHeader
.DataLength
) > ETHERNET_FRAME_SIZE_MAX
)
465 Endpoint_StallTransaction();
467 return RNDIS_ERROR_LOGICAL_CMD_FAILED
;
470 const size_t ExpectedLength
= (uint16_t)le32_to_cpu(RNDISPacketHeader
.DataLength
);
472 if (ExpectedLength
> BufferSize
)
473 *PacketLength
= BufferSize
;
475 *PacketLength
= ExpectedLength
;
477 Endpoint_Read_Stream_LE(Buffer
, *PacketLength
, NULL
);
478 if (ExpectedLength
> BufferSize
)
479 Endpoint_Discard_Stream(ExpectedLength
- BufferSize
, NULL
);
482 return ENDPOINT_RWSTREAM_NoError
;
485 uint8_t RNDIS_Device_SendPacket(USB_ClassInfo_RNDIS_Device_t
* const RNDISInterfaceInfo
,
487 const uint16_t PacketLength
)
491 if ((USB_DeviceState
!= DEVICE_STATE_Configured
) ||
492 (RNDISInterfaceInfo
->State
.CurrRNDISState
!= RNDIS_Data_Initialized
))
494 return ENDPOINT_RWSTREAM_DeviceDisconnected
;
497 Endpoint_SelectEndpoint(RNDISInterfaceInfo
->Config
.DataINEndpoint
.Address
);
499 if ((ErrorCode
= Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError
)
502 RNDIS_Packet_Message_t RNDISPacketHeader
;
504 memset(&RNDISPacketHeader
, 0, sizeof(RNDIS_Packet_Message_t
));
506 RNDISPacketHeader
.MessageType
= CPU_TO_LE32(REMOTE_NDIS_PACKET_MSG
);
507 RNDISPacketHeader
.MessageLength
= cpu_to_le32(sizeof(RNDIS_Packet_Message_t
) + PacketLength
);
508 RNDISPacketHeader
.DataOffset
= CPU_TO_LE32(sizeof(RNDIS_Packet_Message_t
) - sizeof(RNDIS_Message_Header_t
));
509 RNDISPacketHeader
.DataLength
= cpu_to_le32(PacketLength
);
511 Endpoint_Write_Stream_LE(&RNDISPacketHeader
, sizeof(RNDIS_Packet_Message_t
), NULL
);
512 Endpoint_Write_Stream_LE(Buffer
, PacketLength
, NULL
);
515 return ENDPOINT_RWSTREAM_NoError
;