LPCOpen Platform
LPCOpen Platform for NXP LPC Microcontrollers
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
RNDISClassDevice.c
Go to the documentation of this file.
1 /*
2  * @brief Device mode driver for the library USB RNDIS Class driver
3  *
4  * @note
5  * Copyright(C) NXP Semiconductors, 2012
6  * Copyright(C) Dean Camera, 2011, 2012
7  * All rights reserved.
8  *
9  * @par
10  * Software that is described herein is for illustrative purposes only
11  * which provides customers with programming information regarding the
12  * LPC products. This software is supplied "AS IS" without any warranties of
13  * any kind, and NXP Semiconductors and its licensor disclaim any and
14  * all warranties, express or implied, including all implied warranties of
15  * merchantability, fitness for a particular purpose and non-infringement of
16  * intellectual property rights. NXP Semiconductors assumes no responsibility
17  * or liability for the use of the software, conveys no license or rights under any
18  * patent, copyright, mask work right, or any other intellectual property rights in
19  * or to any products. NXP Semiconductors reserves the right to make changes
20  * in the software without notification. NXP Semiconductors also makes no
21  * representation or warranty that such application will be suitable for the
22  * specified use without further testing or modification.
23  *
24  * @par
25  * Permission to use, copy, modify, and distribute this software and its
26  * documentation is hereby granted, under NXP Semiconductors' and its
27  * licensor's relevant copyrights in the software, without fee, provided that it
28  * is used in conjunction with NXP Semiconductors microcontrollers. This
29  * copyright, permission, and disclaimer notice must appear in all copies of
30  * this code.
31  */
32 
33 #define __INCLUDE_FROM_USB_DRIVER
34 #include "../../Core/USBMode.h"
35 
36 #if defined(USB_CAN_BE_DEVICE)
37 
38 #define __INCLUDE_FROM_RNDIS_DRIVER
39 #define __INCLUDE_FROM_RNDIS_DEVICE_C
40 #include "RNDISClassDevice.h"
41 
43  {
71  };
72 
74 {
75  if (!(Endpoint_IsSETUPReceived()))
76  return;
77 
78  if (USB_ControlRequest.wIndex != RNDISInterfaceInfo->Config.ControlInterfaceNumber)
79  return;
80 
81  switch (USB_ControlRequest.bRequest)
82  {
85  {
89 
90  RNDIS_Device_ProcessRNDISControlMessage(RNDISInterfaceInfo);
91  }
92 
93  break;
96  {
97  RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
98 
99  if (!(MessageHeader->MessageLength))
100  {
101  RNDISInterfaceInfo->State.RNDISMessageBuffer[0] = 0;
102  MessageHeader->MessageLength = CPU_TO_LE32(1);
103  }
104 
106  Endpoint_Write_Control_Stream_LE(RNDISInterfaceInfo->State.RNDISMessageBuffer, le32_to_cpu(MessageHeader->MessageLength));
108 
109  MessageHeader->MessageLength = CPU_TO_LE32(0);
110  }
111 
112  break;
113  }
114 }
115 
117 {
118  memset(&RNDISInterfaceInfo->State, 0x00, sizeof(RNDISInterfaceInfo->State));
119 
120  for (uint8_t EndpointNum = 1; EndpointNum < ENDPOINT_TOTAL_ENDPOINTS; EndpointNum++)
121  {
122  uint16_t Size;
123  uint8_t Type;
124  uint8_t Direction;
125  bool DoubleBanked;
126 
127  if (EndpointNum == RNDISInterfaceInfo->Config.DataINEndpointNumber)
128  {
129  Size = RNDISInterfaceInfo->Config.DataINEndpointSize;
130  Direction = ENDPOINT_DIR_IN;
131  Type = EP_TYPE_BULK;
132  DoubleBanked = RNDISInterfaceInfo->Config.DataINEndpointDoubleBank;
133  }
134  else if (EndpointNum == RNDISInterfaceInfo->Config.DataOUTEndpointNumber)
135  {
136  Size = RNDISInterfaceInfo->Config.DataOUTEndpointSize;
137  Direction = ENDPOINT_DIR_OUT;
138  Type = EP_TYPE_BULK;
139  DoubleBanked = RNDISInterfaceInfo->Config.DataOUTEndpointDoubleBank;
140  }
141  else if (EndpointNum == RNDISInterfaceInfo->Config.NotificationEndpointNumber)
142  {
143  Size = RNDISInterfaceInfo->Config.NotificationEndpointSize;
144  Direction = ENDPOINT_DIR_IN;
145  Type = EP_TYPE_INTERRUPT;
146  DoubleBanked = RNDISInterfaceInfo->Config.NotificationEndpointDoubleBank;
147  }
148  else
149  {
150  continue;
151  }
152 
153  if (!(Endpoint_ConfigureEndpoint(EndpointNum, Type, Direction, Size,
154  DoubleBanked ? ENDPOINT_BANK_DOUBLE : ENDPOINT_BANK_SINGLE)))
155  {
156  return false;
157  }
158  }
159 
160  return true;
161 }
162 
163 void RNDIS_Device_USBTask(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)
164 {
166  return;
167 
169 
170  if (Endpoint_IsINReady() && RNDISInterfaceInfo->State.ResponseReady)
171  {
173  {
174  .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
176  .wValue = CPU_TO_LE16(0),
177  .wIndex = CPU_TO_LE16(0),
178  .wLength = CPU_TO_LE16(0),
179  };
180 
181  Endpoint_Write_Stream_LE(&Notification, sizeof(USB_Request_Header_t), NULL);
182 
184 
185  RNDISInterfaceInfo->State.ResponseReady = false;
186  }
187 }
188 
190 {
191  /* Note: Only a single buffer is used for both the received message and its response to save SRAM. Because of
192  this, response bytes should be filled in order so that they do not clobber unread data in the buffer. */
193 
194  RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
195 
196  switch (le32_to_cpu(MessageHeader->MessageType))
197  {
199  {
200  RNDISInterfaceInfo->State.ResponseReady = true;
201 
202  RNDIS_Initialize_Message_t* INITIALIZE_Message =
203  (RNDIS_Initialize_Message_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
204  RNDIS_Initialize_Complete_t* INITIALIZE_Response =
206 
207  INITIALIZE_Response->MessageType = CPU_TO_LE32(REMOTE_NDIS_INITIALIZE_CMPLT);
208  INITIALIZE_Response->MessageLength = CPU_TO_LE32(sizeof(RNDIS_Initialize_Complete_t));
209  INITIALIZE_Response->RequestId = INITIALIZE_Message->RequestId;
210  INITIALIZE_Response->Status = CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS);
211 
212  INITIALIZE_Response->MajorVersion = CPU_TO_LE32(REMOTE_NDIS_VERSION_MAJOR);
213  INITIALIZE_Response->MinorVersion = CPU_TO_LE32(REMOTE_NDIS_VERSION_MINOR);
214  INITIALIZE_Response->DeviceFlags = CPU_TO_LE32(REMOTE_NDIS_DF_CONNECTIONLESS);
215  INITIALIZE_Response->Medium = CPU_TO_LE32(REMOTE_NDIS_MEDIUM_802_3);
216  INITIALIZE_Response->MaxPacketsPerTransfer = CPU_TO_LE32(1);
217  INITIALIZE_Response->MaxTransferSize = CPU_TO_LE32(sizeof(RNDIS_Packet_Message_t) + ETHERNET_FRAME_SIZE_MAX);
218  INITIALIZE_Response->PacketAlignmentFactor = CPU_TO_LE32(0);
219  INITIALIZE_Response->AFListOffset = CPU_TO_LE32(0);
220  INITIALIZE_Response->AFListSize = CPU_TO_LE32(0);
221 
222  RNDISInterfaceInfo->State.CurrRNDISState = RNDIS_Initialized;
223  break;
224  }
226  {
227  RNDISInterfaceInfo->State.ResponseReady = false;
228 
229  MessageHeader->MessageLength = CPU_TO_LE32(0);
230 
231  RNDISInterfaceInfo->State.CurrRNDISState = RNDIS_Uninitialized;
232  break;
233  }
235  {
236  RNDISInterfaceInfo->State.ResponseReady = true;
237 
238  RNDIS_Query_Message_t* QUERY_Message = (RNDIS_Query_Message_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
239  RNDIS_Query_Complete_t* QUERY_Response = (RNDIS_Query_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
240  uint32_t Query_Oid = CPU_TO_LE32(QUERY_Message->Oid);
241 
242  void* QueryData = &RNDISInterfaceInfo->State.RNDISMessageBuffer[sizeof(RNDIS_Message_Header_t) +
243  le32_to_cpu(QUERY_Message->InformationBufferOffset)];
244  void* ResponseData = &RNDISInterfaceInfo->State.RNDISMessageBuffer[sizeof(RNDIS_Query_Complete_t)];
245  uint16_t ResponseSize;
246 
247  QUERY_Response->MessageType = CPU_TO_LE32(REMOTE_NDIS_QUERY_CMPLT);
248 
249  if (RNDIS_Device_ProcessNDISQuery(RNDISInterfaceInfo, Query_Oid, QueryData, le32_to_cpu(QUERY_Message->InformationBufferLength),
250  ResponseData, &ResponseSize))
251  {
252  QUERY_Response->Status = CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS);
253  QUERY_Response->MessageLength = cpu_to_le32(sizeof(RNDIS_Query_Complete_t) + ResponseSize);
254 
255  QUERY_Response->InformationBufferLength = CPU_TO_LE32(ResponseSize);
256  QUERY_Response->InformationBufferOffset = CPU_TO_LE32(sizeof(RNDIS_Query_Complete_t) - sizeof(RNDIS_Message_Header_t));
257  }
258  else
259  {
260  QUERY_Response->Status = CPU_TO_LE32(REMOTE_NDIS_STATUS_NOT_SUPPORTED);
261  QUERY_Response->MessageLength = CPU_TO_LE32(sizeof(RNDIS_Query_Complete_t));
262 
263  QUERY_Response->InformationBufferLength = CPU_TO_LE32(0);
264  QUERY_Response->InformationBufferOffset = CPU_TO_LE32(0);
265  }
266 
267  break;
268  }
269  case REMOTE_NDIS_SET_MSG:
270  {
271  RNDISInterfaceInfo->State.ResponseReady = true;
272 
273  RNDIS_Set_Message_t* SET_Message = (RNDIS_Set_Message_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
274  RNDIS_Set_Complete_t* SET_Response = (RNDIS_Set_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
275  uint32_t SET_Oid = le32_to_cpu(SET_Message->Oid);
276 
277  SET_Response->MessageType = CPU_TO_LE32(REMOTE_NDIS_SET_CMPLT);
278  SET_Response->MessageLength = CPU_TO_LE32(sizeof(RNDIS_Set_Complete_t));
279  SET_Response->RequestId = SET_Message->RequestId;
280 
281  void* SetData = &RNDISInterfaceInfo->State.RNDISMessageBuffer[sizeof(RNDIS_Message_Header_t) +
282  le32_to_cpu(SET_Message->InformationBufferOffset)];
283 
284  SET_Response->Status = RNDIS_Device_ProcessNDISSet(RNDISInterfaceInfo, SET_Oid, SetData,
285  le32_to_cpu(SET_Message->InformationBufferLength)) ?
287  break;
288  }
290  {
291  RNDISInterfaceInfo->State.ResponseReady = true;
292 
293  RNDIS_Reset_Complete_t* RESET_Response = (RNDIS_Reset_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
294 
295  RESET_Response->MessageType = CPU_TO_LE32(REMOTE_NDIS_RESET_CMPLT);
296  RESET_Response->MessageLength = CPU_TO_LE32(sizeof(RNDIS_Reset_Complete_t));
297  RESET_Response->Status = CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS);
298  RESET_Response->AddressingReset = CPU_TO_LE32(0);
299 
300  break;
301  }
303  {
304  RNDISInterfaceInfo->State.ResponseReady = true;
305 
306  RNDIS_KeepAlive_Message_t* KEEPALIVE_Message =
307  (RNDIS_KeepAlive_Message_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
308  RNDIS_KeepAlive_Complete_t* KEEPALIVE_Response =
309  (RNDIS_KeepAlive_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
310 
311  KEEPALIVE_Response->MessageType = CPU_TO_LE32(REMOTE_NDIS_KEEPALIVE_CMPLT);
312  KEEPALIVE_Response->MessageLength = CPU_TO_LE32(sizeof(RNDIS_KeepAlive_Complete_t));
313  KEEPALIVE_Response->RequestId = KEEPALIVE_Message->RequestId;
314  KEEPALIVE_Response->Status = CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS);
315 
316  break;
317  }
318  }
319 }
320 
321 static bool RNDIS_Device_ProcessNDISQuery(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo,
322  const uint32_t OId,
323  void* const QueryData,
324  const uint16_t QuerySize,
325  void* ResponseData,
326  uint16_t* const ResponseSize)
327 {
328  (void)QueryData;
329  (void)QuerySize;
330 
331  switch (OId)
332  {
334  *ResponseSize = sizeof(AdapterSupportedOIDList);
335 
336  memcpy_P(ResponseData, AdapterSupportedOIDList, sizeof(AdapterSupportedOIDList));
337 
338  return true;
340  *ResponseSize = sizeof(uint32_t);
341 
342  /* Indicate that the device is a true ethernet link */
343  *((uint32_t*)ResponseData) = CPU_TO_LE32(0);
344 
345  return true;
347  *ResponseSize = sizeof(uint32_t);
348 
349  *((uint32_t*)ResponseData) = CPU_TO_LE32(NDIS_HardwareStatus_Ready);
350 
351  return true;
354  *ResponseSize = sizeof(uint32_t);
355 
356  *((uint32_t*)ResponseData) = CPU_TO_LE32(REMOTE_NDIS_MEDIUM_802_3);
357 
358  return true;
359  case OID_GEN_VENDOR_ID:
360  *ResponseSize = sizeof(uint32_t);
361 
362  /* Vendor ID 0x0xFFFFFF is reserved for vendors who have not purchased a NDIS VID */
363  *((uint32_t*)ResponseData) = CPU_TO_LE32(0x00FFFFFF);
364 
365  return true;
369  *ResponseSize = sizeof(uint32_t);
370 
371  *((uint32_t*)ResponseData) = CPU_TO_LE32(ETHERNET_FRAME_SIZE_MAX);
372 
373  return true;
375  *ResponseSize = (strlen(RNDISInterfaceInfo->Config.AdapterVendorDescription) + 1);
376 
377  memcpy(ResponseData, RNDISInterfaceInfo->Config.AdapterVendorDescription, *ResponseSize);
378 
379  return true;
381  *ResponseSize = sizeof(uint32_t);
382 
384 
385  return true;
386  case OID_GEN_LINK_SPEED:
387  *ResponseSize = sizeof(uint32_t);
388 
389  /* Indicate 10Mb/s link speed */
390  *((uint32_t*)ResponseData) = CPU_TO_LE32(100000);
391 
392  return true;
395  *ResponseSize = sizeof(MAC_Address_t);
396 
397  memcpy(ResponseData, &RNDISInterfaceInfo->Config.AdapterMACAddress, sizeof(MAC_Address_t));
398 
399  return true;
401  *ResponseSize = sizeof(uint32_t);
402 
403  /* Indicate only one multicast address supported */
404  *((uint32_t*)ResponseData) = CPU_TO_LE32(1);
405 
406  return true;
408  *ResponseSize = sizeof(uint32_t);
409 
410  *((uint32_t*)ResponseData) = cpu_to_le32(RNDISInterfaceInfo->State.CurrPacketFilter);
411 
412  return true;
413  case OID_GEN_XMIT_OK:
414  case OID_GEN_RCV_OK:
415  case OID_GEN_XMIT_ERROR:
416  case OID_GEN_RCV_ERROR:
421  *ResponseSize = sizeof(uint32_t);
422 
423  /* Unused statistic OIDs - always return 0 for each */
424  *((uint32_t*)ResponseData) = CPU_TO_LE32(0);
425 
426  return true;
428  *ResponseSize = sizeof(uint32_t);
429 
430  /* Indicate maximum overall buffer (Ethernet frame and RNDIS header) the adapter can handle */
432 
433  return true;
434  default:
435  return false;
436  }
437 }
438 
439 static bool RNDIS_Device_ProcessNDISSet(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo,
440  const uint32_t OId,
441  const void* SetData,
442  const uint16_t SetSize)
443 {
444  (void)SetSize;
445 
446  switch (OId)
447  {
449  RNDISInterfaceInfo->State.CurrPacketFilter = le32_to_cpu(*((uint32_t*)SetData));
450  RNDISInterfaceInfo->State.CurrRNDISState = le32_to_cpu((RNDISInterfaceInfo->State.CurrPacketFilter) ?
452 
453  return true;
455  /* Do nothing - throw away the value from the host as it is unused */
456 
457  return true;
458  default:
459  return false;
460  }
461 }
462 
464 {
466  (RNDISInterfaceInfo->State.CurrRNDISState != RNDIS_Data_Initialized))
467  {
468  return false;
469  }
470 
472  return Endpoint_IsOUTReceived();
473 }
474 
475 uint8_t RNDIS_Device_ReadPacket(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo,
476  void* Buffer,
477  uint16_t* const PacketLength)
478 {
480  (RNDISInterfaceInfo->State.CurrRNDISState != RNDIS_Data_Initialized))
481  {
483  }
484 
486 
487  *PacketLength = 0;
488 
489  if (!(Endpoint_IsOUTReceived()))
491 
492  RNDIS_Packet_Message_t RNDISPacketHeader;
493  Endpoint_Read_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_Packet_Message_t), NULL);
494 
495  if (le32_to_cpu(RNDISPacketHeader.DataLength) > ETHERNET_FRAME_SIZE_MAX)
496  {
498 
500  }
501 
502  *PacketLength = (uint16_t)le32_to_cpu(RNDISPacketHeader.DataLength);
503 
504  Endpoint_Read_Stream_LE(Buffer, *PacketLength, NULL);
506 
508 }
509 
510 uint8_t RNDIS_Device_SendPacket(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo,
511  void* Buffer,
512  const uint16_t PacketLength)
513 {
514  uint8_t ErrorCode;
515 
517  (RNDISInterfaceInfo->State.CurrRNDISState != RNDIS_Data_Initialized))
518  {
520  }
521 
523 
525  return ErrorCode;
526 
527  RNDIS_Packet_Message_t RNDISPacketHeader;
528 
529  memset(&RNDISPacketHeader, 0, sizeof(RNDIS_Packet_Message_t));
530 
531  RNDISPacketHeader.MessageType = CPU_TO_LE32(REMOTE_NDIS_PACKET_MSG);
532  RNDISPacketHeader.MessageLength = cpu_to_le32(sizeof(RNDIS_Packet_Message_t) + PacketLength);
533  RNDISPacketHeader.DataOffset = CPU_TO_LE32(sizeof(RNDIS_Packet_Message_t) - sizeof(RNDIS_Message_Header_t));
534  RNDISPacketHeader.DataLength = cpu_to_le32(PacketLength);
535 
536  Endpoint_Write_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_Packet_Message_t), NULL);
537  Endpoint_Write_Stream_LE(Buffer, PacketLength, NULL);
539 
541 }
542 
543 #endif
544