Upgrade doxygen configuration files to the latest version.
[pub/lufa.git] / LUFA / Drivers / USB / Class / Device / RNDISClassDevice.c
1 /*
2 LUFA Library
3 Copyright (C) Dean Camera, 2021.
4
5 dean [at] fourwalledcubicle [dot] com
6 www.lufa-lib.org
7 */
8
9 /*
10 Copyright 2021 Dean Camera (dean [at] fourwalledcubicle [dot] com)
11
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.
20
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
28 this software.
29 */
30
31 #define __INCLUDE_FROM_USB_DRIVER
32 #include "../../Core/USBMode.h"
33
34 #if defined(USB_CAN_BE_DEVICE)
35
36 #define __INCLUDE_FROM_RNDIS_DRIVER
37 #define __INCLUDE_FROM_RNDIS_DEVICE_C
38 #include "RNDISClassDevice.h"
39
40 static const uint32_t PROGMEM AdapterSupportedOIDList[] =
41 {
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),
69 };
70
71 void RNDIS_Device_ProcessControlRequest(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)
72 {
73 if (!(Endpoint_IsSETUPReceived()))
74 return;
75
76 if (USB_ControlRequest.wIndex != RNDISInterfaceInfo->Config.ControlInterfaceNumber)
77 return;
78
79 switch (USB_ControlRequest.bRequest)
80 {
81 case RNDIS_REQ_SendEncapsulatedCommand:
82 if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
83 {
84 if (USB_ControlRequest.wLength >= sizeof(RNDISInterfaceInfo->Config.MessageBuffer))
85 break;
86
87 Endpoint_ClearSETUP();
88 Endpoint_Read_Control_Stream_LE(RNDISInterfaceInfo->Config.MessageBuffer, USB_ControlRequest.wLength);
89 Endpoint_ClearIN();
90
91 RNDIS_Device_ProcessRNDISControlMessage(RNDISInterfaceInfo);
92 }
93
94 break;
95 case RNDIS_REQ_GetEncapsulatedResponse:
96 if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
97 {
98 RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)RNDISInterfaceInfo->Config.MessageBuffer;
99
100 if (!(MessageHeader->MessageLength))
101 {
102 RNDISInterfaceInfo->Config.MessageBuffer[0] = 0;
103 MessageHeader->MessageLength = CPU_TO_LE32(1);
104 }
105
106 Endpoint_ClearSETUP();
107 Endpoint_Write_Control_Stream_LE(RNDISInterfaceInfo->Config.MessageBuffer, le32_to_cpu(MessageHeader->MessageLength));
108 Endpoint_ClearOUT();
109
110 MessageHeader->MessageLength = CPU_TO_LE32(0);
111 }
112
113 break;
114 }
115 }
116
117 bool RNDIS_Device_ConfigureEndpoints(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)
118 {
119 memset(&RNDISInterfaceInfo->State, 0x00, sizeof(RNDISInterfaceInfo->State));
120
121 RNDISInterfaceInfo->Config.DataINEndpoint.Type = EP_TYPE_BULK;
122 RNDISInterfaceInfo->Config.DataOUTEndpoint.Type = EP_TYPE_BULK;
123 RNDISInterfaceInfo->Config.NotificationEndpoint.Type = EP_TYPE_INTERRUPT;
124
125 if (RNDISInterfaceInfo->Config.MessageBuffer == NULL)
126 return false;
127
128 if (RNDISInterfaceInfo->Config.MessageBufferLength < RNDIS_DEVICE_MIN_MESSAGE_BUFFER_LENGTH)
129 return false;
130
131 if (!(Endpoint_ConfigureEndpointTable(&RNDISInterfaceInfo->Config.DataINEndpoint, 1)))
132 return false;
133
134 if (!(Endpoint_ConfigureEndpointTable(&RNDISInterfaceInfo->Config.DataOUTEndpoint, 1)))
135 return false;
136
137 if (!(Endpoint_ConfigureEndpointTable(&RNDISInterfaceInfo->Config.NotificationEndpoint, 1)))
138 return false;
139
140 return true;
141 }
142
143 void RNDIS_Device_USBTask(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)
144 {
145 if (USB_DeviceState != DEVICE_STATE_Configured)
146 return;
147
148 Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.NotificationEndpoint.Address);
149
150 if (Endpoint_IsINReady() && RNDISInterfaceInfo->State.ResponseReady)
151 {
152 USB_Request_Header_t Notification = (USB_Request_Header_t)
153 {
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),
159 };
160
161 Endpoint_Write_Stream_LE(&Notification, sizeof(USB_Request_Header_t), NULL);
162
163 Endpoint_ClearIN();
164
165 RNDISInterfaceInfo->State.ResponseReady = false;
166 }
167 }
168
169 void RNDIS_Device_ProcessRNDISControlMessage(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)
170 {
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. */
173
174 RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)RNDISInterfaceInfo->Config.MessageBuffer;
175
176 switch (le32_to_cpu(MessageHeader->MessageType))
177 {
178 case REMOTE_NDIS_INITIALIZE_MSG:
179 RNDISInterfaceInfo->State.ResponseReady = true;
180
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;
185
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);
190
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);
200
201 RNDISInterfaceInfo->State.CurrRNDISState = RNDIS_Initialized;
202 break;
203 case REMOTE_NDIS_HALT_MSG:
204 RNDISInterfaceInfo->State.ResponseReady = false;
205
206 MessageHeader->MessageLength = CPU_TO_LE32(0);
207
208 RNDISInterfaceInfo->State.CurrRNDISState = RNDIS_Uninitialized;
209 break;
210 case REMOTE_NDIS_QUERY_MSG:
211 RNDISInterfaceInfo->State.ResponseReady = true;
212
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);
216
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;
221
222 QUERY_Response->MessageType = CPU_TO_LE32(REMOTE_NDIS_QUERY_CMPLT);
223
224 if (RNDIS_Device_ProcessNDISQuery(RNDISInterfaceInfo, Query_Oid, QueryData, le32_to_cpu(QUERY_Message->InformationBufferLength),
225 ResponseData, &ResponseSize))
226 {
227 QUERY_Response->Status = CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS);
228 QUERY_Response->MessageLength = cpu_to_le32(sizeof(RNDIS_Query_Complete_t) + ResponseSize);
229
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));
232 }
233 else
234 {
235 QUERY_Response->Status = CPU_TO_LE32(REMOTE_NDIS_STATUS_NOT_SUPPORTED);
236 QUERY_Response->MessageLength = CPU_TO_LE32(sizeof(RNDIS_Query_Complete_t));
237
238 QUERY_Response->InformationBufferLength = CPU_TO_LE32(0);
239 QUERY_Response->InformationBufferOffset = CPU_TO_LE32(0);
240 }
241
242 break;
243 case REMOTE_NDIS_SET_MSG:
244 RNDISInterfaceInfo->State.ResponseReady = true;
245
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);
249
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;
253
254 void* SetData = &RNDISInterfaceInfo->Config.MessageBuffer[sizeof(RNDIS_Message_Header_t) +
255 le32_to_cpu(SET_Message->InformationBufferOffset)];
256
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;
260 break;
261 case REMOTE_NDIS_RESET_MSG:
262 RNDISInterfaceInfo->State.ResponseReady = true;
263
264 RNDIS_Reset_Complete_t* RESET_Response = (RNDIS_Reset_Complete_t*)RNDISInterfaceInfo->Config.MessageBuffer;
265
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);
270
271 break;
272 case REMOTE_NDIS_KEEPALIVE_MSG:
273 RNDISInterfaceInfo->State.ResponseReady = true;
274
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;
279
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);
284
285 break;
286 }
287 }
288
289 static bool RNDIS_Device_ProcessNDISQuery(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo,
290 const uint32_t OId,
291 void* const QueryData,
292 const uint16_t QuerySize,
293 void* ResponseData,
294 uint16_t* const ResponseSize)
295 {
296 (void)QueryData;
297 (void)QuerySize;
298
299 switch (OId)
300 {
301 case OID_GEN_SUPPORTED_LIST:
302 *ResponseSize = sizeof(AdapterSupportedOIDList);
303
304 memcpy_P(ResponseData, AdapterSupportedOIDList, sizeof(AdapterSupportedOIDList));
305
306 return true;
307 case OID_GEN_PHYSICAL_MEDIUM:
308 *ResponseSize = sizeof(uint32_t);
309
310 /* Indicate that the device is a true ethernet link */
311 *((uint32_t*)ResponseData) = CPU_TO_LE32(0);
312
313 return true;
314 case OID_GEN_HARDWARE_STATUS:
315 *ResponseSize = sizeof(uint32_t);
316
317 *((uint32_t*)ResponseData) = CPU_TO_LE32(NDIS_HardwareStatus_Ready);
318
319 return true;
320 case OID_GEN_MEDIA_SUPPORTED:
321 case OID_GEN_MEDIA_IN_USE:
322 *ResponseSize = sizeof(uint32_t);
323
324 *((uint32_t*)ResponseData) = CPU_TO_LE32(REMOTE_NDIS_MEDIUM_802_3);
325
326 return true;
327 case OID_GEN_VENDOR_ID:
328 *ResponseSize = sizeof(uint32_t);
329
330 /* Vendor ID 0x0xFFFFFF is reserved for vendors who have not purchased a NDIS VID */
331 *((uint32_t*)ResponseData) = CPU_TO_LE32(0x00FFFFFF);
332
333 return true;
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);
338
339 *((uint32_t*)ResponseData) = CPU_TO_LE32(ETHERNET_FRAME_SIZE_MAX);
340
341 return true;
342 case OID_GEN_VENDOR_DESCRIPTION:
343 *ResponseSize = (strlen(RNDISInterfaceInfo->Config.AdapterVendorDescription) + 1);
344
345 memcpy(ResponseData, RNDISInterfaceInfo->Config.AdapterVendorDescription, *ResponseSize);
346
347 return true;
348 case OID_GEN_MEDIA_CONNECT_STATUS:
349 *ResponseSize = sizeof(uint32_t);
350
351 *((uint32_t*)ResponseData) = CPU_TO_LE32(REMOTE_NDIS_MEDIA_STATE_CONNECTED);
352
353 return true;
354 case OID_GEN_LINK_SPEED:
355 *ResponseSize = sizeof(uint32_t);
356
357 /* Indicate 10Mb/s link speed */
358 *((uint32_t*)ResponseData) = CPU_TO_LE32(100000);
359
360 return true;
361 case OID_802_3_PERMANENT_ADDRESS:
362 case OID_802_3_CURRENT_ADDRESS:
363 *ResponseSize = sizeof(MAC_Address_t);
364
365 memcpy(ResponseData, &RNDISInterfaceInfo->Config.AdapterMACAddress, sizeof(MAC_Address_t));
366
367 return true;
368 case OID_802_3_MAXIMUM_LIST_SIZE:
369 *ResponseSize = sizeof(uint32_t);
370
371 /* Indicate only one multicast address supported */
372 *((uint32_t*)ResponseData) = CPU_TO_LE32(1);
373
374 return true;
375 case OID_GEN_CURRENT_PACKET_FILTER:
376 *ResponseSize = sizeof(uint32_t);
377
378 *((uint32_t*)ResponseData) = cpu_to_le32(RNDISInterfaceInfo->State.CurrPacketFilter);
379
380 return true;
381 case OID_GEN_XMIT_OK:
382 case OID_GEN_RCV_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);
390
391 /* Unused statistic OIDs - always return 0 for each */
392 *((uint32_t*)ResponseData) = CPU_TO_LE32(0);
393
394 return true;
395 case OID_GEN_MAXIMUM_TOTAL_SIZE:
396 *ResponseSize = sizeof(uint32_t);
397
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);
400
401 return true;
402 default:
403 return false;
404 }
405 }
406
407 static bool RNDIS_Device_ProcessNDISSet(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo,
408 const uint32_t OId,
409 const void* SetData,
410 const uint16_t SetSize)
411 {
412 (void)SetSize;
413
414 switch (OId)
415 {
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;
419
420 return true;
421 case OID_802_3_MULTICAST_LIST:
422 /* Do nothing - throw away the value from the host as it is unused */
423
424 return true;
425 default:
426 return false;
427 }
428 }
429
430 bool RNDIS_Device_IsPacketReceived(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)
431 {
432 if ((USB_DeviceState != DEVICE_STATE_Configured) ||
433 (RNDISInterfaceInfo->State.CurrRNDISState != RNDIS_Data_Initialized))
434 {
435 return false;
436 }
437
438 Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.DataOUTEndpoint.Address);
439 return Endpoint_IsOUTReceived();
440 }
441
442 uint8_t RNDIS_Device_ReadPacket(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo,
443 void* Buffer,
444 const uint16_t BufferSize,
445 uint16_t* PacketLength)
446 {
447 if ((USB_DeviceState != DEVICE_STATE_Configured) ||
448 (RNDISInterfaceInfo->State.CurrRNDISState != RNDIS_Data_Initialized))
449 {
450 return ENDPOINT_RWSTREAM_DeviceDisconnected;
451 }
452
453 *PacketLength = 0;
454
455 Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.DataOUTEndpoint.Address);
456
457 if (!(Endpoint_IsOUTReceived()))
458 return ENDPOINT_RWSTREAM_NoError;
459
460 RNDIS_Packet_Message_t RNDISPacketHeader;
461 Endpoint_Read_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_Packet_Message_t), NULL);
462
463 if (le32_to_cpu(RNDISPacketHeader.DataLength) > ETHERNET_FRAME_SIZE_MAX)
464 {
465 Endpoint_StallTransaction();
466
467 return RNDIS_ERROR_LOGICAL_CMD_FAILED;
468 }
469
470 const size_t ExpectedLength = (uint16_t)le32_to_cpu(RNDISPacketHeader.DataLength);
471
472 if (ExpectedLength > BufferSize)
473 *PacketLength = BufferSize;
474 else
475 *PacketLength = ExpectedLength;
476
477 Endpoint_Read_Stream_LE(Buffer, *PacketLength, NULL);
478 if (ExpectedLength > BufferSize)
479 Endpoint_Discard_Stream(ExpectedLength - BufferSize, NULL);
480 Endpoint_ClearOUT();
481
482 return ENDPOINT_RWSTREAM_NoError;
483 }
484
485 uint8_t RNDIS_Device_SendPacket(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo,
486 void* Buffer,
487 const uint16_t PacketLength)
488 {
489 uint8_t ErrorCode;
490
491 if ((USB_DeviceState != DEVICE_STATE_Configured) ||
492 (RNDISInterfaceInfo->State.CurrRNDISState != RNDIS_Data_Initialized))
493 {
494 return ENDPOINT_RWSTREAM_DeviceDisconnected;
495 }
496
497 Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.DataINEndpoint.Address);
498
499 if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError)
500 return ErrorCode;
501
502 RNDIS_Packet_Message_t RNDISPacketHeader;
503
504 memset(&RNDISPacketHeader, 0, sizeof(RNDIS_Packet_Message_t));
505
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);
510
511 Endpoint_Write_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_Packet_Message_t), NULL);
512 Endpoint_Write_Stream_LE(Buffer, PacketLength, NULL);
513 Endpoint_ClearIN();
514
515 return ENDPOINT_RWSTREAM_NoError;
516 }
517
518 #endif
519