LPCOpen Platform
LPCOpen Platform for NXP LPC Microcontrollers
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
RNDISClassHost.c
Go to the documentation of this file.
1 /*
2  * @brief Host 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 
34 #define __INCLUDE_FROM_USB_DRIVER
35 #include "../../Core/USBMode.h"
36 
37 #if defined(USB_CAN_BE_HOST)
38 
39 #define __INCLUDE_FROM_RNDIS_DRIVER
40 #define __INCLUDE_FROM_RNDIS_HOST_C
41 #include "RNDISClassHost.h"
42 
43 uint8_t RNDIS_Host_ConfigurePipes(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
44  uint16_t ConfigDescriptorSize,
45  void* ConfigDescriptorData)
46 {
47  USB_Descriptor_Endpoint_t* DataINEndpoint = NULL;
48  USB_Descriptor_Endpoint_t* DataOUTEndpoint = NULL;
49  USB_Descriptor_Endpoint_t* NotificationEndpoint = NULL;
50  USB_Descriptor_Interface_t* RNDISControlInterface = NULL;
51  uint8_t portnum = RNDISInterfaceInfo->Config.PortNumber;
52 
53  memset(&RNDISInterfaceInfo->State, 0x00, sizeof(RNDISInterfaceInfo->State));
54 
55  if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
57 
58  RNDISControlInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t);
59 
60  while (!(DataINEndpoint) || !(DataOUTEndpoint) || !(NotificationEndpoint))
61  {
62  if (!(RNDISControlInterface) ||
63  USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
65  {
66  if (NotificationEndpoint)
67  {
68  if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
70  {
72  }
73 
74  DataINEndpoint = NULL;
75  DataOUTEndpoint = NULL;
76  }
77  else
78  {
79  if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
81  {
83  }
84 
85  RNDISControlInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t);
86 
87  NotificationEndpoint = NULL;
88  }
89 
90  continue;
91  }
92 
93  USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);
94 
95  if ((EndpointData->EndpointAddress & ENDPOINT_DIR_MASK) == ENDPOINT_DIR_IN)
96  {
97  if ((EndpointData->Attributes & EP_TYPE_MASK) == EP_TYPE_INTERRUPT)
98  NotificationEndpoint = EndpointData;
99  else
100  DataINEndpoint = EndpointData;
101  }
102  else
103  {
104  DataOUTEndpoint = EndpointData;
105  }
106  }
107 
108  for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++)
109  {
110  uint16_t Size;
111  uint8_t Type;
112  uint8_t Token;
113  uint8_t EndpointAddress;
114  uint8_t InterruptPeriod;
115  bool DoubleBanked;
116 
117  if (PipeNum == RNDISInterfaceInfo->Config.DataINPipeNumber)
118  {
119  Size = le16_to_cpu(DataINEndpoint->EndpointSize);
120  EndpointAddress = DataINEndpoint->EndpointAddress;
121  Token = PIPE_TOKEN_IN;
122  Type = EP_TYPE_BULK;
123  DoubleBanked = RNDISInterfaceInfo->Config.DataINPipeDoubleBank;
124  InterruptPeriod = 0;
125 
126  RNDISInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize;
127  }
128  else if (PipeNum == RNDISInterfaceInfo->Config.DataOUTPipeNumber)
129  {
130  Size = le16_to_cpu(DataOUTEndpoint->EndpointSize);
131  EndpointAddress = DataOUTEndpoint->EndpointAddress;
132  Token = PIPE_TOKEN_OUT;
133  Type = EP_TYPE_BULK;
134  DoubleBanked = RNDISInterfaceInfo->Config.DataOUTPipeDoubleBank;
135  InterruptPeriod = 0;
136 
137  RNDISInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize;
138  }
139  else if (PipeNum == RNDISInterfaceInfo->Config.NotificationPipeNumber)
140  {
141  Size = le16_to_cpu(NotificationEndpoint->EndpointSize);
142  EndpointAddress = NotificationEndpoint->EndpointAddress;
143  Token = PIPE_TOKEN_IN;
144  Type = EP_TYPE_INTERRUPT;
145  DoubleBanked = RNDISInterfaceInfo->Config.NotificationPipeDoubleBank;
146  InterruptPeriod = NotificationEndpoint->PollingIntervalMS;
147 
148  RNDISInterfaceInfo->State.NotificationPipeSize = NotificationEndpoint->EndpointSize;
149  }
150  else
151  {
152  continue;
153  }
154 
155  if (!(Pipe_ConfigurePipe(portnum,PipeNum, Type, Token, EndpointAddress, Size,
156  DoubleBanked ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE)))
157  {
159  }
160 
161  if (InterruptPeriod)
162  Pipe_SetInterruptPeriod(InterruptPeriod);
163  }
164 
165  RNDISInterfaceInfo->State.ControlInterfaceNumber = RNDISControlInterface->InterfaceNumber;
166  RNDISInterfaceInfo->State.IsActive = true;
167 
169 }
170 
171 static uint8_t DCOMP_RNDIS_Host_NextRNDISControlInterface(void* const CurrentDescriptor)
172 {
174 
175  if (Header->Type == DTYPE_Interface)
176  {
178 
179  if ((Interface->Class == CDC_CSCP_CDCClass) &&
180  (Interface->SubClass == CDC_CSCP_ACMSubclass) &&
181  (Interface->Protocol == CDC_CSCP_VendorSpecificProtocol))
182  {
184  }
185  }
186 
188 }
189 
190 static uint8_t DCOMP_RNDIS_Host_NextRNDISDataInterface(void* const CurrentDescriptor)
191 {
193 
194  if (Header->Type == DTYPE_Interface)
195  {
196  USB_Descriptor_Interface_t* Interface = DESCRIPTOR_PCAST(CurrentDescriptor,
198 
199  if ((Interface->Class == CDC_CSCP_CDCDataClass) &&
200  (Interface->SubClass == CDC_CSCP_NoDataSubclass) &&
201  (Interface->Protocol == CDC_CSCP_NoDataProtocol))
202  {
204  }
205  }
206 
208 }
209 
210 static uint8_t DCOMP_RNDIS_Host_NextRNDISInterfaceEndpoint(void* const CurrentDescriptor)
211 {
213 
214  if (Header->Type == DTYPE_Endpoint)
215  {
217 
218  uint8_t EndpointType = (Endpoint->Attributes & EP_TYPE_MASK);
219 
220  if (((EndpointType == EP_TYPE_BULK) || (EndpointType == EP_TYPE_INTERRUPT)) &&
221  !(Pipe_IsEndpointBound(Endpoint->EndpointAddress)))
222  {
224  }
225  }
226  else if (Header->Type == DTYPE_Interface)
227  {
228  return DESCRIPTOR_SEARCH_Fail;
229  }
230 
232 }
233 
234 static uint8_t RNDIS_SendEncapsulatedCommand(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
235  void* Buffer,
236  const uint16_t Length)
237 {
239  {
240  .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
242  .wValue = 0,
243  .wIndex = RNDISInterfaceInfo->State.ControlInterfaceNumber,
244  .wLength = Length,
245  };
246  uint8_t portnum = RNDISInterfaceInfo->Config.PortNumber;
247 
249 
250  return USB_Host_SendControlRequest(portnum,Buffer);
251 }
252 
253 static uint8_t RNDIS_GetEncapsulatedResponse(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
254  void* Buffer,
255  const uint16_t Length)
256 {
258  {
259  .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
261  .wValue = 0,
262  .wIndex = RNDISInterfaceInfo->State.ControlInterfaceNumber,
263  .wLength = Length,
264  };
265  uint8_t portnum = RNDISInterfaceInfo->Config.PortNumber;
266 
268 
269  return USB_Host_SendControlRequest(portnum,Buffer);
270 }
271 
272 uint8_t RNDIS_Host_SendKeepAlive(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo)
273 {
274  uint8_t ErrorCode;
275 
276  RNDIS_KeepAlive_Message_t KeepAliveMessage;
277  RNDIS_KeepAlive_Complete_t KeepAliveMessageResponse;
278 
279  KeepAliveMessage.MessageType = CPU_TO_LE32(REMOTE_NDIS_KEEPALIVE_MSG);
280  KeepAliveMessage.MessageLength = CPU_TO_LE32(sizeof(RNDIS_KeepAlive_Message_t));
281  KeepAliveMessage.RequestId = cpu_to_le32(RNDISInterfaceInfo->State.RequestID++);
282 
283  if ((ErrorCode = RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo, &KeepAliveMessage,
285  {
286  return ErrorCode;
287  }
288 
289  if ((ErrorCode = RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo, &KeepAliveMessageResponse,
291  {
292  return ErrorCode;
293  }
294 
296 }
297 
298 uint8_t RNDIS_Host_InitializeDevice(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo)
299 {
300  uint8_t ErrorCode;
301 
302  RNDIS_Initialize_Message_t InitMessage;
303  RNDIS_Initialize_Complete_t InitMessageResponse;
304 
305  InitMessage.MessageType = CPU_TO_LE32(REMOTE_NDIS_INITIALIZE_MSG);
306  InitMessage.MessageLength = CPU_TO_LE32(sizeof(RNDIS_Initialize_Message_t));
307  InitMessage.RequestId = cpu_to_le32(RNDISInterfaceInfo->State.RequestID++);
308 
309  InitMessage.MajorVersion = CPU_TO_LE32(REMOTE_NDIS_VERSION_MAJOR);
310  InitMessage.MinorVersion = CPU_TO_LE32(REMOTE_NDIS_VERSION_MINOR);
311  InitMessage.MaxTransferSize = cpu_to_le32(RNDISInterfaceInfo->Config.HostMaxPacketSize);
312 
313  if ((ErrorCode = RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo, &InitMessage,
315  {
316  return ErrorCode;
317  }
318 
319  if ((ErrorCode = RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo, &InitMessageResponse,
321  {
322  return ErrorCode;
323  }
324 
325  if (InitMessageResponse.Status != CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS))
327 
328  RNDISInterfaceInfo->State.DeviceMaxPacketSize = le32_to_cpu(InitMessageResponse.MaxTransferSize);
329 
331 }
332 
333 uint8_t RNDIS_Host_SetRNDISProperty(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
334  const uint32_t Oid,
335  void* Buffer,
336  const uint16_t Length)
337 {
338  uint8_t ErrorCode;
339 
340  struct
341  {
342  RNDIS_Set_Message_t SetMessage;
343 
344  /* Temporary fix VLA issue on IAR compiler */
345  #define ContiguousBufferLength 1024
346 
347  uint8_t ContiguousBuffer[ContiguousBufferLength];
348  } SetMessageData;
349 
350  RNDIS_Set_Complete_t SetMessageResponse;
351 
352  SetMessageData.SetMessage.MessageType = CPU_TO_LE32(REMOTE_NDIS_SET_MSG);
353  SetMessageData.SetMessage.MessageLength = cpu_to_le32(sizeof(RNDIS_Set_Message_t) + Length);
354  SetMessageData.SetMessage.RequestId = cpu_to_le32(RNDISInterfaceInfo->State.RequestID++);
355 
356  SetMessageData.SetMessage.Oid = cpu_to_le32(Oid);
357  SetMessageData.SetMessage.InformationBufferLength = cpu_to_le32(Length);
358  SetMessageData.SetMessage.InformationBufferOffset = CPU_TO_LE32(sizeof(RNDIS_Set_Message_t) - sizeof(RNDIS_Message_Header_t));
359  SetMessageData.SetMessage.DeviceVcHandle = CPU_TO_LE32(0);
360 
361  memcpy(&SetMessageData.ContiguousBuffer, Buffer, Length);
362 
363  if ((ErrorCode = RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo, &SetMessageData,
364  SetMessageData.SetMessage.MessageLength)) != HOST_SENDCONTROL_Successful)
365  {
366  return ErrorCode;
367  }
368 
369  if ((ErrorCode = RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo, &SetMessageResponse,
371  {
372  return ErrorCode;
373  }
374 
375  if (SetMessageResponse.Status != CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS))
377 
379 }
380 
382  const uint32_t Oid,
383  void* Buffer,
384  const uint16_t MaxLength)
385 {
386  uint8_t ErrorCode;
387 
388  RNDIS_Query_Message_t QueryMessage;
389 
390  struct
391  {
392  RNDIS_Query_Complete_t QueryMessageResponse;
393 
394  /* Temporary fix VLA issue on IAR compiler */
395  #define ContiguousBufferLength 1024
396 
397  uint8_t ContiguousBuffer[ContiguousBufferLength];
398  } QueryMessageResponseData;
399 
400  QueryMessage.MessageType = CPU_TO_LE32(REMOTE_NDIS_QUERY_MSG);
401  QueryMessage.MessageLength = CPU_TO_LE32(sizeof(RNDIS_Query_Message_t));
402  QueryMessage.RequestId = cpu_to_le32(RNDISInterfaceInfo->State.RequestID++);
403 
404  QueryMessage.Oid = cpu_to_le32(Oid);
405  QueryMessage.InformationBufferLength = CPU_TO_LE32(0);
406  QueryMessage.InformationBufferOffset = CPU_TO_LE32(0);
407  QueryMessage.DeviceVcHandle = CPU_TO_LE32(0);
408 
409  if ((ErrorCode = RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo, &QueryMessage,
411  {
412  return ErrorCode;
413  }
414 
415  if ((ErrorCode = RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo, &QueryMessageResponseData,
416  sizeof(QueryMessageResponseData))) != HOST_SENDCONTROL_Successful)
417  {
418  return ErrorCode;
419  }
420 
421  if (QueryMessageResponseData.QueryMessageResponse.Status != CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS))
423 
424  memcpy(Buffer, &QueryMessageResponseData.ContiguousBuffer, MaxLength);
425 
427 }
428 
430 {
431  bool PacketWaiting;
432  uint8_t portnum = RNDISInterfaceInfo->Config.PortNumber;
433 
434  if ((USB_HostState[portnum] != HOST_STATE_Configured) || !(RNDISInterfaceInfo->State.IsActive))
435  return false;
436 
437  Pipe_SelectPipe(portnum,RNDISInterfaceInfo->Config.DataINPipeNumber);
438 
439  Pipe_Unfreeze();
440  PacketWaiting = Pipe_IsINReceived(portnum);
441  Pipe_Freeze();
442 
443  return PacketWaiting;
444 }
445 
446 uint8_t RNDIS_Host_ReadPacket(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
447  void* Buffer,
448  uint16_t* const PacketLength)
449 {
450  uint8_t ErrorCode;
451  uint8_t portnum = RNDISInterfaceInfo->Config.PortNumber;
452 
453  if ((USB_HostState[portnum] != HOST_STATE_Configured) || !(RNDISInterfaceInfo->State.IsActive))
455 
456  Pipe_SelectPipe(portnum,RNDISInterfaceInfo->Config.DataINPipeNumber);
457  Pipe_Unfreeze();
458 
459  if (!(Pipe_IsReadWriteAllowed(portnum)))
460  {
461  if (Pipe_IsINReceived(portnum))
462  Pipe_ClearIN(portnum);
463 
464  *PacketLength = 0;
465  Pipe_Freeze();
466  return PIPE_RWSTREAM_NoError;
467  }
468 
469  RNDIS_Packet_Message_t DeviceMessage;
470 
471  if ((ErrorCode = Pipe_Read_Stream_LE(portnum,&DeviceMessage, sizeof(RNDIS_Packet_Message_t),
473  {
474  return ErrorCode;
475  }
476 
477  *PacketLength = (uint16_t)le32_to_cpu(DeviceMessage.DataLength);
478 
479  Pipe_Discard_Stream(portnum,DeviceMessage.DataOffset -
481  NULL);
482 
483  Pipe_Read_Stream_LE(portnum,Buffer, *PacketLength, NULL);
484 
485  if (!(Pipe_BytesInPipe(portnum)))
486  Pipe_ClearIN(portnum);
487 
488  Pipe_Freeze();
489 
490  return PIPE_RWSTREAM_NoError;
491 }
492 
493 uint8_t RNDIS_Host_SendPacket(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
494  void* Buffer,
495  const uint16_t PacketLength)
496 {
497  uint8_t ErrorCode;
498  uint8_t portnum = RNDISInterfaceInfo->Config.PortNumber;
499 
500  if ((USB_HostState[portnum] != HOST_STATE_Configured) || !(RNDISInterfaceInfo->State.IsActive))
502 
503  RNDIS_Packet_Message_t DeviceMessage;
504 
505  memset(&DeviceMessage, 0, sizeof(RNDIS_Packet_Message_t));
506  DeviceMessage.MessageType = CPU_TO_LE32(REMOTE_NDIS_PACKET_MSG);
507  DeviceMessage.MessageLength = CPU_TO_LE32(sizeof(RNDIS_Packet_Message_t) + PacketLength);
508  DeviceMessage.DataOffset = CPU_TO_LE32(sizeof(RNDIS_Packet_Message_t) - sizeof(RNDIS_Message_Header_t));
509  DeviceMessage.DataLength = cpu_to_le32(PacketLength);
510 
511  Pipe_SelectPipe(portnum,RNDISInterfaceInfo->Config.DataOUTPipeNumber);
512  Pipe_Unfreeze();
513 
514  if ((ErrorCode = Pipe_Write_Stream_LE(portnum,&DeviceMessage, sizeof(RNDIS_Packet_Message_t),
516  {
517  return ErrorCode;
518  }
519 
520  Pipe_Write_Stream_LE(portnum,Buffer, PacketLength, NULL);
521  Pipe_ClearOUT(portnum);
522 
523  Pipe_Freeze();
524 
525  return PIPE_RWSTREAM_NoError;
526 }
527 
528 #endif
529