]> git.sur5r.net Git - freertos/blob
a981ca76a9fa2f71e9c4979d702b59d475eb45b6
[freertos] /
1 /*\r
2  * @brief Device mode driver for the library USB CDC Class driver\r
3  *\r
4  * @note\r
5  * Copyright(C) NXP Semiconductors, 2012\r
6  * Copyright(C) Dean Camera, 2011, 2012\r
7  * All rights reserved.\r
8  *\r
9  * @par\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
23  *\r
24  * @par\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
30  * this code.\r
31  */\r
32 \r
33 \r
34 #define  __INCLUDE_FROM_USB_DRIVER\r
35 #include "../../Core/USBMode.h"\r
36 \r
37 #if defined(USB_CAN_BE_DEVICE)\r
38 \r
39 #define  __INCLUDE_FROM_CDC_DRIVER\r
40 #define  __INCLUDE_FROM_CDC_DEVICE_C\r
41 #include "CDCClassDevice.h"\r
42 \r
43 void CDC_Device_ProcessControlRequest(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)\r
44 {\r
45         if (!(Endpoint_IsSETUPReceived(CDCInterfaceInfo->Config.PortNumber)))\r
46           return;\r
47 \r
48         if (USB_ControlRequest.wIndex != CDCInterfaceInfo->Config.ControlInterfaceNumber)\r
49           return;\r
50 \r
51         switch (USB_ControlRequest.bRequest)\r
52         {\r
53                 case CDC_REQ_GetLineEncoding:\r
54                         if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))\r
55                         {\r
56                                 Endpoint_ClearSETUP(CDCInterfaceInfo->Config.PortNumber);\r
57 \r
58                                 while (!(Endpoint_IsINReady(CDCInterfaceInfo->Config.PortNumber)));\r
59 \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
64 \r
65                                 Endpoint_ClearIN(CDCInterfaceInfo->Config.PortNumber);\r
66                                 Endpoint_ClearStatusStage(CDCInterfaceInfo->Config.PortNumber);\r
67                         }\r
68 \r
69                         break;\r
70                 case CDC_REQ_SetLineEncoding:\r
71                         if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))\r
72                         {\r
73                                 Endpoint_ClearSETUP(CDCInterfaceInfo->Config.PortNumber);\r
74 \r
75                                 while (!(Endpoint_IsOUTReceived(CDCInterfaceInfo->Config.PortNumber)));\r
76 \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
81 \r
82                                 Endpoint_ClearOUT(CDCInterfaceInfo->Config.PortNumber);\r
83                                 Endpoint_ClearStatusStage(CDCInterfaceInfo->Config.PortNumber);\r
84 \r
85                                 EVENT_CDC_Device_LineEncodingChanged(CDCInterfaceInfo);\r
86                         }\r
87 \r
88                         break;\r
89                 case CDC_REQ_SetControlLineState:\r
90                         if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))\r
91                         {\r
92                                 Endpoint_ClearSETUP(CDCInterfaceInfo->Config.PortNumber);\r
93                                 Endpoint_ClearStatusStage(CDCInterfaceInfo->Config.PortNumber);\r
94 \r
95                                 CDCInterfaceInfo->State.ControlLineStates.HostToDevice = USB_ControlRequest.wValue;\r
96 \r
97                                 EVENT_CDC_Device_ControLineStateChanged(CDCInterfaceInfo);\r
98                         }\r
99 \r
100                         break;\r
101                 case CDC_REQ_SendBreak:\r
102                         if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))\r
103                         {\r
104                                 Endpoint_ClearSETUP(CDCInterfaceInfo->Config.PortNumber);\r
105                                 Endpoint_ClearStatusStage(CDCInterfaceInfo->Config.PortNumber);\r
106 \r
107                                 EVENT_CDC_Device_BreakSent(CDCInterfaceInfo, (uint8_t)USB_ControlRequest.wValue);\r
108                         }\r
109 \r
110                         break;\r
111         }\r
112 }\r
113 \r
114 bool CDC_Device_ConfigureEndpoints(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)\r
115 {\r
116         memset(&CDCInterfaceInfo->State, 0x00, sizeof(CDCInterfaceInfo->State));\r
117 \r
118         for (uint8_t EndpointNum = 1; EndpointNum < ENDPOINT_TOTAL_ENDPOINTS(CDCInterfaceInfo->Config.PortNumber); EndpointNum++)\r
119         {\r
120                 uint16_t Size;\r
121                 uint8_t  Type;\r
122                 uint8_t  Direction;\r
123                 bool     DoubleBanked;\r
124 \r
125                 if (EndpointNum == CDCInterfaceInfo->Config.DataINEndpointNumber)\r
126                 {\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
131                 }\r
132                 else if (EndpointNum == CDCInterfaceInfo->Config.DataOUTEndpointNumber)\r
133                 {\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
138                 }\r
139                 else if (EndpointNum == CDCInterfaceInfo->Config.NotificationEndpointNumber)\r
140                 {\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
145                 }\r
146                 else\r
147                 {\r
148                         continue;\r
149                 }\r
150 \r
151                 if (!(Endpoint_ConfigureEndpoint(CDCInterfaceInfo->Config.PortNumber, EndpointNum, Type, Direction, Size,\r
152                                                  DoubleBanked ? ENDPOINT_BANK_DOUBLE : ENDPOINT_BANK_SINGLE)))\r
153                 {\r
154                         return false;\r
155                 }\r
156         }\r
157 \r
158         return true;\r
159 }\r
160 \r
161 void CDC_Device_USBTask(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)\r
162 {\r
163         if ((USB_DeviceState[CDCInterfaceInfo->Config.PortNumber] != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))\r
164           return;\r
165 \r
166         #if !defined(NO_CLASS_DRIVER_AUTOFLUSH)\r
167         CDC_Device_Flush(CDCInterfaceInfo);\r
168         #endif\r
169 }\r
170 \r
171 uint8_t CDC_Device_SendString(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,\r
172                               const char* const String)\r
173 {\r
174         if ((USB_DeviceState[CDCInterfaceInfo->Config.PortNumber] != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))\r
175           return ENDPOINT_RWSTREAM_DeviceDisconnected;\r
176 \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
181 }\r
182 \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
186 {\r
187         if ((USB_DeviceState[CDCInterfaceInfo->Config.PortNumber] != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))\r
188           return ENDPOINT_RWSTREAM_DeviceDisconnected;\r
189 \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
194 }\r
195 \r
196 uint8_t CDC_Device_SendByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,\r
197                             const uint8_t Data)\r
198 {\r
199         if ((USB_DeviceState[CDCInterfaceInfo->Config.PortNumber] != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))\r
200           return ENDPOINT_RWSTREAM_DeviceDisconnected;\r
201 \r
202         Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.PortNumber, CDCInterfaceInfo->Config.DataINEndpointNumber);\r
203 \r
204         if (!(Endpoint_IsReadWriteAllowed(CDCInterfaceInfo->Config.PortNumber)))\r
205         {\r
206                 Endpoint_ClearIN(CDCInterfaceInfo->Config.PortNumber);\r
207 \r
208                 uint8_t ErrorCode;\r
209 \r
210                 if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError)\r
211                   return ErrorCode;\r
212         }\r
213 \r
214         Endpoint_Write_8(CDCInterfaceInfo->Config.PortNumber, Data);\r
215         return ENDPOINT_READYWAIT_NoError;\r
216 }\r
217 \r
218 uint8_t CDC_Device_Flush(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)\r
219 {\r
220         if ((USB_DeviceState[CDCInterfaceInfo->Config.PortNumber] != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))\r
221           return ENDPOINT_RWSTREAM_DeviceDisconnected;\r
222 \r
223         uint8_t ErrorCode;\r
224 \r
225         Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.PortNumber, CDCInterfaceInfo->Config.DataINEndpointNumber);\r
226 \r
227         if (!(Endpoint_BytesInEndpoint(CDCInterfaceInfo->Config.PortNumber)))\r
228           return ENDPOINT_READYWAIT_NoError;\r
229 \r
230         bool BankFull = !(Endpoint_IsReadWriteAllowed(CDCInterfaceInfo->Config.PortNumber));\r
231 \r
232         Endpoint_ClearIN(CDCInterfaceInfo->Config.PortNumber);\r
233 \r
234         if (BankFull)\r
235         {\r
236                 if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError)\r
237                   return ErrorCode;\r
238 \r
239                 Endpoint_ClearIN(CDCInterfaceInfo->Config.PortNumber);\r
240         }\r
241 \r
242         return ENDPOINT_READYWAIT_NoError;\r
243 }\r
244 \r
245 uint16_t CDC_Device_BytesReceived(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)\r
246 {\r
247         if ((USB_DeviceState[CDCInterfaceInfo->Config.PortNumber] != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))\r
248           return 0;\r
249 \r
250         Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.PortNumber, CDCInterfaceInfo->Config.DataOUTEndpointNumber);\r
251 \r
252         if (Endpoint_IsOUTReceived(CDCInterfaceInfo->Config.PortNumber))\r
253         {\r
254                 if (!(Endpoint_BytesInEndpoint(CDCInterfaceInfo->Config.PortNumber)))\r
255                 {\r
256                         Endpoint_ClearOUT(CDCInterfaceInfo->Config.PortNumber);\r
257                         return 0;\r
258                 }\r
259                 else\r
260                 {\r
261                         return Endpoint_BytesInEndpoint(CDCInterfaceInfo->Config.PortNumber);\r
262                 }\r
263         }\r
264         else\r
265         {\r
266                 return 0;\r
267         }\r
268 }\r
269 \r
270 int16_t CDC_Device_ReceiveByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)\r
271 {\r
272         if ((USB_DeviceState[CDCInterfaceInfo->Config.PortNumber] != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))\r
273           return -1;\r
274 \r
275         int16_t ReceivedByte = -1;\r
276 \r
277         Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.PortNumber, CDCInterfaceInfo->Config.DataOUTEndpointNumber);\r
278 \r
279         if (Endpoint_IsOUTReceived(CDCInterfaceInfo->Config.PortNumber))\r
280         {\r
281                 if (Endpoint_BytesInEndpoint(CDCInterfaceInfo->Config.PortNumber)){\r
282                   ReceivedByte = Endpoint_Read_8(CDCInterfaceInfo->Config.PortNumber);\r
283                 //Endpoint_ClearOUT();\r
284                 }\r
285 \r
286                 if (!(Endpoint_BytesInEndpoint(CDCInterfaceInfo->Config.PortNumber)))\r
287                   Endpoint_ClearOUT(CDCInterfaceInfo->Config.PortNumber);\r
288         }\r
289 \r
290         return ReceivedByte;\r
291 }\r
292 \r
293 void CDC_Device_SendControlLineStateChange(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)\r
294 {\r
295         if ((USB_DeviceState[CDCInterfaceInfo->Config.PortNumber] != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))\r
296           return;\r
297 \r
298         Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.PortNumber, CDCInterfaceInfo->Config.NotificationEndpointNumber);\r
299 \r
300         USB_Request_Header_t Notification = (USB_Request_Header_t)\r
301                 {\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
307                 };\r
308 \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
312                                  NULL);\r
313         Endpoint_ClearIN(CDCInterfaceInfo->Config.PortNumber);\r
314 }\r
315 \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
319 {\r
320         *Stream = (FILE)FDEV_SETUP_STREAM(CDC_Device_putchar, CDC_Device_getchar, _FDEV_SETUP_RW);\r
321         fdev_set_udata(Stream, CDCInterfaceInfo);\r
322 }\r
323 \r
324 void CDC_Device_CreateBlockingStream(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,\r
325                                      FILE* const Stream)\r
326 {\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
329 }\r
330 \r
331 static int CDC_Device_putchar(char c,\r
332                               FILE* Stream)\r
333 {\r
334         return CDC_Device_SendByte((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream), c) ? _FDEV_ERR : 0;\r
335 }\r
336 \r
337 static int CDC_Device_getchar(FILE* Stream)\r
338 {\r
339         int16_t ReceivedByte = CDC_Device_ReceiveByte((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream));\r
340 \r
341         if (ReceivedByte < 0)\r
342           return _FDEV_EOF;\r
343 \r
344         return ReceivedByte;\r
345 }\r
346 \r
347 static int CDC_Device_getchar_Blocking(FILE* Stream)\r
348 {\r
349         int16_t ReceivedByte;\r
350 \r
351         while ((ReceivedByte = CDC_Device_ReceiveByte((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream))) < 0)\r
352         {\r
353                 if (USB_DeviceState[corenum] == DEVICE_STATE_Unattached)\r
354                   return _FDEV_EOF;\r
355 \r
356                 CDC_Device_USBTask((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream));\r
357                 USB_USBTask();\r
358         }\r
359 \r
360         return ReceivedByte;\r
361 }\r
362 #endif\r
363 \r
364 void CDC_Device_Event_Stub(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)\r
365 {\r
366 \r
367 }\r
368 \r
369 void CDC_Device_Event_Stub2(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, const uint8_t Duration)\r
370 {\r
371 }\r
372 #endif\r
373 \r