| LPCOpen Platform v1.03 LPCOpen Platform for NXP LPC Microcontrollers

- Main Page
- Modules
- Data Structures
- Files
- Related Pages

- File List
- Globals

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)
56 return CDC_ENUMERROR_InvalidConfigDescriptor;
57
58 while (!(DataINEndpoint) || !(DataOUTEndpoint) || !(NotificationEndpoint))
59 {
60 if (!(CDCControlInterface) ||
61 USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
62 DCOMP_CDC_Host_NextCDCInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
63 {
64 if (NotificationEndpoint)
65 {
66 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
67 DCOMP_CDC_Host_NextCDCDataInterface) != DESCRIPTOR_SEARCH_COMP_Found)
68 {
69 return CDC_ENUMERROR_NoCompatibleInterfaceFound;
70 }
71
72 DataINEndpoint = NULL;
73 DataOUTEndpoint = NULL;
74 }
75 else
76 {
77 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
78 DCOMP_CDC_Host_NextCDCControlInterface) != DESCRIPTOR_SEARCH_COMP_Found)
79 {
80 return CDC_ENUMERROR_NoCompatibleInterfaceFound;
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 {
156 return CDC_ENUMERROR_PipeConfigurationFailed;
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 {
173 USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
174
175 if (Header->Type == DTYPE_Interface)
176 {
177 USB_Descriptor_Interface_t* Interface = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Interface_t);
178
179 if ((Interface->Class == CDC_CSCP_CDCClass) &&
180 (Interface->SubClass == CDC_CSCP_ACMSubclass) &&
181 (Interface->Protocol == CDC_CSCP_ATCommandProtocol))
182 {
183 return DESCRIPTOR_SEARCH_Found;
184 }
185 }
186
187 return DESCRIPTOR_SEARCH_NotFound;
188 }
189
190 static uint8_t DCOMP_CDC_Host_NextCDCDataInterface(void* const CurrentDescriptor)
191 {
192 USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
193
194 if (Header->Type == DTYPE_Interface)
195 {
196 USB_Descriptor_Interface_t* Interface = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Interface_t);
197
198 if ((Interface->Class == CDC_CSCP_CDCDataClass) &&
199 (Interface->SubClass == CDC_CSCP_NoDataSubclass) &&
200 (Interface->Protocol == CDC_CSCP_NoDataProtocol))
201 {
202 return DESCRIPTOR_SEARCH_Found;
203 }
204 }
205
206 return DESCRIPTOR_SEARCH_NotFound;
207 }
208
209 static uint8_t DCOMP_CDC_Host_NextCDCInterfaceEndpoint(void* const CurrentDescriptor)
210 {
211 USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
212
213 if (Header->Type == DTYPE_Endpoint)
214 {
215 USB_Descriptor_Endpoint_t* Endpoint = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Endpoint_t);
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 {
222 return DESCRIPTOR_SEARCH_Found;
223 }
224 }
225 else if (Header->Type == DTYPE_Interface)
226 {
227 return DESCRIPTOR_SEARCH_Fail;
228 }
229
230 return DESCRIPTOR_SEARCH_NotFound;
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 {
275 USB_ControlRequest = (USB_Request_Header_t)
276 {
277 .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
278 .bRequest = CDC_REQ_SetLineEncoding,
279 .wValue = 0,
280 .wIndex = CDCInterfaceInfo->State.ControlInterfaceNumber,
281 .wLength = sizeof(CDCInterfaceInfo->State.LineEncoding),
282 };
283 uint8_t portnum = CDCInterfaceInfo->Config.PortNumber;
284
285 Pipe_SelectPipe(portnum,PIPE_CONTROLPIPE);
286
287 return USB_Host_SendControlRequest(portnum,&CDCInterfaceInfo->State.LineEncoding);
288 }
289
290 uint8_t CDC_Host_SendControlLineStateChange(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
291 {
292 USB_ControlRequest = (USB_Request_Header_t)
293 {
294 .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
295 .bRequest = CDC_REQ_SetControlLineState,
296 .wValue = CDCInterfaceInfo->State.ControlLineStates.HostToDevice,
297 .wIndex = CDCInterfaceInfo->State.ControlInterfaceNumber,
298 .wLength = 0,
299 };
300 uint8_t portnum = CDCInterfaceInfo->Config.PortNumber;
301
302 Pipe_SelectPipe(portnum,PIPE_CONTROLPIPE);
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 {
310 USB_ControlRequest = (USB_Request_Header_t)
311 {
312 .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
313 .bRequest = CDC_REQ_SendBreak,
314 .wValue = Duration,
315 .wIndex = CDCInterfaceInfo->State.ControlInterfaceNumber,
316 .wLength = 0,
317 };
318 uint8_t portnum = CDCInterfaceInfo->Config.PortNumber;
319
320 Pipe_SelectPipe(portnum,PIPE_CONTROLPIPE);
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))
333 return PIPE_READYWAIT_DeviceDisconnected;
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))
351 return PIPE_READYWAIT_DeviceDisconnected;
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))
369 return PIPE_READYWAIT_DeviceDisconnected;
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))
451 return PIPE_READYWAIT_DeviceDisconnected;
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 {
513 if (USB_HostState == HOST_STATE_Unattached)
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
524 void CDC_Host_Event_Stub(void)
525 {
526
527 }
528
529 #endif
530