2 * @brief Device mode driver for the library USB CDC Class driver
\r
5 * Copyright(C) NXP Semiconductors, 2012
\r
6 * Copyright(C) Dean Camera, 2011, 2012
\r
7 * All rights reserved.
\r
10 * Software that is described herein is for illustrative purposes only
\r
11 * which provides customers with programming information regarding the
\r
12 * LPC products. This software is supplied "AS IS" without any warranties of
\r
13 * any kind, and NXP Semiconductors and its licensor disclaim any and
\r
14 * all warranties, express or implied, including all implied warranties of
\r
15 * merchantability, fitness for a particular purpose and non-infringement of
\r
16 * intellectual property rights. NXP Semiconductors assumes no responsibility
\r
17 * or liability for the use of the software, conveys no license or rights under any
\r
18 * patent, copyright, mask work right, or any other intellectual property rights in
\r
19 * or to any products. NXP Semiconductors reserves the right to make changes
\r
20 * in the software without notification. NXP Semiconductors also makes no
\r
21 * representation or warranty that such application will be suitable for the
\r
22 * specified use without further testing or modification.
\r
25 * Permission to use, copy, modify, and distribute this software and its
\r
26 * documentation is hereby granted, under NXP Semiconductors' and its
\r
27 * licensor's relevant copyrights in the software, without fee, provided that it
\r
28 * is used in conjunction with NXP Semiconductors microcontrollers. This
\r
29 * copyright, permission, and disclaimer notice must appear in all copies of
\r
34 #define __INCLUDE_FROM_USB_DRIVER
\r
35 #include "../../Core/USBMode.h"
\r
37 #if defined(USB_CAN_BE_DEVICE)
\r
39 #define __INCLUDE_FROM_CDC_DRIVER
\r
40 #define __INCLUDE_FROM_CDC_DEVICE_C
\r
41 #include "CDCClassDevice.h"
\r
43 void CDC_Device_ProcessControlRequest(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
\r
45 if (!(Endpoint_IsSETUPReceived(CDCInterfaceInfo->Config.PortNumber)))
\r
48 if (USB_ControlRequest.wIndex != CDCInterfaceInfo->Config.ControlInterfaceNumber)
\r
51 switch (USB_ControlRequest.bRequest)
\r
53 case CDC_REQ_GetLineEncoding:
\r
54 if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
\r
56 Endpoint_ClearSETUP(CDCInterfaceInfo->Config.PortNumber);
\r
58 while (!(Endpoint_IsINReady(CDCInterfaceInfo->Config.PortNumber)));
\r
60 Endpoint_Write_32_LE(CDCInterfaceInfo->Config.PortNumber, CDCInterfaceInfo->State.LineEncoding.BaudRateBPS);
\r
61 Endpoint_Write_8(CDCInterfaceInfo->Config.PortNumber, CDCInterfaceInfo->State.LineEncoding.CharFormat);
\r
62 Endpoint_Write_8(CDCInterfaceInfo->Config.PortNumber, CDCInterfaceInfo->State.LineEncoding.ParityType);
\r
63 Endpoint_Write_8(CDCInterfaceInfo->Config.PortNumber, CDCInterfaceInfo->State.LineEncoding.DataBits);
\r
65 Endpoint_ClearIN(CDCInterfaceInfo->Config.PortNumber);
\r
66 Endpoint_ClearStatusStage(CDCInterfaceInfo->Config.PortNumber);
\r
70 case CDC_REQ_SetLineEncoding:
\r
71 if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
\r
73 Endpoint_ClearSETUP(CDCInterfaceInfo->Config.PortNumber);
\r
75 while (!(Endpoint_IsOUTReceived(CDCInterfaceInfo->Config.PortNumber)));
\r
77 CDCInterfaceInfo->State.LineEncoding.BaudRateBPS = Endpoint_Read_32_LE(CDCInterfaceInfo->Config.PortNumber);
\r
78 CDCInterfaceInfo->State.LineEncoding.CharFormat = Endpoint_Read_8(CDCInterfaceInfo->Config.PortNumber);
\r
79 CDCInterfaceInfo->State.LineEncoding.ParityType = Endpoint_Read_8(CDCInterfaceInfo->Config.PortNumber);
\r
80 CDCInterfaceInfo->State.LineEncoding.DataBits = Endpoint_Read_8(CDCInterfaceInfo->Config.PortNumber);
\r
82 Endpoint_ClearOUT(CDCInterfaceInfo->Config.PortNumber);
\r
83 Endpoint_ClearStatusStage(CDCInterfaceInfo->Config.PortNumber);
\r
85 EVENT_CDC_Device_LineEncodingChanged(CDCInterfaceInfo);
\r
89 case CDC_REQ_SetControlLineState:
\r
90 if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
\r
92 Endpoint_ClearSETUP(CDCInterfaceInfo->Config.PortNumber);
\r
93 Endpoint_ClearStatusStage(CDCInterfaceInfo->Config.PortNumber);
\r
95 CDCInterfaceInfo->State.ControlLineStates.HostToDevice = USB_ControlRequest.wValue;
\r
97 EVENT_CDC_Device_ControLineStateChanged(CDCInterfaceInfo);
\r
101 case CDC_REQ_SendBreak:
\r
102 if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
\r
104 Endpoint_ClearSETUP(CDCInterfaceInfo->Config.PortNumber);
\r
105 Endpoint_ClearStatusStage(CDCInterfaceInfo->Config.PortNumber);
\r
107 EVENT_CDC_Device_BreakSent(CDCInterfaceInfo, (uint8_t)USB_ControlRequest.wValue);
\r
114 bool CDC_Device_ConfigureEndpoints(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
\r
116 memset(&CDCInterfaceInfo->State, 0x00, sizeof(CDCInterfaceInfo->State));
\r
118 for (uint8_t EndpointNum = 1; EndpointNum < ENDPOINT_TOTAL_ENDPOINTS(CDCInterfaceInfo->Config.PortNumber); EndpointNum++)
\r
125 if (EndpointNum == CDCInterfaceInfo->Config.DataINEndpointNumber)
\r
127 Size = CDCInterfaceInfo->Config.DataINEndpointSize;
\r
128 Direction = ENDPOINT_DIR_IN;
\r
129 Type = EP_TYPE_BULK;
\r
130 DoubleBanked = CDCInterfaceInfo->Config.DataINEndpointDoubleBank;
\r
132 else if (EndpointNum == CDCInterfaceInfo->Config.DataOUTEndpointNumber)
\r
134 Size = CDCInterfaceInfo->Config.DataOUTEndpointSize;
\r
135 Direction = ENDPOINT_DIR_OUT;
\r
136 Type = EP_TYPE_BULK;
\r
137 DoubleBanked = CDCInterfaceInfo->Config.DataOUTEndpointDoubleBank;
\r
139 else if (EndpointNum == CDCInterfaceInfo->Config.NotificationEndpointNumber)
\r
141 Size = CDCInterfaceInfo->Config.NotificationEndpointSize;
\r
142 Direction = ENDPOINT_DIR_IN;
\r
143 Type = EP_TYPE_INTERRUPT;
\r
144 DoubleBanked = CDCInterfaceInfo->Config.NotificationEndpointDoubleBank;
\r
151 if (!(Endpoint_ConfigureEndpoint(CDCInterfaceInfo->Config.PortNumber, EndpointNum, Type, Direction, Size,
\r
152 DoubleBanked ? ENDPOINT_BANK_DOUBLE : ENDPOINT_BANK_SINGLE)))
\r
161 void CDC_Device_USBTask(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
\r
163 if ((USB_DeviceState[CDCInterfaceInfo->Config.PortNumber] != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
\r
166 #if !defined(NO_CLASS_DRIVER_AUTOFLUSH)
\r
167 CDC_Device_Flush(CDCInterfaceInfo);
\r
171 uint8_t CDC_Device_SendString(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,
\r
172 const char* const String)
\r
174 if ((USB_DeviceState[CDCInterfaceInfo->Config.PortNumber] != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
\r
175 return ENDPOINT_RWSTREAM_DeviceDisconnected;
\r
177 Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.PortNumber, CDCInterfaceInfo->Config.DataINEndpointNumber);
\r
178 Endpoint_Write_Stream_LE(CDCInterfaceInfo->Config.PortNumber, String, strlen(String), NULL);
\r
179 Endpoint_ClearIN(CDCInterfaceInfo->Config.PortNumber);
\r
180 return ENDPOINT_RWSTREAM_NoError;
\r
183 uint8_t CDC_Device_SendData(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,
\r
184 const char* const Buffer,
\r
185 const uint16_t Length)
\r
187 if ((USB_DeviceState[CDCInterfaceInfo->Config.PortNumber] != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
\r
188 return ENDPOINT_RWSTREAM_DeviceDisconnected;
\r
190 Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.PortNumber, CDCInterfaceInfo->Config.DataINEndpointNumber);
\r
191 Endpoint_Write_Stream_LE(CDCInterfaceInfo->Config.PortNumber, Buffer, Length, NULL);
\r
192 Endpoint_ClearIN(CDCInterfaceInfo->Config.PortNumber);
\r
193 return ENDPOINT_RWSTREAM_NoError;
\r
196 uint8_t CDC_Device_SendByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,
\r
197 const uint8_t Data)
\r
199 if ((USB_DeviceState[CDCInterfaceInfo->Config.PortNumber] != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
\r
200 return ENDPOINT_RWSTREAM_DeviceDisconnected;
\r
202 Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.PortNumber, CDCInterfaceInfo->Config.DataINEndpointNumber);
\r
204 if (!(Endpoint_IsReadWriteAllowed(CDCInterfaceInfo->Config.PortNumber)))
\r
206 Endpoint_ClearIN(CDCInterfaceInfo->Config.PortNumber);
\r
210 if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError)
\r
214 Endpoint_Write_8(CDCInterfaceInfo->Config.PortNumber, Data);
\r
215 return ENDPOINT_READYWAIT_NoError;
\r
218 uint8_t CDC_Device_Flush(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
\r
220 if ((USB_DeviceState[CDCInterfaceInfo->Config.PortNumber] != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
\r
221 return ENDPOINT_RWSTREAM_DeviceDisconnected;
\r
225 Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.PortNumber, CDCInterfaceInfo->Config.DataINEndpointNumber);
\r
227 if (!(Endpoint_BytesInEndpoint(CDCInterfaceInfo->Config.PortNumber)))
\r
228 return ENDPOINT_READYWAIT_NoError;
\r
230 bool BankFull = !(Endpoint_IsReadWriteAllowed(CDCInterfaceInfo->Config.PortNumber));
\r
232 Endpoint_ClearIN(CDCInterfaceInfo->Config.PortNumber);
\r
236 if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError)
\r
239 Endpoint_ClearIN(CDCInterfaceInfo->Config.PortNumber);
\r
242 return ENDPOINT_READYWAIT_NoError;
\r
245 uint16_t CDC_Device_BytesReceived(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
\r
247 if ((USB_DeviceState[CDCInterfaceInfo->Config.PortNumber] != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
\r
250 Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.PortNumber, CDCInterfaceInfo->Config.DataOUTEndpointNumber);
\r
252 if (Endpoint_IsOUTReceived(CDCInterfaceInfo->Config.PortNumber))
\r
254 if (!(Endpoint_BytesInEndpoint(CDCInterfaceInfo->Config.PortNumber)))
\r
256 Endpoint_ClearOUT(CDCInterfaceInfo->Config.PortNumber);
\r
261 return Endpoint_BytesInEndpoint(CDCInterfaceInfo->Config.PortNumber);
\r
270 int16_t CDC_Device_ReceiveByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
\r
272 if ((USB_DeviceState[CDCInterfaceInfo->Config.PortNumber] != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
\r
275 int16_t ReceivedByte = -1;
\r
277 Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.PortNumber, CDCInterfaceInfo->Config.DataOUTEndpointNumber);
\r
279 if (Endpoint_IsOUTReceived(CDCInterfaceInfo->Config.PortNumber))
\r
281 if (Endpoint_BytesInEndpoint(CDCInterfaceInfo->Config.PortNumber)){
\r
282 ReceivedByte = Endpoint_Read_8(CDCInterfaceInfo->Config.PortNumber);
\r
283 //Endpoint_ClearOUT();
\r
286 if (!(Endpoint_BytesInEndpoint(CDCInterfaceInfo->Config.PortNumber)))
\r
287 Endpoint_ClearOUT(CDCInterfaceInfo->Config.PortNumber);
\r
290 return ReceivedByte;
\r
293 void CDC_Device_SendControlLineStateChange(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
\r
295 if ((USB_DeviceState[CDCInterfaceInfo->Config.PortNumber] != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
\r
298 Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.PortNumber, CDCInterfaceInfo->Config.NotificationEndpointNumber);
\r
300 USB_Request_Header_t Notification = (USB_Request_Header_t)
\r
302 .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
\r
303 .bRequest = CDC_NOTIF_SerialState,
\r
304 .wValue = CPU_TO_LE16(0),
\r
305 .wIndex = CPU_TO_LE16(0),
\r
306 .wLength = CPU_TO_LE16(sizeof(CDCInterfaceInfo->State.ControlLineStates.DeviceToHost)),
\r
309 Endpoint_Write_Stream_LE(CDCInterfaceInfo->Config.PortNumber, &Notification, sizeof(USB_Request_Header_t), NULL);
\r
310 Endpoint_Write_Stream_LE(CDCInterfaceInfo->Config.PortNumber, &CDCInterfaceInfo->State.ControlLineStates.DeviceToHost,
\r
311 sizeof(CDCInterfaceInfo->State.ControlLineStates.DeviceToHost),
\r
313 Endpoint_ClearIN(CDCInterfaceInfo->Config.PortNumber);
\r
316 #if (defined(FDEV_SETUP_STREAM) && (!defined(__IAR_SYSTEMS_ICC__) || (_DLIB_FILE_DESCRIPTOR == 1)))
\r
317 void CDC_Device_CreateStream(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,
\r
318 FILE* const Stream)
\r
320 *Stream = (FILE)FDEV_SETUP_STREAM(CDC_Device_putchar, CDC_Device_getchar, _FDEV_SETUP_RW);
\r
321 fdev_set_udata(Stream, CDCInterfaceInfo);
\r
324 void CDC_Device_CreateBlockingStream(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,
\r
325 FILE* const Stream)
\r
327 *Stream = (FILE)FDEV_SETUP_STREAM(CDC_Device_putchar, CDC_Device_getchar_Blocking, _FDEV_SETUP_RW);
\r
328 fdev_set_udata(Stream, CDCInterfaceInfo);
\r
331 static int CDC_Device_putchar(char c,
\r
334 return CDC_Device_SendByte((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream), c) ? _FDEV_ERR : 0;
\r
337 static int CDC_Device_getchar(FILE* Stream)
\r
339 int16_t ReceivedByte = CDC_Device_ReceiveByte((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream));
\r
341 if (ReceivedByte < 0)
\r
344 return ReceivedByte;
\r
347 static int CDC_Device_getchar_Blocking(FILE* Stream)
\r
349 int16_t ReceivedByte;
\r
351 while ((ReceivedByte = CDC_Device_ReceiveByte((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream))) < 0)
\r
353 if (USB_DeviceState[corenum] == DEVICE_STATE_Unattached)
\r
356 CDC_Device_USBTask((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream));
\r
360 return ReceivedByte;
\r
364 void CDC_Device_Event_Stub(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
\r
369 void CDC_Device_Event_Stub2(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, const uint8_t Duration)
\r