]> git.friedersdorff.com Git - max/tmk_keyboard.git/blob - tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/RNDISClassDevice.c
Merge commit '5a0132f1c1c9a14fd2941f0a5e29bbf5e31da20c' into master-core-pull
[max/tmk_keyboard.git] / tmk_core / protocol / lufa / LUFA-git / LUFA / Drivers / USB / Class / Device / RNDISClassDevice.c
1 /*
2              LUFA Library
3      Copyright (C) Dean Camera, 2014.
4
5   dean [at] fourwalledcubicle [dot] com
6            www.lufa-lib.org
7 */
8
9 /*
10   Copyright 2014  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                                 Endpoint_ClearSETUP();
85                                 Endpoint_Read_Control_Stream_LE(RNDISInterfaceInfo->Config.MessageBuffer, USB_ControlRequest.wLength);
86                                 Endpoint_ClearIN();
87
88                                 RNDIS_Device_ProcessRNDISControlMessage(RNDISInterfaceInfo);
89                         }
90
91                         break;
92                 case RNDIS_REQ_GetEncapsulatedResponse:
93                         if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
94                         {
95                                 RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)RNDISInterfaceInfo->Config.MessageBuffer;
96
97                                 if (!(MessageHeader->MessageLength))
98                                 {
99                                         RNDISInterfaceInfo->Config.MessageBuffer[0] = 0;
100                                         MessageHeader->MessageLength                = CPU_TO_LE32(1);
101                                 }
102
103                                 Endpoint_ClearSETUP();
104                                 Endpoint_Write_Control_Stream_LE(RNDISInterfaceInfo->Config.MessageBuffer, le32_to_cpu(MessageHeader->MessageLength));
105                                 Endpoint_ClearOUT();
106
107                                 MessageHeader->MessageLength = CPU_TO_LE32(0);
108                         }
109
110                         break;
111         }
112 }
113
114 bool RNDIS_Device_ConfigureEndpoints(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)
115 {
116         memset(&RNDISInterfaceInfo->State, 0x00, sizeof(RNDISInterfaceInfo->State));
117
118         RNDISInterfaceInfo->Config.DataINEndpoint.Type       = EP_TYPE_BULK;
119         RNDISInterfaceInfo->Config.DataOUTEndpoint.Type      = EP_TYPE_BULK;
120         RNDISInterfaceInfo->Config.NotificationEndpoint.Type = EP_TYPE_INTERRUPT;
121
122         if (RNDISInterfaceInfo->Config.MessageBuffer == NULL)
123           return false;
124
125         if (RNDISInterfaceInfo->Config.MessageBufferLength < RNDIS_DEVICE_MIN_MESSAGE_BUFFER_LENGTH)
126           return false;
127
128         if (!(Endpoint_ConfigureEndpointTable(&RNDISInterfaceInfo->Config.DataINEndpoint, 1)))
129           return false;
130
131         if (!(Endpoint_ConfigureEndpointTable(&RNDISInterfaceInfo->Config.DataOUTEndpoint, 1)))
132           return false;
133
134         if (!(Endpoint_ConfigureEndpointTable(&RNDISInterfaceInfo->Config.NotificationEndpoint, 1)))
135           return false;
136
137         return true;
138 }
139
140 void RNDIS_Device_USBTask(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)
141 {
142         if (USB_DeviceState != DEVICE_STATE_Configured)
143           return;
144
145         Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.NotificationEndpoint.Address);
146
147         if (Endpoint_IsINReady() && RNDISInterfaceInfo->State.ResponseReady)
148         {
149                 USB_Request_Header_t Notification = (USB_Request_Header_t)
150                         {
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),
156                         };
157
158                 Endpoint_Write_Stream_LE(&Notification, sizeof(USB_Request_Header_t), NULL);
159
160                 Endpoint_ClearIN();
161
162                 RNDISInterfaceInfo->State.ResponseReady = false;
163         }
164 }
165
166 void RNDIS_Device_ProcessRNDISControlMessage(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)
167 {
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. */
170
171         RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)RNDISInterfaceInfo->Config.MessageBuffer;
172
173         switch (le32_to_cpu(MessageHeader->MessageType))
174         {
175                 case REMOTE_NDIS_INITIALIZE_MSG:
176                         RNDISInterfaceInfo->State.ResponseReady     = true;
177
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;
182
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);
187
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);
197
198                         RNDISInterfaceInfo->State.CurrRNDISState    = RNDIS_Initialized;
199                         break;
200                 case REMOTE_NDIS_HALT_MSG:
201                         RNDISInterfaceInfo->State.ResponseReady     = false;
202
203                         MessageHeader->MessageLength                = CPU_TO_LE32(0);
204
205                         RNDISInterfaceInfo->State.CurrRNDISState    = RNDIS_Uninitialized;
206                         break;
207                 case REMOTE_NDIS_QUERY_MSG:
208                         RNDISInterfaceInfo->State.ResponseReady     = true;
209
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);
213
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;
218
219                         QUERY_Response->MessageType                 = CPU_TO_LE32(REMOTE_NDIS_QUERY_CMPLT);
220
221                         if (RNDIS_Device_ProcessNDISQuery(RNDISInterfaceInfo, Query_Oid, QueryData, le32_to_cpu(QUERY_Message->InformationBufferLength),
222                                                           ResponseData, &ResponseSize))
223                         {
224                                 QUERY_Response->Status                  = CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS);
225                                 QUERY_Response->MessageLength           = cpu_to_le32(sizeof(RNDIS_Query_Complete_t) + ResponseSize);
226
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));
229                         }
230                         else
231                         {
232                                 QUERY_Response->Status                  = CPU_TO_LE32(REMOTE_NDIS_STATUS_NOT_SUPPORTED);
233                                 QUERY_Response->MessageLength           = CPU_TO_LE32(sizeof(RNDIS_Query_Complete_t));
234
235                                 QUERY_Response->InformationBufferLength = CPU_TO_LE32(0);
236                                 QUERY_Response->InformationBufferOffset = CPU_TO_LE32(0);
237                         }
238
239                         break;
240                 case REMOTE_NDIS_SET_MSG:
241                         RNDISInterfaceInfo->State.ResponseReady     = true;
242
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);
246
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;
250
251                         void* SetData = &RNDISInterfaceInfo->Config.MessageBuffer[sizeof(RNDIS_Message_Header_t) +
252                                                                                       le32_to_cpu(SET_Message->InformationBufferOffset)];
253
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;
257                         break;
258                 case REMOTE_NDIS_RESET_MSG:
259                         RNDISInterfaceInfo->State.ResponseReady     = true;
260
261                         RNDIS_Reset_Complete_t* RESET_Response      = (RNDIS_Reset_Complete_t*)RNDISInterfaceInfo->Config.MessageBuffer;
262
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);
267
268                         break;
269                 case REMOTE_NDIS_KEEPALIVE_MSG:
270                         RNDISInterfaceInfo->State.ResponseReady     = true;
271
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;
276
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);
281
282                         break;
283         }
284 }
285
286 static bool RNDIS_Device_ProcessNDISQuery(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo,
287                                           const uint32_t OId,
288                                           void* const QueryData,
289                                           const uint16_t QuerySize,
290                                           void* ResponseData,
291                                           uint16_t* const ResponseSize)
292 {
293         (void)QueryData;
294         (void)QuerySize;
295
296         switch (OId)
297         {
298                 case OID_GEN_SUPPORTED_LIST:
299                         *ResponseSize = sizeof(AdapterSupportedOIDList);
300
301                         memcpy_P(ResponseData, AdapterSupportedOIDList, sizeof(AdapterSupportedOIDList));
302
303                         return true;
304                 case OID_GEN_PHYSICAL_MEDIUM:
305                         *ResponseSize = sizeof(uint32_t);
306
307                         /* Indicate that the device is a true ethernet link */
308                         *((uint32_t*)ResponseData) = CPU_TO_LE32(0);
309
310                         return true;
311                 case OID_GEN_HARDWARE_STATUS:
312                         *ResponseSize = sizeof(uint32_t);
313
314                         *((uint32_t*)ResponseData) = CPU_TO_LE32(NDIS_HardwareStatus_Ready);
315
316                         return true;
317                 case OID_GEN_MEDIA_SUPPORTED:
318                 case OID_GEN_MEDIA_IN_USE:
319                         *ResponseSize = sizeof(uint32_t);
320
321                         *((uint32_t*)ResponseData) = CPU_TO_LE32(REMOTE_NDIS_MEDIUM_802_3);
322
323                         return true;
324                 case OID_GEN_VENDOR_ID:
325                         *ResponseSize = sizeof(uint32_t);
326
327                         /* Vendor ID 0x0xFFFFFF is reserved for vendors who have not purchased a NDIS VID */
328                         *((uint32_t*)ResponseData) = CPU_TO_LE32(0x00FFFFFF);
329
330                         return true;
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);
335
336                         *((uint32_t*)ResponseData) = CPU_TO_LE32(ETHERNET_FRAME_SIZE_MAX);
337
338                         return true;
339                 case OID_GEN_VENDOR_DESCRIPTION:
340                         *ResponseSize = (strlen(RNDISInterfaceInfo->Config.AdapterVendorDescription) + 1);
341
342                         memcpy(ResponseData, RNDISInterfaceInfo->Config.AdapterVendorDescription, *ResponseSize);
343
344                         return true;
345                 case OID_GEN_MEDIA_CONNECT_STATUS:
346                         *ResponseSize = sizeof(uint32_t);
347
348                         *((uint32_t*)ResponseData) = CPU_TO_LE32(REMOTE_NDIS_MEDIA_STATE_CONNECTED);
349
350                         return true;
351                 case OID_GEN_LINK_SPEED:
352                         *ResponseSize = sizeof(uint32_t);
353
354                         /* Indicate 10Mb/s link speed */
355                         *((uint32_t*)ResponseData) = CPU_TO_LE32(100000);
356
357                         return true;
358                 case OID_802_3_PERMANENT_ADDRESS:
359                 case OID_802_3_CURRENT_ADDRESS:
360                         *ResponseSize = sizeof(MAC_Address_t);
361
362                         memcpy(ResponseData, &RNDISInterfaceInfo->Config.AdapterMACAddress, sizeof(MAC_Address_t));
363
364                         return true;
365                 case OID_802_3_MAXIMUM_LIST_SIZE:
366                         *ResponseSize = sizeof(uint32_t);
367
368                         /* Indicate only one multicast address supported */
369                         *((uint32_t*)ResponseData) = CPU_TO_LE32(1);
370
371                         return true;
372                 case OID_GEN_CURRENT_PACKET_FILTER:
373                         *ResponseSize = sizeof(uint32_t);
374
375                         *((uint32_t*)ResponseData) = cpu_to_le32(RNDISInterfaceInfo->State.CurrPacketFilter);
376
377                         return true;
378                 case OID_GEN_XMIT_OK:
379                 case OID_GEN_RCV_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);
387
388                         /* Unused statistic OIDs - always return 0 for each */
389                         *((uint32_t*)ResponseData) = CPU_TO_LE32(0);
390
391                         return true;
392                 case OID_GEN_MAXIMUM_TOTAL_SIZE:
393                         *ResponseSize = sizeof(uint32_t);
394
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);
397
398                         return true;
399                 default:
400                         return false;
401         }
402 }
403
404 static bool RNDIS_Device_ProcessNDISSet(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo,
405                                         const uint32_t OId,
406                                         const void* SetData,
407                                         const uint16_t SetSize)
408 {
409         (void)SetSize;
410
411         switch (OId)
412         {
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;
416
417                         return true;
418                 case OID_802_3_MULTICAST_LIST:
419                         /* Do nothing - throw away the value from the host as it is unused */
420
421                         return true;
422                 default:
423                         return false;
424         }
425 }
426
427 bool RNDIS_Device_IsPacketReceived(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)
428 {
429         if ((USB_DeviceState != DEVICE_STATE_Configured) ||
430             (RNDISInterfaceInfo->State.CurrRNDISState != RNDIS_Data_Initialized))
431         {
432                 return false;
433         }
434
435         Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.DataOUTEndpoint.Address);
436         return Endpoint_IsOUTReceived();
437 }
438
439 uint8_t RNDIS_Device_ReadPacket(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo,
440                                 void* Buffer,
441                                 uint16_t* const PacketLength)
442 {
443         if ((USB_DeviceState != DEVICE_STATE_Configured) ||
444             (RNDISInterfaceInfo->State.CurrRNDISState != RNDIS_Data_Initialized))
445         {
446                 return ENDPOINT_RWSTREAM_DeviceDisconnected;
447         }
448
449         Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.DataOUTEndpoint.Address);
450
451         *PacketLength = 0;
452
453         if (!(Endpoint_IsOUTReceived()))
454                 return ENDPOINT_RWSTREAM_NoError;
455
456         RNDIS_Packet_Message_t RNDISPacketHeader;
457         Endpoint_Read_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_Packet_Message_t), NULL);
458
459         if (le32_to_cpu(RNDISPacketHeader.DataLength) > ETHERNET_FRAME_SIZE_MAX)
460         {
461                 Endpoint_StallTransaction();
462
463                 return RNDIS_ERROR_LOGICAL_CMD_FAILED;
464         }
465
466         *PacketLength = (uint16_t)le32_to_cpu(RNDISPacketHeader.DataLength);
467
468         Endpoint_Read_Stream_LE(Buffer, *PacketLength, NULL);
469         Endpoint_ClearOUT();
470
471         return ENDPOINT_RWSTREAM_NoError;
472 }
473
474 uint8_t RNDIS_Device_SendPacket(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo,
475                                 void* Buffer,
476                                 const uint16_t PacketLength)
477 {
478         uint8_t ErrorCode;
479
480         if ((USB_DeviceState != DEVICE_STATE_Configured) ||
481             (RNDISInterfaceInfo->State.CurrRNDISState != RNDIS_Data_Initialized))
482         {
483                 return ENDPOINT_RWSTREAM_DeviceDisconnected;
484         }
485
486         Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.DataINEndpoint.Address);
487
488         if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError)
489           return ErrorCode;
490
491         RNDIS_Packet_Message_t RNDISPacketHeader;
492
493         memset(&RNDISPacketHeader, 0, sizeof(RNDIS_Packet_Message_t));
494
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);
499
500         Endpoint_Write_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_Packet_Message_t), NULL);
501         Endpoint_Write_Stream_LE(Buffer, PacketLength, NULL);
502         Endpoint_ClearIN();
503
504         return ENDPOINT_RWSTREAM_NoError;
505 }
506
507 #endif
508