3 Copyright (C) Dean Camera, 2016.
5 dean [at] fourwalledcubicle [dot] com
10 Copyright 2016 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 Endpoint_ClearSETUP();
85 Endpoint_Read_Control_Stream_LE(RNDISInterfaceInfo
->Config
.MessageBuffer
, USB_ControlRequest
.wLength
);
88 RNDIS_Device_ProcessRNDISControlMessage(RNDISInterfaceInfo
);
92 case RNDIS_REQ_GetEncapsulatedResponse
:
93 if (USB_ControlRequest
.bmRequestType
== (REQDIR_DEVICETOHOST
| REQTYPE_CLASS
| REQREC_INTERFACE
))
95 RNDIS_Message_Header_t
* MessageHeader
= (RNDIS_Message_Header_t
*)RNDISInterfaceInfo
->Config
.MessageBuffer
;
97 if (!(MessageHeader
->MessageLength
))
99 RNDISInterfaceInfo
->Config
.MessageBuffer
[0] = 0;
100 MessageHeader
->MessageLength
= CPU_TO_LE32(1);
103 Endpoint_ClearSETUP();
104 Endpoint_Write_Control_Stream_LE(RNDISInterfaceInfo
->Config
.MessageBuffer
, le32_to_cpu(MessageHeader
->MessageLength
));
107 MessageHeader
->MessageLength
= CPU_TO_LE32(0);
114 bool RNDIS_Device_ConfigureEndpoints(USB_ClassInfo_RNDIS_Device_t
* const RNDISInterfaceInfo
)
116 memset(&RNDISInterfaceInfo
->State
, 0x00, sizeof(RNDISInterfaceInfo
->State
));
118 RNDISInterfaceInfo
->Config
.DataINEndpoint
.Type
= EP_TYPE_BULK
;
119 RNDISInterfaceInfo
->Config
.DataOUTEndpoint
.Type
= EP_TYPE_BULK
;
120 RNDISInterfaceInfo
->Config
.NotificationEndpoint
.Type
= EP_TYPE_INTERRUPT
;
122 if (RNDISInterfaceInfo
->Config
.MessageBuffer
== NULL
)
125 if (RNDISInterfaceInfo
->Config
.MessageBufferLength
< RNDIS_DEVICE_MIN_MESSAGE_BUFFER_LENGTH
)
128 if (!(Endpoint_ConfigureEndpointTable(&RNDISInterfaceInfo
->Config
.DataINEndpoint
, 1)))
131 if (!(Endpoint_ConfigureEndpointTable(&RNDISInterfaceInfo
->Config
.DataOUTEndpoint
, 1)))
134 if (!(Endpoint_ConfigureEndpointTable(&RNDISInterfaceInfo
->Config
.NotificationEndpoint
, 1)))
140 void RNDIS_Device_USBTask(USB_ClassInfo_RNDIS_Device_t
* const RNDISInterfaceInfo
)
142 if (USB_DeviceState
!= DEVICE_STATE_Configured
)
145 Endpoint_SelectEndpoint(RNDISInterfaceInfo
->Config
.NotificationEndpoint
.Address
);
147 if (Endpoint_IsINReady() && RNDISInterfaceInfo
->State
.ResponseReady
)
149 USB_Request_Header_t Notification
= (USB_Request_Header_t
)
151 .bmRequestType
= (REQDIR_DEVICETOHOST
| REQTYPE_CLASS
| REQREC_INTERFACE
),
152 .bRequest
= RNDIS_NOTIF_ResponseAvailable
,
153 .wValue
= CPU_TO_LE16(0),
154 .wIndex
= CPU_TO_LE16(0),
155 .wLength
= CPU_TO_LE16(0),
158 Endpoint_Write_Stream_LE(&Notification
, sizeof(USB_Request_Header_t
), NULL
);
162 RNDISInterfaceInfo
->State
.ResponseReady
= false;
166 void RNDIS_Device_ProcessRNDISControlMessage(USB_ClassInfo_RNDIS_Device_t
* const RNDISInterfaceInfo
)
168 /* Note: Only a single buffer is used for both the received message and its response to save SRAM. Because of
169 this, response bytes should be filled in order so that they do not clobber unread data in the buffer. */
171 RNDIS_Message_Header_t
* MessageHeader
= (RNDIS_Message_Header_t
*)RNDISInterfaceInfo
->Config
.MessageBuffer
;
173 switch (le32_to_cpu(MessageHeader
->MessageType
))
175 case REMOTE_NDIS_INITIALIZE_MSG
:
176 RNDISInterfaceInfo
->State
.ResponseReady
= true;
178 RNDIS_Initialize_Message_t
* INITIALIZE_Message
=
179 (RNDIS_Initialize_Message_t
*)RNDISInterfaceInfo
->Config
.MessageBuffer
;
180 RNDIS_Initialize_Complete_t
* INITIALIZE_Response
=
181 (RNDIS_Initialize_Complete_t
*)RNDISInterfaceInfo
->Config
.MessageBuffer
;
183 INITIALIZE_Response
->MessageType
= CPU_TO_LE32(REMOTE_NDIS_INITIALIZE_CMPLT
);
184 INITIALIZE_Response
->MessageLength
= CPU_TO_LE32(sizeof(RNDIS_Initialize_Complete_t
));
185 INITIALIZE_Response
->RequestId
= INITIALIZE_Message
->RequestId
;
186 INITIALIZE_Response
->Status
= CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS
);
188 INITIALIZE_Response
->MajorVersion
= CPU_TO_LE32(REMOTE_NDIS_VERSION_MAJOR
);
189 INITIALIZE_Response
->MinorVersion
= CPU_TO_LE32(REMOTE_NDIS_VERSION_MINOR
);
190 INITIALIZE_Response
->DeviceFlags
= CPU_TO_LE32(REMOTE_NDIS_DF_CONNECTIONLESS
);
191 INITIALIZE_Response
->Medium
= CPU_TO_LE32(REMOTE_NDIS_MEDIUM_802_3
);
192 INITIALIZE_Response
->MaxPacketsPerTransfer
= CPU_TO_LE32(1);
193 INITIALIZE_Response
->MaxTransferSize
= CPU_TO_LE32(sizeof(RNDIS_Packet_Message_t
) + ETHERNET_FRAME_SIZE_MAX
);
194 INITIALIZE_Response
->PacketAlignmentFactor
= CPU_TO_LE32(0);
195 INITIALIZE_Response
->AFListOffset
= CPU_TO_LE32(0);
196 INITIALIZE_Response
->AFListSize
= CPU_TO_LE32(0);
198 RNDISInterfaceInfo
->State
.CurrRNDISState
= RNDIS_Initialized
;
200 case REMOTE_NDIS_HALT_MSG
:
201 RNDISInterfaceInfo
->State
.ResponseReady
= false;
203 MessageHeader
->MessageLength
= CPU_TO_LE32(0);
205 RNDISInterfaceInfo
->State
.CurrRNDISState
= RNDIS_Uninitialized
;
207 case REMOTE_NDIS_QUERY_MSG
:
208 RNDISInterfaceInfo
->State
.ResponseReady
= true;
210 RNDIS_Query_Message_t
* QUERY_Message
= (RNDIS_Query_Message_t
*)RNDISInterfaceInfo
->Config
.MessageBuffer
;
211 RNDIS_Query_Complete_t
* QUERY_Response
= (RNDIS_Query_Complete_t
*)RNDISInterfaceInfo
->Config
.MessageBuffer
;
212 uint32_t Query_Oid
= CPU_TO_LE32(QUERY_Message
->Oid
);
214 void* QueryData
= &RNDISInterfaceInfo
->Config
.MessageBuffer
[sizeof(RNDIS_Message_Header_t
) +
215 le32_to_cpu(QUERY_Message
->InformationBufferOffset
)];
216 void* ResponseData
= &RNDISInterfaceInfo
->Config
.MessageBuffer
[sizeof(RNDIS_Query_Complete_t
)];
217 uint16_t ResponseSize
;
219 QUERY_Response
->MessageType
= CPU_TO_LE32(REMOTE_NDIS_QUERY_CMPLT
);
221 if (RNDIS_Device_ProcessNDISQuery(RNDISInterfaceInfo
, Query_Oid
, QueryData
, le32_to_cpu(QUERY_Message
->InformationBufferLength
),
222 ResponseData
, &ResponseSize
))
224 QUERY_Response
->Status
= CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS
);
225 QUERY_Response
->MessageLength
= cpu_to_le32(sizeof(RNDIS_Query_Complete_t
) + ResponseSize
);
227 QUERY_Response
->InformationBufferLength
= CPU_TO_LE32(ResponseSize
);
228 QUERY_Response
->InformationBufferOffset
= CPU_TO_LE32(sizeof(RNDIS_Query_Complete_t
) - sizeof(RNDIS_Message_Header_t
));
232 QUERY_Response
->Status
= CPU_TO_LE32(REMOTE_NDIS_STATUS_NOT_SUPPORTED
);
233 QUERY_Response
->MessageLength
= CPU_TO_LE32(sizeof(RNDIS_Query_Complete_t
));
235 QUERY_Response
->InformationBufferLength
= CPU_TO_LE32(0);
236 QUERY_Response
->InformationBufferOffset
= CPU_TO_LE32(0);
240 case REMOTE_NDIS_SET_MSG
:
241 RNDISInterfaceInfo
->State
.ResponseReady
= true;
243 RNDIS_Set_Message_t
* SET_Message
= (RNDIS_Set_Message_t
*)RNDISInterfaceInfo
->Config
.MessageBuffer
;
244 RNDIS_Set_Complete_t
* SET_Response
= (RNDIS_Set_Complete_t
*)RNDISInterfaceInfo
->Config
.MessageBuffer
;
245 uint32_t SET_Oid
= le32_to_cpu(SET_Message
->Oid
);
247 SET_Response
->MessageType
= CPU_TO_LE32(REMOTE_NDIS_SET_CMPLT
);
248 SET_Response
->MessageLength
= CPU_TO_LE32(sizeof(RNDIS_Set_Complete_t
));
249 SET_Response
->RequestId
= SET_Message
->RequestId
;
251 void* SetData
= &RNDISInterfaceInfo
->Config
.MessageBuffer
[sizeof(RNDIS_Message_Header_t
) +
252 le32_to_cpu(SET_Message
->InformationBufferOffset
)];
254 SET_Response
->Status
= RNDIS_Device_ProcessNDISSet(RNDISInterfaceInfo
, SET_Oid
, SetData
,
255 le32_to_cpu(SET_Message
->InformationBufferLength
)) ?
256 REMOTE_NDIS_STATUS_SUCCESS
: REMOTE_NDIS_STATUS_NOT_SUPPORTED
;
258 case REMOTE_NDIS_RESET_MSG
:
259 RNDISInterfaceInfo
->State
.ResponseReady
= true;
261 RNDIS_Reset_Complete_t
* RESET_Response
= (RNDIS_Reset_Complete_t
*)RNDISInterfaceInfo
->Config
.MessageBuffer
;
263 RESET_Response
->MessageType
= CPU_TO_LE32(REMOTE_NDIS_RESET_CMPLT
);
264 RESET_Response
->MessageLength
= CPU_TO_LE32(sizeof(RNDIS_Reset_Complete_t
));
265 RESET_Response
->Status
= CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS
);
266 RESET_Response
->AddressingReset
= CPU_TO_LE32(0);
269 case REMOTE_NDIS_KEEPALIVE_MSG
:
270 RNDISInterfaceInfo
->State
.ResponseReady
= true;
272 RNDIS_KeepAlive_Message_t
* KEEPALIVE_Message
=
273 (RNDIS_KeepAlive_Message_t
*)RNDISInterfaceInfo
->Config
.MessageBuffer
;
274 RNDIS_KeepAlive_Complete_t
* KEEPALIVE_Response
=
275 (RNDIS_KeepAlive_Complete_t
*)RNDISInterfaceInfo
->Config
.MessageBuffer
;
277 KEEPALIVE_Response
->MessageType
= CPU_TO_LE32(REMOTE_NDIS_KEEPALIVE_CMPLT
);
278 KEEPALIVE_Response
->MessageLength
= CPU_TO_LE32(sizeof(RNDIS_KeepAlive_Complete_t
));
279 KEEPALIVE_Response
->RequestId
= KEEPALIVE_Message
->RequestId
;
280 KEEPALIVE_Response
->Status
= CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS
);
286 static bool RNDIS_Device_ProcessNDISQuery(USB_ClassInfo_RNDIS_Device_t
* const RNDISInterfaceInfo
,
288 void* const QueryData
,
289 const uint16_t QuerySize
,
291 uint16_t* const ResponseSize
)
298 case OID_GEN_SUPPORTED_LIST
:
299 *ResponseSize
= sizeof(AdapterSupportedOIDList
);
301 memcpy_P(ResponseData
, AdapterSupportedOIDList
, sizeof(AdapterSupportedOIDList
));
304 case OID_GEN_PHYSICAL_MEDIUM
:
305 *ResponseSize
= sizeof(uint32_t);
307 /* Indicate that the device is a true ethernet link */
308 *((uint32_t*)ResponseData
) = CPU_TO_LE32(0);
311 case OID_GEN_HARDWARE_STATUS
:
312 *ResponseSize
= sizeof(uint32_t);
314 *((uint32_t*)ResponseData
) = CPU_TO_LE32(NDIS_HardwareStatus_Ready
);
317 case OID_GEN_MEDIA_SUPPORTED
:
318 case OID_GEN_MEDIA_IN_USE
:
319 *ResponseSize
= sizeof(uint32_t);
321 *((uint32_t*)ResponseData
) = CPU_TO_LE32(REMOTE_NDIS_MEDIUM_802_3
);
324 case OID_GEN_VENDOR_ID
:
325 *ResponseSize
= sizeof(uint32_t);
327 /* Vendor ID 0x0xFFFFFF is reserved for vendors who have not purchased a NDIS VID */
328 *((uint32_t*)ResponseData
) = CPU_TO_LE32(0x00FFFFFF);
331 case OID_GEN_MAXIMUM_FRAME_SIZE
:
332 case OID_GEN_TRANSMIT_BLOCK_SIZE
:
333 case OID_GEN_RECEIVE_BLOCK_SIZE
:
334 *ResponseSize
= sizeof(uint32_t);
336 *((uint32_t*)ResponseData
) = CPU_TO_LE32(ETHERNET_FRAME_SIZE_MAX
);
339 case OID_GEN_VENDOR_DESCRIPTION
:
340 *ResponseSize
= (strlen(RNDISInterfaceInfo
->Config
.AdapterVendorDescription
) + 1);
342 memcpy(ResponseData
, RNDISInterfaceInfo
->Config
.AdapterVendorDescription
, *ResponseSize
);
345 case OID_GEN_MEDIA_CONNECT_STATUS
:
346 *ResponseSize
= sizeof(uint32_t);
348 *((uint32_t*)ResponseData
) = CPU_TO_LE32(REMOTE_NDIS_MEDIA_STATE_CONNECTED
);
351 case OID_GEN_LINK_SPEED
:
352 *ResponseSize
= sizeof(uint32_t);
354 /* Indicate 10Mb/s link speed */
355 *((uint32_t*)ResponseData
) = CPU_TO_LE32(100000);
358 case OID_802_3_PERMANENT_ADDRESS
:
359 case OID_802_3_CURRENT_ADDRESS
:
360 *ResponseSize
= sizeof(MAC_Address_t
);
362 memcpy(ResponseData
, &RNDISInterfaceInfo
->Config
.AdapterMACAddress
, sizeof(MAC_Address_t
));
365 case OID_802_3_MAXIMUM_LIST_SIZE
:
366 *ResponseSize
= sizeof(uint32_t);
368 /* Indicate only one multicast address supported */
369 *((uint32_t*)ResponseData
) = CPU_TO_LE32(1);
372 case OID_GEN_CURRENT_PACKET_FILTER
:
373 *ResponseSize
= sizeof(uint32_t);
375 *((uint32_t*)ResponseData
) = cpu_to_le32(RNDISInterfaceInfo
->State
.CurrPacketFilter
);
378 case OID_GEN_XMIT_OK
:
380 case OID_GEN_XMIT_ERROR
:
381 case OID_GEN_RCV_ERROR
:
382 case OID_GEN_RCV_NO_BUFFER
:
383 case OID_802_3_RCV_ERROR_ALIGNMENT
:
384 case OID_802_3_XMIT_ONE_COLLISION
:
385 case OID_802_3_XMIT_MORE_COLLISIONS
:
386 *ResponseSize
= sizeof(uint32_t);
388 /* Unused statistic OIDs - always return 0 for each */
389 *((uint32_t*)ResponseData
) = CPU_TO_LE32(0);
392 case OID_GEN_MAXIMUM_TOTAL_SIZE
:
393 *ResponseSize
= sizeof(uint32_t);
395 /* Indicate maximum overall buffer (Ethernet frame and RNDIS header) the adapter can handle */
396 *((uint32_t*)ResponseData
) = CPU_TO_LE32(RNDISInterfaceInfo
->Config
.MessageBufferLength
+ ETHERNET_FRAME_SIZE_MAX
);
404 static bool RNDIS_Device_ProcessNDISSet(USB_ClassInfo_RNDIS_Device_t
* const RNDISInterfaceInfo
,
407 const uint16_t SetSize
)
413 case OID_GEN_CURRENT_PACKET_FILTER
:
414 RNDISInterfaceInfo
->State
.CurrPacketFilter
= le32_to_cpu(*((uint32_t*)SetData
));
415 RNDISInterfaceInfo
->State
.CurrRNDISState
= (RNDISInterfaceInfo
->State
.CurrPacketFilter
) ? RNDIS_Data_Initialized
: RNDIS_Initialized
;
418 case OID_802_3_MULTICAST_LIST
:
419 /* Do nothing - throw away the value from the host as it is unused */
427 bool RNDIS_Device_IsPacketReceived(USB_ClassInfo_RNDIS_Device_t
* const RNDISInterfaceInfo
)
429 if ((USB_DeviceState
!= DEVICE_STATE_Configured
) ||
430 (RNDISInterfaceInfo
->State
.CurrRNDISState
!= RNDIS_Data_Initialized
))
435 Endpoint_SelectEndpoint(RNDISInterfaceInfo
->Config
.DataOUTEndpoint
.Address
);
436 return Endpoint_IsOUTReceived();
439 uint8_t RNDIS_Device_ReadPacket(USB_ClassInfo_RNDIS_Device_t
* const RNDISInterfaceInfo
,
441 uint16_t* const PacketLength
)
443 if ((USB_DeviceState
!= DEVICE_STATE_Configured
) ||
444 (RNDISInterfaceInfo
->State
.CurrRNDISState
!= RNDIS_Data_Initialized
))
446 return ENDPOINT_RWSTREAM_DeviceDisconnected
;
449 Endpoint_SelectEndpoint(RNDISInterfaceInfo
->Config
.DataOUTEndpoint
.Address
);
453 if (!(Endpoint_IsOUTReceived()))
454 return ENDPOINT_RWSTREAM_NoError
;
456 RNDIS_Packet_Message_t RNDISPacketHeader
;
457 Endpoint_Read_Stream_LE(&RNDISPacketHeader
, sizeof(RNDIS_Packet_Message_t
), NULL
);
459 if (le32_to_cpu(RNDISPacketHeader
.DataLength
) > ETHERNET_FRAME_SIZE_MAX
)
461 Endpoint_StallTransaction();
463 return RNDIS_ERROR_LOGICAL_CMD_FAILED
;
466 *PacketLength
= (uint16_t)le32_to_cpu(RNDISPacketHeader
.DataLength
);
468 Endpoint_Read_Stream_LE(Buffer
, *PacketLength
, NULL
);
471 return ENDPOINT_RWSTREAM_NoError
;
474 uint8_t RNDIS_Device_SendPacket(USB_ClassInfo_RNDIS_Device_t
* const RNDISInterfaceInfo
,
476 const uint16_t PacketLength
)
480 if ((USB_DeviceState
!= DEVICE_STATE_Configured
) ||
481 (RNDISInterfaceInfo
->State
.CurrRNDISState
!= RNDIS_Data_Initialized
))
483 return ENDPOINT_RWSTREAM_DeviceDisconnected
;
486 Endpoint_SelectEndpoint(RNDISInterfaceInfo
->Config
.DataINEndpoint
.Address
);
488 if ((ErrorCode
= Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError
)
491 RNDIS_Packet_Message_t RNDISPacketHeader
;
493 memset(&RNDISPacketHeader
, 0, sizeof(RNDIS_Packet_Message_t
));
495 RNDISPacketHeader
.MessageType
= CPU_TO_LE32(REMOTE_NDIS_PACKET_MSG
);
496 RNDISPacketHeader
.MessageLength
= cpu_to_le32(sizeof(RNDIS_Packet_Message_t
) + PacketLength
);
497 RNDISPacketHeader
.DataOffset
= CPU_TO_LE32(sizeof(RNDIS_Packet_Message_t
) - sizeof(RNDIS_Message_Header_t
));
498 RNDISPacketHeader
.DataLength
= cpu_to_le32(PacketLength
);
500 Endpoint_Write_Stream_LE(&RNDISPacketHeader
, sizeof(RNDIS_Packet_Message_t
), NULL
);
501 Endpoint_Write_Stream_LE(Buffer
, PacketLength
, NULL
);
504 return ENDPOINT_RWSTREAM_NoError
;