]> git.donarmstrong.com Git - qmk_firmware.git/blob - protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/Device/RNDISClassDevice.c
Squashed 'tmk_core/' content from commit 05caacc
[qmk_firmware.git] / protocol / lufa / LUFA-120730 / LUFA / Drivers / USB / Class / Device / RNDISClassDevice.c
1 /*\r
2              LUFA Library\r
3      Copyright (C) Dean Camera, 2012.\r
4 \r
5   dean [at] fourwalledcubicle [dot] com\r
6            www.lufa-lib.org\r
7 */\r
8 \r
9 /*\r
10   Copyright 2012  Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
11 \r
12   Permission to use, copy, modify, distribute, and sell this\r
13   software and its documentation for any purpose is hereby granted\r
14   without fee, provided that the above copyright notice appear in\r
15   all copies and that both that the copyright notice and this\r
16   permission notice and warranty disclaimer appear in supporting\r
17   documentation, and that the name of the author not be used in\r
18   advertising or publicity pertaining to distribution of the\r
19   software without specific, written prior permission.\r
20 \r
21   The author disclaim all warranties with regard to this\r
22   software, including all implied warranties of merchantability\r
23   and fitness.  In no event shall the author be liable for any\r
24   special, indirect or consequential damages or any damages\r
25   whatsoever resulting from loss of use, data or profits, whether\r
26   in an action of contract, negligence or other tortious action,\r
27   arising out of or in connection with the use or performance of\r
28   this software.\r
29 */\r
30 \r
31 #define  __INCLUDE_FROM_USB_DRIVER\r
32 #include "../../Core/USBMode.h"\r
33 \r
34 #if defined(USB_CAN_BE_DEVICE)\r
35 \r
36 #define  __INCLUDE_FROM_RNDIS_DRIVER\r
37 #define  __INCLUDE_FROM_RNDIS_DEVICE_C\r
38 #include "RNDISClassDevice.h"\r
39 \r
40 static const uint32_t PROGMEM AdapterSupportedOIDList[]  =\r
41         {\r
42                 CPU_TO_LE32(OID_GEN_SUPPORTED_LIST),\r
43                 CPU_TO_LE32(OID_GEN_PHYSICAL_MEDIUM),\r
44                 CPU_TO_LE32(OID_GEN_HARDWARE_STATUS),\r
45                 CPU_TO_LE32(OID_GEN_MEDIA_SUPPORTED),\r
46                 CPU_TO_LE32(OID_GEN_MEDIA_IN_USE),\r
47                 CPU_TO_LE32(OID_GEN_MAXIMUM_FRAME_SIZE),\r
48                 CPU_TO_LE32(OID_GEN_MAXIMUM_TOTAL_SIZE),\r
49                 CPU_TO_LE32(OID_GEN_LINK_SPEED),\r
50                 CPU_TO_LE32(OID_GEN_TRANSMIT_BLOCK_SIZE),\r
51                 CPU_TO_LE32(OID_GEN_RECEIVE_BLOCK_SIZE),\r
52                 CPU_TO_LE32(OID_GEN_VENDOR_ID),\r
53                 CPU_TO_LE32(OID_GEN_VENDOR_DESCRIPTION),\r
54                 CPU_TO_LE32(OID_GEN_CURRENT_PACKET_FILTER),\r
55                 CPU_TO_LE32(OID_GEN_MAXIMUM_TOTAL_SIZE),\r
56                 CPU_TO_LE32(OID_GEN_MEDIA_CONNECT_STATUS),\r
57                 CPU_TO_LE32(OID_GEN_XMIT_OK),\r
58                 CPU_TO_LE32(OID_GEN_RCV_OK),\r
59                 CPU_TO_LE32(OID_GEN_XMIT_ERROR),\r
60                 CPU_TO_LE32(OID_GEN_RCV_ERROR),\r
61                 CPU_TO_LE32(OID_GEN_RCV_NO_BUFFER),\r
62                 CPU_TO_LE32(OID_802_3_PERMANENT_ADDRESS),\r
63                 CPU_TO_LE32(OID_802_3_CURRENT_ADDRESS),\r
64                 CPU_TO_LE32(OID_802_3_MULTICAST_LIST),\r
65                 CPU_TO_LE32(OID_802_3_MAXIMUM_LIST_SIZE),\r
66                 CPU_TO_LE32(OID_802_3_RCV_ERROR_ALIGNMENT),\r
67                 CPU_TO_LE32(OID_802_3_XMIT_ONE_COLLISION),\r
68                 CPU_TO_LE32(OID_802_3_XMIT_MORE_COLLISIONS),\r
69         };\r
70 \r
71 void RNDIS_Device_ProcessControlRequest(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)\r
72 {\r
73         if (!(Endpoint_IsSETUPReceived()))\r
74           return;\r
75 \r
76         if (USB_ControlRequest.wIndex != RNDISInterfaceInfo->Config.ControlInterfaceNumber)\r
77           return;\r
78 \r
79         switch (USB_ControlRequest.bRequest)\r
80         {\r
81                 case RNDIS_REQ_SendEncapsulatedCommand:\r
82                         if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))\r
83                         {\r
84                                 Endpoint_ClearSETUP();\r
85                                 Endpoint_Read_Control_Stream_LE(RNDISInterfaceInfo->State.RNDISMessageBuffer, USB_ControlRequest.wLength);\r
86                                 Endpoint_ClearIN();\r
87 \r
88                                 RNDIS_Device_ProcessRNDISControlMessage(RNDISInterfaceInfo);\r
89                         }\r
90 \r
91                         break;\r
92                 case RNDIS_REQ_GetEncapsulatedResponse:\r
93                         if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))\r
94                         {\r
95                                 RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;\r
96 \r
97                                 if (!(MessageHeader->MessageLength))\r
98                                 {\r
99                                         RNDISInterfaceInfo->State.RNDISMessageBuffer[0] = 0;\r
100                                         MessageHeader->MessageLength                    = CPU_TO_LE32(1);\r
101                                 }\r
102 \r
103                                 Endpoint_ClearSETUP();\r
104                                 Endpoint_Write_Control_Stream_LE(RNDISInterfaceInfo->State.RNDISMessageBuffer, le32_to_cpu(MessageHeader->MessageLength));\r
105                                 Endpoint_ClearOUT();\r
106 \r
107                                 MessageHeader->MessageLength = CPU_TO_LE32(0);\r
108                         }\r
109 \r
110                         break;\r
111         }\r
112 }\r
113 \r
114 bool RNDIS_Device_ConfigureEndpoints(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)\r
115 {\r
116         memset(&RNDISInterfaceInfo->State, 0x00, sizeof(RNDISInterfaceInfo->State));\r
117 \r
118         RNDISInterfaceInfo->Config.DataINEndpoint.Type       = EP_TYPE_BULK;\r
119         RNDISInterfaceInfo->Config.DataOUTEndpoint.Type      = EP_TYPE_BULK;\r
120         RNDISInterfaceInfo->Config.NotificationEndpoint.Type = EP_TYPE_INTERRUPT;\r
121 \r
122         if (!(Endpoint_ConfigureEndpointTable(&RNDISInterfaceInfo->Config.DataINEndpoint, 1)))\r
123           return false;\r
124 \r
125         if (!(Endpoint_ConfigureEndpointTable(&RNDISInterfaceInfo->Config.DataOUTEndpoint, 1)))\r
126           return false;\r
127 \r
128         if (!(Endpoint_ConfigureEndpointTable(&RNDISInterfaceInfo->Config.NotificationEndpoint, 1)))\r
129           return false;\r
130 \r
131         return true;\r
132 }\r
133 \r
134 void RNDIS_Device_USBTask(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)\r
135 {\r
136         if (USB_DeviceState != DEVICE_STATE_Configured)\r
137           return;\r
138 \r
139         Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.NotificationEndpoint.Address);\r
140 \r
141         if (Endpoint_IsINReady() && RNDISInterfaceInfo->State.ResponseReady)\r
142         {\r
143                 USB_Request_Header_t Notification = (USB_Request_Header_t)\r
144                         {\r
145                                 .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),\r
146                                 .bRequest      = RNDIS_NOTIF_ResponseAvailable,\r
147                                 .wValue        = CPU_TO_LE16(0),\r
148                                 .wIndex        = CPU_TO_LE16(0),\r
149                                 .wLength       = CPU_TO_LE16(0),\r
150                         };\r
151 \r
152                 Endpoint_Write_Stream_LE(&Notification, sizeof(USB_Request_Header_t), NULL);\r
153 \r
154                 Endpoint_ClearIN();\r
155 \r
156                 RNDISInterfaceInfo->State.ResponseReady = false;\r
157         }\r
158 }\r
159 \r
160 void RNDIS_Device_ProcessRNDISControlMessage(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)\r
161 {\r
162         /* Note: Only a single buffer is used for both the received message and its response to save SRAM. Because of\r
163                  this, response bytes should be filled in order so that they do not clobber unread data in the buffer. */\r
164 \r
165         RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;\r
166 \r
167         switch (le32_to_cpu(MessageHeader->MessageType))\r
168         {\r
169                 case REMOTE_NDIS_INITIALIZE_MSG:\r
170                         RNDISInterfaceInfo->State.ResponseReady     = true;\r
171 \r
172                         RNDIS_Initialize_Message_t*  INITIALIZE_Message  =\r
173                                        (RNDIS_Initialize_Message_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;\r
174                         RNDIS_Initialize_Complete_t* INITIALIZE_Response =\r
175                                        (RNDIS_Initialize_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;\r
176 \r
177                         INITIALIZE_Response->MessageType            = CPU_TO_LE32(REMOTE_NDIS_INITIALIZE_CMPLT);\r
178                         INITIALIZE_Response->MessageLength          = CPU_TO_LE32(sizeof(RNDIS_Initialize_Complete_t));\r
179                         INITIALIZE_Response->RequestId              = INITIALIZE_Message->RequestId;\r
180                         INITIALIZE_Response->Status                 = CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS);\r
181 \r
182                         INITIALIZE_Response->MajorVersion           = CPU_TO_LE32(REMOTE_NDIS_VERSION_MAJOR);\r
183                         INITIALIZE_Response->MinorVersion           = CPU_TO_LE32(REMOTE_NDIS_VERSION_MINOR);\r
184                         INITIALIZE_Response->DeviceFlags            = CPU_TO_LE32(REMOTE_NDIS_DF_CONNECTIONLESS);\r
185                         INITIALIZE_Response->Medium                 = CPU_TO_LE32(REMOTE_NDIS_MEDIUM_802_3);\r
186                         INITIALIZE_Response->MaxPacketsPerTransfer  = CPU_TO_LE32(1);\r
187                         INITIALIZE_Response->MaxTransferSize        = CPU_TO_LE32(sizeof(RNDIS_Packet_Message_t) + ETHERNET_FRAME_SIZE_MAX);\r
188                         INITIALIZE_Response->PacketAlignmentFactor  = CPU_TO_LE32(0);\r
189                         INITIALIZE_Response->AFListOffset           = CPU_TO_LE32(0);\r
190                         INITIALIZE_Response->AFListSize             = CPU_TO_LE32(0);\r
191 \r
192                         RNDISInterfaceInfo->State.CurrRNDISState    = RNDIS_Initialized;\r
193                         break;\r
194                 case REMOTE_NDIS_HALT_MSG:\r
195                         RNDISInterfaceInfo->State.ResponseReady     = false;\r
196 \r
197                         MessageHeader->MessageLength                = CPU_TO_LE32(0);\r
198 \r
199                         RNDISInterfaceInfo->State.CurrRNDISState    = RNDIS_Uninitialized;\r
200                         break;\r
201                 case REMOTE_NDIS_QUERY_MSG:\r
202                         RNDISInterfaceInfo->State.ResponseReady     = true;\r
203 \r
204                         RNDIS_Query_Message_t*  QUERY_Message       = (RNDIS_Query_Message_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;\r
205                         RNDIS_Query_Complete_t* QUERY_Response      = (RNDIS_Query_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;\r
206                         uint32_t                Query_Oid           = CPU_TO_LE32(QUERY_Message->Oid);\r
207 \r
208                         void*    QueryData    = &RNDISInterfaceInfo->State.RNDISMessageBuffer[sizeof(RNDIS_Message_Header_t) +\r
209                                                                                               le32_to_cpu(QUERY_Message->InformationBufferOffset)];\r
210                         void*    ResponseData = &RNDISInterfaceInfo->State.RNDISMessageBuffer[sizeof(RNDIS_Query_Complete_t)];\r
211                         uint16_t ResponseSize;\r
212 \r
213                         QUERY_Response->MessageType                 = CPU_TO_LE32(REMOTE_NDIS_QUERY_CMPLT);\r
214 \r
215                         if (RNDIS_Device_ProcessNDISQuery(RNDISInterfaceInfo, Query_Oid, QueryData, le32_to_cpu(QUERY_Message->InformationBufferLength),\r
216                                                           ResponseData, &ResponseSize))\r
217                         {\r
218                                 QUERY_Response->Status                  = CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS);\r
219                                 QUERY_Response->MessageLength           = cpu_to_le32(sizeof(RNDIS_Query_Complete_t) + ResponseSize);\r
220 \r
221                                 QUERY_Response->InformationBufferLength = CPU_TO_LE32(ResponseSize);\r
222                                 QUERY_Response->InformationBufferOffset = CPU_TO_LE32(sizeof(RNDIS_Query_Complete_t) - sizeof(RNDIS_Message_Header_t));\r
223                         }\r
224                         else\r
225                         {\r
226                                 QUERY_Response->Status                  = CPU_TO_LE32(REMOTE_NDIS_STATUS_NOT_SUPPORTED);\r
227                                 QUERY_Response->MessageLength           = CPU_TO_LE32(sizeof(RNDIS_Query_Complete_t));\r
228 \r
229                                 QUERY_Response->InformationBufferLength = CPU_TO_LE32(0);\r
230                                 QUERY_Response->InformationBufferOffset = CPU_TO_LE32(0);\r
231                         }\r
232 \r
233                         break;\r
234                 case REMOTE_NDIS_SET_MSG:\r
235                         RNDISInterfaceInfo->State.ResponseReady     = true;\r
236 \r
237                         RNDIS_Set_Message_t*  SET_Message           = (RNDIS_Set_Message_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;\r
238                         RNDIS_Set_Complete_t* SET_Response          = (RNDIS_Set_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;\r
239                         uint32_t              SET_Oid               = le32_to_cpu(SET_Message->Oid);\r
240 \r
241                         SET_Response->MessageType                   = CPU_TO_LE32(REMOTE_NDIS_SET_CMPLT);\r
242                         SET_Response->MessageLength                 = CPU_TO_LE32(sizeof(RNDIS_Set_Complete_t));\r
243                         SET_Response->RequestId                     = SET_Message->RequestId;\r
244 \r
245                         void* SetData = &RNDISInterfaceInfo->State.RNDISMessageBuffer[sizeof(RNDIS_Message_Header_t) +\r
246                                                                                       le32_to_cpu(SET_Message->InformationBufferOffset)];\r
247 \r
248                         SET_Response->Status = RNDIS_Device_ProcessNDISSet(RNDISInterfaceInfo, SET_Oid, SetData,\r
249                                                                            le32_to_cpu(SET_Message->InformationBufferLength)) ?\r
250                                                                            REMOTE_NDIS_STATUS_SUCCESS : REMOTE_NDIS_STATUS_NOT_SUPPORTED;\r
251                         break;\r
252                 case REMOTE_NDIS_RESET_MSG:\r
253                         RNDISInterfaceInfo->State.ResponseReady     = true;\r
254 \r
255                         RNDIS_Reset_Complete_t* RESET_Response      = (RNDIS_Reset_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;\r
256 \r
257                         RESET_Response->MessageType                 = CPU_TO_LE32(REMOTE_NDIS_RESET_CMPLT);\r
258                         RESET_Response->MessageLength               = CPU_TO_LE32(sizeof(RNDIS_Reset_Complete_t));\r
259                         RESET_Response->Status                      = CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS);\r
260                         RESET_Response->AddressingReset             = CPU_TO_LE32(0);\r
261 \r
262                         break;\r
263                 case REMOTE_NDIS_KEEPALIVE_MSG:\r
264                         RNDISInterfaceInfo->State.ResponseReady     = true;\r
265 \r
266                         RNDIS_KeepAlive_Message_t*  KEEPALIVE_Message  =\r
267                                         (RNDIS_KeepAlive_Message_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;\r
268                         RNDIS_KeepAlive_Complete_t* KEEPALIVE_Response =\r
269                                         (RNDIS_KeepAlive_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;\r
270 \r
271                         KEEPALIVE_Response->MessageType             = CPU_TO_LE32(REMOTE_NDIS_KEEPALIVE_CMPLT);\r
272                         KEEPALIVE_Response->MessageLength           = CPU_TO_LE32(sizeof(RNDIS_KeepAlive_Complete_t));\r
273                         KEEPALIVE_Response->RequestId               = KEEPALIVE_Message->RequestId;\r
274                         KEEPALIVE_Response->Status                  = CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS);\r
275 \r
276                         break;\r
277         }\r
278 }\r
279 \r
280 static bool RNDIS_Device_ProcessNDISQuery(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo,\r
281                                           const uint32_t OId,\r
282                                           void* const QueryData,\r
283                                           const uint16_t QuerySize,\r
284                                           void* ResponseData,\r
285                                           uint16_t* const ResponseSize)\r
286 {\r
287         (void)QueryData;\r
288         (void)QuerySize;\r
289 \r
290         switch (OId)\r
291         {\r
292                 case OID_GEN_SUPPORTED_LIST:\r
293                         *ResponseSize = sizeof(AdapterSupportedOIDList);\r
294 \r
295                         memcpy_P(ResponseData, AdapterSupportedOIDList, sizeof(AdapterSupportedOIDList));\r
296 \r
297                         return true;\r
298                 case OID_GEN_PHYSICAL_MEDIUM:\r
299                         *ResponseSize = sizeof(uint32_t);\r
300 \r
301                         /* Indicate that the device is a true ethernet link */\r
302                         *((uint32_t*)ResponseData) = CPU_TO_LE32(0);\r
303 \r
304                         return true;\r
305                 case OID_GEN_HARDWARE_STATUS:\r
306                         *ResponseSize = sizeof(uint32_t);\r
307 \r
308                         *((uint32_t*)ResponseData) = CPU_TO_LE32(NDIS_HardwareStatus_Ready);\r
309 \r
310                         return true;\r
311                 case OID_GEN_MEDIA_SUPPORTED:\r
312                 case OID_GEN_MEDIA_IN_USE:\r
313                         *ResponseSize = sizeof(uint32_t);\r
314 \r
315                         *((uint32_t*)ResponseData) = CPU_TO_LE32(REMOTE_NDIS_MEDIUM_802_3);\r
316 \r
317                         return true;\r
318                 case OID_GEN_VENDOR_ID:\r
319                         *ResponseSize = sizeof(uint32_t);\r
320 \r
321                         /* Vendor ID 0x0xFFFFFF is reserved for vendors who have not purchased a NDIS VID */\r
322                         *((uint32_t*)ResponseData) = CPU_TO_LE32(0x00FFFFFF);\r
323 \r
324                         return true;\r
325                 case OID_GEN_MAXIMUM_FRAME_SIZE:\r
326                 case OID_GEN_TRANSMIT_BLOCK_SIZE:\r
327                 case OID_GEN_RECEIVE_BLOCK_SIZE:\r
328                         *ResponseSize = sizeof(uint32_t);\r
329 \r
330                         *((uint32_t*)ResponseData) = CPU_TO_LE32(ETHERNET_FRAME_SIZE_MAX);\r
331 \r
332                         return true;\r
333                 case OID_GEN_VENDOR_DESCRIPTION:\r
334                         *ResponseSize = (strlen(RNDISInterfaceInfo->Config.AdapterVendorDescription) + 1);\r
335 \r
336                         memcpy(ResponseData, RNDISInterfaceInfo->Config.AdapterVendorDescription, *ResponseSize);\r
337 \r
338                         return true;\r
339                 case OID_GEN_MEDIA_CONNECT_STATUS:\r
340                         *ResponseSize = sizeof(uint32_t);\r
341 \r
342                         *((uint32_t*)ResponseData) = CPU_TO_LE32(REMOTE_NDIS_MEDIA_STATE_CONNECTED);\r
343 \r
344                         return true;\r
345                 case OID_GEN_LINK_SPEED:\r
346                         *ResponseSize = sizeof(uint32_t);\r
347 \r
348                         /* Indicate 10Mb/s link speed */\r
349                         *((uint32_t*)ResponseData) = CPU_TO_LE32(100000);\r
350 \r
351                         return true;\r
352                 case OID_802_3_PERMANENT_ADDRESS:\r
353                 case OID_802_3_CURRENT_ADDRESS:\r
354                         *ResponseSize = sizeof(MAC_Address_t);\r
355 \r
356                         memcpy(ResponseData, &RNDISInterfaceInfo->Config.AdapterMACAddress, sizeof(MAC_Address_t));\r
357 \r
358                         return true;\r
359                 case OID_802_3_MAXIMUM_LIST_SIZE:\r
360                         *ResponseSize = sizeof(uint32_t);\r
361 \r
362                         /* Indicate only one multicast address supported */\r
363                         *((uint32_t*)ResponseData) = CPU_TO_LE32(1);\r
364 \r
365                         return true;\r
366                 case OID_GEN_CURRENT_PACKET_FILTER:\r
367                         *ResponseSize = sizeof(uint32_t);\r
368 \r
369                         *((uint32_t*)ResponseData) = cpu_to_le32(RNDISInterfaceInfo->State.CurrPacketFilter);\r
370 \r
371                         return true;\r
372                 case OID_GEN_XMIT_OK:\r
373                 case OID_GEN_RCV_OK:\r
374                 case OID_GEN_XMIT_ERROR:\r
375                 case OID_GEN_RCV_ERROR:\r
376                 case OID_GEN_RCV_NO_BUFFER:\r
377                 case OID_802_3_RCV_ERROR_ALIGNMENT:\r
378                 case OID_802_3_XMIT_ONE_COLLISION:\r
379                 case OID_802_3_XMIT_MORE_COLLISIONS:\r
380                         *ResponseSize = sizeof(uint32_t);\r
381 \r
382                         /* Unused statistic OIDs - always return 0 for each */\r
383                         *((uint32_t*)ResponseData) = CPU_TO_LE32(0);\r
384 \r
385                         return true;\r
386                 case OID_GEN_MAXIMUM_TOTAL_SIZE:\r
387                         *ResponseSize = sizeof(uint32_t);\r
388 \r
389                         /* Indicate maximum overall buffer (Ethernet frame and RNDIS header) the adapter can handle */\r
390                         *((uint32_t*)ResponseData) = CPU_TO_LE32(RNDIS_MESSAGE_BUFFER_SIZE + ETHERNET_FRAME_SIZE_MAX);\r
391 \r
392                         return true;\r
393                 default:\r
394                         return false;\r
395         }\r
396 }\r
397 \r
398 static bool RNDIS_Device_ProcessNDISSet(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo,\r
399                                         const uint32_t OId,\r
400                                         const void* SetData,\r
401                                         const uint16_t SetSize)\r
402 {\r
403         (void)SetSize;\r
404 \r
405         switch (OId)\r
406         {\r
407                 case OID_GEN_CURRENT_PACKET_FILTER:\r
408                         RNDISInterfaceInfo->State.CurrPacketFilter = le32_to_cpu(*((uint32_t*)SetData));\r
409                         RNDISInterfaceInfo->State.CurrRNDISState   = (RNDISInterfaceInfo->State.CurrPacketFilter) ? RNDIS_Data_Initialized : RNDIS_Initialized;\r
410 \r
411                         return true;\r
412                 case OID_802_3_MULTICAST_LIST:\r
413                         /* Do nothing - throw away the value from the host as it is unused */\r
414 \r
415                         return true;\r
416                 default:\r
417                         return false;\r
418         }\r
419 }\r
420 \r
421 bool RNDIS_Device_IsPacketReceived(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)\r
422 {\r
423         if ((USB_DeviceState != DEVICE_STATE_Configured) ||\r
424             (RNDISInterfaceInfo->State.CurrRNDISState != RNDIS_Data_Initialized))\r
425         {\r
426                 return false;\r
427         }\r
428 \r
429         Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.DataOUTEndpoint.Address);\r
430         return Endpoint_IsOUTReceived();\r
431 }\r
432 \r
433 uint8_t RNDIS_Device_ReadPacket(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo,\r
434                                 void* Buffer,\r
435                                 uint16_t* const PacketLength)\r
436 {\r
437         if ((USB_DeviceState != DEVICE_STATE_Configured) ||\r
438             (RNDISInterfaceInfo->State.CurrRNDISState != RNDIS_Data_Initialized))\r
439         {\r
440                 return ENDPOINT_RWSTREAM_DeviceDisconnected;\r
441         }\r
442 \r
443         Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.DataOUTEndpoint.Address);\r
444 \r
445         *PacketLength = 0;\r
446 \r
447         if (!(Endpoint_IsOUTReceived()))\r
448                 return ENDPOINT_RWSTREAM_NoError;\r
449 \r
450         RNDIS_Packet_Message_t RNDISPacketHeader;\r
451         Endpoint_Read_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_Packet_Message_t), NULL);\r
452 \r
453         if (le32_to_cpu(RNDISPacketHeader.DataLength) > ETHERNET_FRAME_SIZE_MAX)\r
454         {\r
455                 Endpoint_StallTransaction();\r
456 \r
457                 return RNDIS_ERROR_LOGICAL_CMD_FAILED;\r
458         }\r
459 \r
460         *PacketLength = (uint16_t)le32_to_cpu(RNDISPacketHeader.DataLength);\r
461 \r
462         Endpoint_Read_Stream_LE(Buffer, *PacketLength, NULL);\r
463         Endpoint_ClearOUT();\r
464 \r
465         return ENDPOINT_RWSTREAM_NoError;\r
466 }\r
467 \r
468 uint8_t RNDIS_Device_SendPacket(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo,\r
469                                 void* Buffer,\r
470                                 const uint16_t PacketLength)\r
471 {\r
472         uint8_t ErrorCode;\r
473 \r
474         if ((USB_DeviceState != DEVICE_STATE_Configured) ||\r
475             (RNDISInterfaceInfo->State.CurrRNDISState != RNDIS_Data_Initialized))\r
476         {\r
477                 return ENDPOINT_RWSTREAM_DeviceDisconnected;\r
478         }\r
479 \r
480         Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.DataINEndpoint.Address);\r
481 \r
482         if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError)\r
483           return ErrorCode;\r
484 \r
485         RNDIS_Packet_Message_t RNDISPacketHeader;\r
486 \r
487         memset(&RNDISPacketHeader, 0, sizeof(RNDIS_Packet_Message_t));\r
488 \r
489         RNDISPacketHeader.MessageType   = CPU_TO_LE32(REMOTE_NDIS_PACKET_MSG);\r
490         RNDISPacketHeader.MessageLength = cpu_to_le32(sizeof(RNDIS_Packet_Message_t) + PacketLength);\r
491         RNDISPacketHeader.DataOffset    = CPU_TO_LE32(sizeof(RNDIS_Packet_Message_t) - sizeof(RNDIS_Message_Header_t));\r
492         RNDISPacketHeader.DataLength    = cpu_to_le32(PacketLength);\r
493 \r
494         Endpoint_Write_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_Packet_Message_t), NULL);\r
495         Endpoint_Write_Stream_LE(Buffer, PacketLength, NULL);\r
496         Endpoint_ClearIN();\r
497 \r
498         return ENDPOINT_RWSTREAM_NoError;\r
499 }\r
500 \r
501 #endif\r
502 \r