| 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
CDCClassDevice.c
Go to the documentation of this file.
1 /*
2 * @brief Device 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_DEVICE)
38
39 #define __INCLUDE_FROM_CDC_DRIVER
40 #define __INCLUDE_FROM_CDC_DEVICE_C
41 #include "CDCClassDevice.h"
42
43 void CDC_Device_ProcessControlRequest(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
44 {
45 if (!(Endpoint_IsSETUPReceived(CDCInterfaceInfo->Config.PortNumber)))
46 return;
47
48 if (USB_ControlRequest.wIndex != CDCInterfaceInfo->Config.ControlInterfaceNumber)
49 return;
50
51 switch (USB_ControlRequest.bRequest)
52 {
53 case CDC_REQ_GetLineEncoding:
54 if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
55 {
56 Endpoint_ClearSETUP(CDCInterfaceInfo->Config.PortNumber);
57
58 while (!(Endpoint_IsINReady(CDCInterfaceInfo->Config.PortNumber)));
59
60 Endpoint_Write_32_LE(CDCInterfaceInfo->Config.PortNumber, CDCInterfaceInfo->State.LineEncoding.BaudRateBPS);
61 Endpoint_Write_8(CDCInterfaceInfo->Config.PortNumber, CDCInterfaceInfo->State.LineEncoding.CharFormat);
62 Endpoint_Write_8(CDCInterfaceInfo->Config.PortNumber, CDCInterfaceInfo->State.LineEncoding.ParityType);
63 Endpoint_Write_8(CDCInterfaceInfo->Config.PortNumber, CDCInterfaceInfo->State.LineEncoding.DataBits);
64
65 Endpoint_ClearIN(CDCInterfaceInfo->Config.PortNumber);
66 Endpoint_ClearStatusStage(CDCInterfaceInfo->Config.PortNumber);
67 }
68
69 break;
70 case CDC_REQ_SetLineEncoding:
71 if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
72 {
73 Endpoint_ClearSETUP(CDCInterfaceInfo->Config.PortNumber);
74
75 while (!(Endpoint_IsOUTReceived(CDCInterfaceInfo->Config.PortNumber)));
76
77 CDCInterfaceInfo->State.LineEncoding.BaudRateBPS = Endpoint_Read_32_LE(CDCInterfaceInfo->Config.PortNumber);
78 CDCInterfaceInfo->State.LineEncoding.CharFormat = Endpoint_Read_8(CDCInterfaceInfo->Config.PortNumber);
79 CDCInterfaceInfo->State.LineEncoding.ParityType = Endpoint_Read_8(CDCInterfaceInfo->Config.PortNumber);
80 CDCInterfaceInfo->State.LineEncoding.DataBits = Endpoint_Read_8(CDCInterfaceInfo->Config.PortNumber);
81
82 Endpoint_ClearOUT(CDCInterfaceInfo->Config.PortNumber);
83 Endpoint_ClearStatusStage(CDCInterfaceInfo->Config.PortNumber);
84
85 EVENT_CDC_Device_LineEncodingChanged(CDCInterfaceInfo);
86 }
87
88 break;
89 case CDC_REQ_SetControlLineState:
90 if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
91 {
92 Endpoint_ClearSETUP(CDCInterfaceInfo->Config.PortNumber);
93 Endpoint_ClearStatusStage(CDCInterfaceInfo->Config.PortNumber);
94
95 CDCInterfaceInfo->State.ControlLineStates.HostToDevice = USB_ControlRequest.wValue;
96
97 EVENT_CDC_Device_ControLineStateChanged(CDCInterfaceInfo);
98 }
99
100 break;
101 case CDC_REQ_SendBreak:
102 if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
103 {
104 Endpoint_ClearSETUP(CDCInterfaceInfo->Config.PortNumber);
105 Endpoint_ClearStatusStage(CDCInterfaceInfo->Config.PortNumber);
106
107 EVENT_CDC_Device_BreakSent(CDCInterfaceInfo, (uint8_t)USB_ControlRequest.wValue);
108 }
109
110 break;
111 }
112 }
113
114 bool CDC_Device_ConfigureEndpoints(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
115 {
116 memset(&CDCInterfaceInfo->State, 0x00, sizeof(CDCInterfaceInfo->State));
117
118 for (uint8_t EndpointNum = 1; EndpointNum < ENDPOINT_TOTAL_ENDPOINTS(CDCInterfaceInfo->Config.PortNumber); EndpointNum++)
119 {
120 uint16_t Size;
121 uint8_t Type;
122 uint8_t Direction;
123 bool DoubleBanked;
124
125 if (EndpointNum == CDCInterfaceInfo->Config.DataINEndpointNumber)
126 {
127 Size = CDCInterfaceInfo->Config.DataINEndpointSize;
128 Direction = ENDPOINT_DIR_IN;
129 Type = EP_TYPE_BULK;
130 DoubleBanked = CDCInterfaceInfo->Config.DataINEndpointDoubleBank;
131 }
132 else if (EndpointNum == CDCInterfaceInfo->Config.DataOUTEndpointNumber)
133 {
134 Size = CDCInterfaceInfo->Config.DataOUTEndpointSize;
135 Direction = ENDPOINT_DIR_OUT;
136 Type = EP_TYPE_BULK;
137 DoubleBanked = CDCInterfaceInfo->Config.DataOUTEndpointDoubleBank;
138 }
139 else if (EndpointNum == CDCInterfaceInfo->Config.NotificationEndpointNumber)
140 {
141 Size = CDCInterfaceInfo->Config.NotificationEndpointSize;
142 Direction = ENDPOINT_DIR_IN;
143 Type = EP_TYPE_INTERRUPT;
144 DoubleBanked = CDCInterfaceInfo->Config.NotificationEndpointDoubleBank;
145 }
146 else
147 {
148 continue;
149 }
150
151 if (!(Endpoint_ConfigureEndpoint(CDCInterfaceInfo->Config.PortNumber, EndpointNum, Type, Direction, Size,
152 DoubleBanked ? ENDPOINT_BANK_DOUBLE : ENDPOINT_BANK_SINGLE)))
153 {
154 return false;
155 }
156 }
157
158 return true;
159 }
160
161 void CDC_Device_USBTask(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
162 {
163 if ((USB_DeviceState[CDCInterfaceInfo->Config.PortNumber] != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
164 return;
165
166 #if !defined(NO_CLASS_DRIVER_AUTOFLUSH)
167 CDC_Device_Flush(CDCInterfaceInfo);
168 #endif
169 }
170
171 uint8_t CDC_Device_SendString(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,
172 const char* const String)
173 {
174 if ((USB_DeviceState[CDCInterfaceInfo->Config.PortNumber] != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
175 return ENDPOINT_RWSTREAM_DeviceDisconnected;
176
177 Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.PortNumber, CDCInterfaceInfo->Config.DataINEndpointNumber);
178 Endpoint_Write_Stream_LE(CDCInterfaceInfo->Config.PortNumber, String, strlen(String), NULL);
179 Endpoint_ClearIN(CDCInterfaceInfo->Config.PortNumber);
180 return ENDPOINT_RWSTREAM_NoError;
181 }
182
183 uint8_t CDC_Device_SendData(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,
184 const char* const Buffer,
185 const uint16_t Length)
186 {
187 if ((USB_DeviceState[CDCInterfaceInfo->Config.PortNumber] != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
188 return ENDPOINT_RWSTREAM_DeviceDisconnected;
189
190 Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.PortNumber, CDCInterfaceInfo->Config.DataINEndpointNumber);
191 Endpoint_Write_Stream_LE(CDCInterfaceInfo->Config.PortNumber, Buffer, Length, NULL);
192 Endpoint_ClearIN(CDCInterfaceInfo->Config.PortNumber);
193 return ENDPOINT_RWSTREAM_NoError;
194 }
195
196 uint8_t CDC_Device_SendByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,
197 const uint8_t Data)
198 {
199 if ((USB_DeviceState[CDCInterfaceInfo->Config.PortNumber] != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
200 return ENDPOINT_RWSTREAM_DeviceDisconnected;
201
202 Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.PortNumber, CDCInterfaceInfo->Config.DataINEndpointNumber);
203
204 if (!(Endpoint_IsReadWriteAllowed(CDCInterfaceInfo->Config.PortNumber)))
205 {
206 Endpoint_ClearIN(CDCInterfaceInfo->Config.PortNumber);
207
208 uint8_t ErrorCode;
209
210 if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError)
211 return ErrorCode;
212 }
213
214 Endpoint_Write_8(CDCInterfaceInfo->Config.PortNumber, Data);
215 return ENDPOINT_READYWAIT_NoError;
216 }
217
218 uint8_t CDC_Device_Flush(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
219 {
220 if ((USB_DeviceState[CDCInterfaceInfo->Config.PortNumber] != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
221 return ENDPOINT_RWSTREAM_DeviceDisconnected;
222
223 uint8_t ErrorCode;
224
225 Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.PortNumber, CDCInterfaceInfo->Config.DataINEndpointNumber);
226
227 if (!(Endpoint_BytesInEndpoint(CDCInterfaceInfo->Config.PortNumber)))
228 return ENDPOINT_READYWAIT_NoError;
229
230 bool BankFull = !(Endpoint_IsReadWriteAllowed(CDCInterfaceInfo->Config.PortNumber));
231
232 Endpoint_ClearIN(CDCInterfaceInfo->Config.PortNumber);
233
234 if (BankFull)
235 {
236 if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError)
237 return ErrorCode;
238
239 Endpoint_ClearIN(CDCInterfaceInfo->Config.PortNumber);
240 }
241
242 return ENDPOINT_READYWAIT_NoError;
243 }
244
245 uint16_t CDC_Device_BytesReceived(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
246 {
247 if ((USB_DeviceState[CDCInterfaceInfo->Config.PortNumber] != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
248 return 0;
249
250 Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.PortNumber, CDCInterfaceInfo->Config.DataOUTEndpointNumber);
251
252 if (Endpoint_IsOUTReceived(CDCInterfaceInfo->Config.PortNumber))
253 {
254 if (!(Endpoint_BytesInEndpoint(CDCInterfaceInfo->Config.PortNumber)))
255 {
256 Endpoint_ClearOUT(CDCInterfaceInfo->Config.PortNumber);
257 return 0;
258 }
259 else
260 {
261 return Endpoint_BytesInEndpoint(CDCInterfaceInfo->Config.PortNumber);
262 }
263 }
264 else
265 {
266 return 0;
267 }
268 }
269
270 int16_t CDC_Device_ReceiveByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
271 {
272 if ((USB_DeviceState[CDCInterfaceInfo->Config.PortNumber] != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
273 return -1;
274
275 int16_t ReceivedByte = -1;
276
277 Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.PortNumber, CDCInterfaceInfo->Config.DataOUTEndpointNumber);
278
279 if (Endpoint_IsOUTReceived(CDCInterfaceInfo->Config.PortNumber))
280 {
281 if (Endpoint_BytesInEndpoint(CDCInterfaceInfo->Config.PortNumber)){
282 ReceivedByte = Endpoint_Read_8(CDCInterfaceInfo->Config.PortNumber);
283 //Endpoint_ClearOUT();
284 }
285
286 if (!(Endpoint_BytesInEndpoint(CDCInterfaceInfo->Config.PortNumber)))
287 Endpoint_ClearOUT(CDCInterfaceInfo->Config.PortNumber);
288 }
289
290 return ReceivedByte;
291 }
292
293 void CDC_Device_SendControlLineStateChange(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
294 {
295 if ((USB_DeviceState[CDCInterfaceInfo->Config.PortNumber] != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
296 return;
297
298 Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.PortNumber, CDCInterfaceInfo->Config.NotificationEndpointNumber);
299
300 USB_Request_Header_t Notification = (USB_Request_Header_t)
301 {
302 .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
303 .bRequest = CDC_NOTIF_SerialState,
304 .wValue = CPU_TO_LE16(0),
305 .wIndex = CPU_TO_LE16(0),
306 .wLength = CPU_TO_LE16(sizeof(CDCInterfaceInfo->State.ControlLineStates.DeviceToHost)),
307 };
308
309 Endpoint_Write_Stream_LE(CDCInterfaceInfo->Config.PortNumber, &Notification, sizeof(USB_Request_Header_t), NULL);
310 Endpoint_Write_Stream_LE(CDCInterfaceInfo->Config.PortNumber, &CDCInterfaceInfo->State.ControlLineStates.DeviceToHost,
311 sizeof(CDCInterfaceInfo->State.ControlLineStates.DeviceToHost),
312 NULL);
313 Endpoint_ClearIN(CDCInterfaceInfo->Config.PortNumber);
314 }
315
316 #if (defined(FDEV_SETUP_STREAM) && (!defined(__IAR_SYSTEMS_ICC__) || (_DLIB_FILE_DESCRIPTOR == 1)))
317 void CDC_Device_CreateStream(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,
318 FILE* const Stream)
319 {
320 *Stream = (FILE)FDEV_SETUP_STREAM(CDC_Device_putchar, CDC_Device_getchar, _FDEV_SETUP_RW);
321 fdev_set_udata(Stream, CDCInterfaceInfo);
322 }
323
324 void CDC_Device_CreateBlockingStream(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,
325 FILE* const Stream)
326 {
327 *Stream = (FILE)FDEV_SETUP_STREAM(CDC_Device_putchar, CDC_Device_getchar_Blocking, _FDEV_SETUP_RW);
328 fdev_set_udata(Stream, CDCInterfaceInfo);
329 }
330
331 static int CDC_Device_putchar(char c,
332 FILE* Stream)
333 {
334 return CDC_Device_SendByte((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream), c) ? _FDEV_ERR : 0;
335 }
336
337 static int CDC_Device_getchar(FILE* Stream)
338 {
339 int16_t ReceivedByte = CDC_Device_ReceiveByte((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream));
340
341 if (ReceivedByte < 0)
342 return _FDEV_EOF;
343
344 return ReceivedByte;
345 }
346
347 static int CDC_Device_getchar_Blocking(FILE* Stream)
348 {
349 int16_t ReceivedByte;
350
351 while ((ReceivedByte = CDC_Device_ReceiveByte((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream))) < 0)
352 {
353 if (USB_DeviceState[corenum] == DEVICE_STATE_Unattached)
354 return _FDEV_EOF;
355
356 CDC_Device_USBTask((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream));
357 USB_USBTask();
358 }
359
360 return ReceivedByte;
361 }
362 #endif
363
364 void CDC_Device_Event_Stub(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
365 {
366
367 }
368
369 void CDC_Device_Event_Stub2(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, const uint8_t Duration)
370 {
371 }
372 #endif
373