LPCOpen Platform
LPCOpen Platform for NXP LPC Microcontrollers
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
CDCClassHost.c
Go to the documentation of this file.
1 /*
2  * @brief Host mode driver for the library USB CDC 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_CDC_DRIVER
40 #define __INCLUDE_FROM_CDC_HOST_C
41 #include "CDCClassHost.h"
42 
43 uint8_t CDC_Host_ConfigurePipes(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo,
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* CDCControlInterface = NULL;
51  uint8_t portnum = CDCInterfaceInfo->Config.PortNumber;
52 
53  memset(&CDCInterfaceInfo->State, 0x00, sizeof(CDCInterfaceInfo->State));
54 
55  if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
57 
58  while (!(DataINEndpoint) || !(DataOUTEndpoint) || !(NotificationEndpoint))
59  {
60  if (!(CDCControlInterface) ||
61  USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
63  {
64  if (NotificationEndpoint)
65  {
66  if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
68  {
70  }
71 
72  DataINEndpoint = NULL;
73  DataOUTEndpoint = NULL;
74  }
75  else
76  {
77  if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
79  {
81  }
82 
83  CDCControlInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t);
84 
85  NotificationEndpoint = NULL;
86  }
87 
88  continue;
89  }
90 
91  USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);
92 
93  if ((EndpointData->EndpointAddress & ENDPOINT_DIR_MASK) == ENDPOINT_DIR_IN)
94  {
95  if ((EndpointData->Attributes & EP_TYPE_MASK) == EP_TYPE_INTERRUPT)
96  NotificationEndpoint = EndpointData;
97  else
98  DataINEndpoint = EndpointData;
99  }
100  else
101  {
102  DataOUTEndpoint = EndpointData;
103  }
104  }
105 
106  for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++)
107  {
108  uint16_t Size;
109  uint8_t Type;
110  uint8_t Token;
111  uint8_t EndpointAddress;
112  uint8_t InterruptPeriod;
113  bool DoubleBanked;
114 
115  if (PipeNum == CDCInterfaceInfo->Config.DataINPipeNumber)
116  {
117  Size = le16_to_cpu(DataINEndpoint->EndpointSize);
118  EndpointAddress = DataINEndpoint->EndpointAddress;
119  Token = PIPE_TOKEN_IN;
120  Type = EP_TYPE_BULK;
121  DoubleBanked = CDCInterfaceInfo->Config.DataINPipeDoubleBank;
122  InterruptPeriod = 0;
123 
124  CDCInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize;
125  }
126  else if (PipeNum == CDCInterfaceInfo->Config.DataOUTPipeNumber)
127  {
128  Size = le16_to_cpu(DataOUTEndpoint->EndpointSize);
129  EndpointAddress = DataOUTEndpoint->EndpointAddress;
130  Token = PIPE_TOKEN_OUT;
131  Type = EP_TYPE_BULK;
132  DoubleBanked = CDCInterfaceInfo->Config.DataOUTPipeDoubleBank;
133  InterruptPeriod = 0;
134 
135  CDCInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize;
136  }
137  else if (PipeNum == CDCInterfaceInfo->Config.NotificationPipeNumber)
138  {
139  Size = le16_to_cpu(NotificationEndpoint->EndpointSize);
140  EndpointAddress = NotificationEndpoint->EndpointAddress;
141  Token = PIPE_TOKEN_IN;
142  Type = EP_TYPE_INTERRUPT;
143  DoubleBanked = CDCInterfaceInfo->Config.NotificationPipeDoubleBank;
144  InterruptPeriod = NotificationEndpoint->PollingIntervalMS;
145 
146  CDCInterfaceInfo->State.NotificationPipeSize = NotificationEndpoint->EndpointSize;
147  }
148  else
149  {
150  continue;
151  }
152 
153  if (!(Pipe_ConfigurePipe(portnum,PipeNum, Type, Token, EndpointAddress, Size,
154  DoubleBanked ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE)))
155  {
157  }
158 
159  if (InterruptPeriod)
160  Pipe_SetInterruptPeriod(InterruptPeriod);
161  }
162 
163  CDCInterfaceInfo->State.ControlInterfaceNumber = CDCControlInterface->InterfaceNumber;
164  CDCInterfaceInfo->State.ControlLineStates.HostToDevice = (CDC_CONTROL_LINE_OUT_RTS | CDC_CONTROL_LINE_OUT_DTR);
165  CDCInterfaceInfo->State.ControlLineStates.DeviceToHost = (CDC_CONTROL_LINE_IN_DCD | CDC_CONTROL_LINE_IN_DSR);
166  CDCInterfaceInfo->State.IsActive = true;
167 
168  return CDC_ENUMERROR_NoError;
169 }
170 
171 static uint8_t DCOMP_CDC_Host_NextCDCControlInterface(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_ATCommandProtocol))
182  {
184  }
185  }
186 
188 }
189 
190 static uint8_t DCOMP_CDC_Host_NextCDCDataInterface(void* const CurrentDescriptor)
191 {
193 
194  if (Header->Type == DTYPE_Interface)
195  {
197 
198  if ((Interface->Class == CDC_CSCP_CDCDataClass) &&
199  (Interface->SubClass == CDC_CSCP_NoDataSubclass) &&
200  (Interface->Protocol == CDC_CSCP_NoDataProtocol))
201  {
203  }
204  }
205 
207 }
208 
209 static uint8_t DCOMP_CDC_Host_NextCDCInterfaceEndpoint(void* const CurrentDescriptor)
210 {
212 
213  if (Header->Type == DTYPE_Endpoint)
214  {
216 
217  uint8_t EndpointType = (Endpoint->Attributes & EP_TYPE_MASK);
218 
219  if (((EndpointType == EP_TYPE_BULK) || (EndpointType == EP_TYPE_INTERRUPT)) &&
220  !(Pipe_IsEndpointBound(Endpoint->EndpointAddress)))
221  {
223  }
224  }
225  else if (Header->Type == DTYPE_Interface)
226  {
227  return DESCRIPTOR_SEARCH_Fail;
228  }
229 
231 }
232 
233 void CDC_Host_USBTask(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
234 {
235  uint8_t portnum = CDCInterfaceInfo->Config.PortNumber;
236 
237  if ((USB_HostState[portnum] != HOST_STATE_Configured) || !(CDCInterfaceInfo->State.IsActive))
238  return;
239 
240  Pipe_SelectPipe(portnum,CDCInterfaceInfo->Config.NotificationPipeNumber);
241  Pipe_Unfreeze();
242 
243  if (Pipe_IsINReceived(portnum))
244  {
245  USB_Request_Header_t Notification;
246  Pipe_Read_Stream_LE(portnum,&Notification, sizeof(USB_Request_Header_t), NULL);
247 
248  if ((Notification.bRequest == CDC_NOTIF_SerialState) &&
249  (Notification.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)))
250  {
251  Pipe_Read_Stream_LE(portnum,
252  &CDCInterfaceInfo->State.ControlLineStates.DeviceToHost,
253  sizeof(CDCInterfaceInfo->State.ControlLineStates.DeviceToHost),
254  NULL);
255 
256  Pipe_ClearIN(portnum);
257 
258  EVENT_CDC_Host_ControLineStateChanged(CDCInterfaceInfo);
259  }
260  else
261  {
262  Pipe_ClearIN(portnum);
263  }
264  }
265 
266  Pipe_Freeze();
267 
268  #if !defined(NO_CLASS_DRIVER_AUTOFLUSH)
269  CDC_Host_Flush(CDCInterfaceInfo);
270  #endif
271 }
272 
273 uint8_t CDC_Host_SetLineEncoding(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
274 {
276  {
277  .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
279  .wValue = 0,
280  .wIndex = CDCInterfaceInfo->State.ControlInterfaceNumber,
281  .wLength = sizeof(CDCInterfaceInfo->State.LineEncoding),
282  };
283  uint8_t portnum = CDCInterfaceInfo->Config.PortNumber;
284 
286 
287  return USB_Host_SendControlRequest(portnum,&CDCInterfaceInfo->State.LineEncoding);
288 }
289 
291 {
293  {
294  .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
296  .wValue = CDCInterfaceInfo->State.ControlLineStates.HostToDevice,
297  .wIndex = CDCInterfaceInfo->State.ControlInterfaceNumber,
298  .wLength = 0,
299  };
300  uint8_t portnum = CDCInterfaceInfo->Config.PortNumber;
301 
303 
304  return USB_Host_SendControlRequest(portnum,NULL);
305 }
306 
307 uint8_t CDC_Host_SendBreak(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo,
308  const uint8_t Duration)
309 {
311  {
312  .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
314  .wValue = Duration,
315  .wIndex = CDCInterfaceInfo->State.ControlInterfaceNumber,
316  .wLength = 0,
317  };
318  uint8_t portnum = CDCInterfaceInfo->Config.PortNumber;
319 
321 
322  return USB_Host_SendControlRequest(portnum,NULL);
323 }
324 
325 uint8_t CDC_Host_SendData(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo,
326  const uint8_t* const Buffer,
327  const uint16_t Length)
328 {
329  uint8_t portnum = CDCInterfaceInfo->Config.PortNumber;
330  uint8_t ErrorCode;
331 
332  if ((USB_HostState[portnum] != HOST_STATE_Configured) || !(CDCInterfaceInfo->State.IsActive))
334 
335  Pipe_SelectPipe(portnum,CDCInterfaceInfo->Config.DataOUTPipeNumber);
336 
337  Pipe_Unfreeze();
338  ErrorCode = Pipe_Write_Stream_LE(portnum,Buffer, Length, NULL);
339  Pipe_Freeze();
340 
341  return ErrorCode;
342 }
343 
344 uint8_t CDC_Host_SendString(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo,
345  const char* const String)
346 {
347  uint8_t portnum = CDCInterfaceInfo->Config.PortNumber;
348  uint8_t ErrorCode;
349 
350  if ((USB_HostState[portnum] != HOST_STATE_Configured) || !(CDCInterfaceInfo->State.IsActive))
352 
353  Pipe_SelectPipe(portnum,CDCInterfaceInfo->Config.DataOUTPipeNumber);
354 
355  Pipe_Unfreeze();
356  ErrorCode = Pipe_Write_Stream_LE(portnum,String, strlen(String), NULL);
357  Pipe_Freeze();
358 
359  return ErrorCode;
360 }
361 
362 uint8_t CDC_Host_SendByte(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo,
363  const uint8_t Data)
364 {
365  uint8_t portnum = CDCInterfaceInfo->Config.PortNumber;
366  uint8_t ErrorCode;
367 
368  if ((USB_HostState[portnum] != HOST_STATE_Configured) || !(CDCInterfaceInfo->State.IsActive))
370 
371  Pipe_SelectPipe(portnum,CDCInterfaceInfo->Config.DataOUTPipeNumber);
372  Pipe_Unfreeze();
373 
374  if (!(Pipe_IsReadWriteAllowed(portnum)))
375  {
376  Pipe_ClearOUT(portnum);
377 
378  if ((ErrorCode = Pipe_WaitUntilReady(portnum)) != PIPE_READYWAIT_NoError)
379  return ErrorCode;
380  }
381 
382  Pipe_Write_8(portnum,Data);
383  Pipe_Freeze();
384 
385  return PIPE_READYWAIT_NoError;
386 }
387 
388 uint16_t CDC_Host_BytesReceived(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
389 {
390  uint8_t portnum = CDCInterfaceInfo->Config.PortNumber;
391 
392  if ((USB_HostState[portnum] != HOST_STATE_Configured) || !(CDCInterfaceInfo->State.IsActive))
393  return 0;
394 
395  Pipe_SelectPipe(portnum,CDCInterfaceInfo->Config.DataINPipeNumber);
396  Pipe_Unfreeze();
397 
398  if (Pipe_IsINReceived(portnum))
399  {
400  if (!(Pipe_BytesInPipe(portnum)))
401  {
402  Pipe_ClearIN(portnum);
403  Pipe_Freeze();
404  return 0;
405  }
406  else
407  {
408  Pipe_Freeze();
409  return Pipe_BytesInPipe(portnum);
410  }
411  }
412  else
413  {
414  Pipe_Freeze();
415 
416  return 0;
417  }
418 }
419 
420 int16_t CDC_Host_ReceiveByte(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
421 {
422  uint8_t portnum = CDCInterfaceInfo->Config.PortNumber;
423  int16_t ReceivedByte = -1;
424 
425  if ((USB_HostState[portnum] != HOST_STATE_Configured) || !(CDCInterfaceInfo->State.IsActive))
426  return -1;
427 
428  Pipe_SelectPipe(portnum,CDCInterfaceInfo->Config.DataINPipeNumber);
429  Pipe_Unfreeze();
430 
431  if (Pipe_IsINReceived(portnum))
432  {
433  if (Pipe_BytesInPipe(portnum))
434  ReceivedByte = Pipe_Read_8(portnum);
435 
436  if (!(Pipe_BytesInPipe(portnum)))
437  Pipe_ClearIN(portnum);
438  }
439 
440  Pipe_Freeze();
441 
442  return ReceivedByte;
443 }
444 
445 uint8_t CDC_Host_Flush(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
446 {
447  uint8_t portnum = CDCInterfaceInfo->Config.PortNumber;
448  uint8_t ErrorCode;
449 
450  if ((USB_HostState[portnum] != HOST_STATE_Configured) || !(CDCInterfaceInfo->State.IsActive))
452 
453  Pipe_SelectPipe(portnum,CDCInterfaceInfo->Config.DataOUTPipeNumber);
454  Pipe_Unfreeze();
455 
456  if (!(Pipe_BytesInPipe(portnum)))
457  return PIPE_READYWAIT_NoError;
458 
459  bool BankFull = !(Pipe_IsReadWriteAllowed(portnum));
460 
461  Pipe_ClearOUT(portnum);
462 
463  if (BankFull)
464  {
465  if ((ErrorCode = Pipe_WaitUntilReady(portnum)) != PIPE_READYWAIT_NoError)
466  return ErrorCode;
467 
468  Pipe_ClearOUT(portnum);
469  }
470 
471  Pipe_Freeze();
472 
473  return PIPE_READYWAIT_NoError;
474 }
475 
476 #if (defined(FDEV_SETUP_STREAM) && (!defined(__IAR_SYSTEMS_ICC__) || (_DLIB_FILE_DESCRIPTOR == 1)))
477 void CDC_Host_CreateStream(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo,
478  FILE* const Stream)
479 {
480  *Stream = (FILE)FDEV_SETUP_STREAM(CDC_Host_putchar, CDC_Host_getchar, _FDEV_SETUP_RW);
481  fdev_set_udata(Stream, CDCInterfaceInfo);
482 }
483 
484 void CDC_Host_CreateBlockingStream(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo,
485  FILE* const Stream)
486 {
487  *Stream = (FILE)FDEV_SETUP_STREAM(CDC_Host_putchar, CDC_Host_getchar_Blocking, _FDEV_SETUP_RW);
488  fdev_set_udata(Stream, CDCInterfaceInfo);
489 }
490 
491 static int CDC_Host_putchar(char c,
492  FILE* Stream)
493 {
494  return CDC_Host_SendByte((USB_ClassInfo_CDC_Host_t*)fdev_get_udata(Stream), c) ? _FDEV_ERR : 0;
495 }
496 
497 static int CDC_Host_getchar(FILE* Stream)
498 {
499  int16_t ReceivedByte = CDC_Host_ReceiveByte((USB_ClassInfo_CDC_Host_t*)fdev_get_udata(Stream));
500 
501  if (ReceivedByte < 0)
502  return _FDEV_EOF;
503 
504  return ReceivedByte;
505 }
506 
507 static int CDC_Host_getchar_Blocking(FILE* Stream)
508 {
509  int16_t ReceivedByte;
510 
511  while ((ReceivedByte = CDC_Host_ReceiveByte((USB_ClassInfo_CDC_Host_t*)fdev_get_udata(Stream))) < 0)
512  {
514  return _FDEV_EOF;
515 
516  CDC_Host_USBTask((USB_ClassInfo_CDC_Host_t*)fdev_get_udata(Stream));
517  USB_USBTask();
518  }
519 
520  return ReceivedByte;
521 }
522 #endif
523 
525 {
526 
527 }
528 
529 #endif
530