]> git.donarmstrong.com Git - qmk_firmware.git/blob - protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/Device/CDCClassDevice.c
Now includes LUFA-120730 in repository
[qmk_firmware.git] / protocol / lufa / LUFA-120730 / LUFA / Drivers / USB / Class / Device / CDCClassDevice.c
1 /*\r
2              LUFA Library\r
3      Copyright (C) Dean Camera, 2012.\r
4 \r
5   dean [at] fourwalledcubicle [dot] com\r
6            www.lufa-lib.org\r
7 */\r
8 \r
9 /*\r
10   Copyright 2012  Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
11 \r
12   Permission to use, copy, modify, distribute, and sell this\r
13   software and its documentation for any purpose is hereby granted\r
14   without fee, provided that the above copyright notice appear in\r
15   all copies and that both that the copyright notice and this\r
16   permission notice and warranty disclaimer appear in supporting\r
17   documentation, and that the name of the author not be used in\r
18   advertising or publicity pertaining to distribution of the\r
19   software without specific, written prior permission.\r
20 \r
21   The author disclaim all warranties with regard to this\r
22   software, including all implied warranties of merchantability\r
23   and fitness.  In no event shall the author be liable for any\r
24   special, indirect or consequential damages or any damages\r
25   whatsoever resulting from loss of use, data or profits, whether\r
26   in an action of contract, negligence or other tortious action,\r
27   arising out of or in connection with the use or performance of\r
28   this software.\r
29 */\r
30 \r
31 #define  __INCLUDE_FROM_USB_DRIVER\r
32 #include "../../Core/USBMode.h"\r
33 \r
34 #if defined(USB_CAN_BE_DEVICE)\r
35 \r
36 #define  __INCLUDE_FROM_CDC_DRIVER\r
37 #define  __INCLUDE_FROM_CDC_DEVICE_C\r
38 #include "CDCClassDevice.h"\r
39 \r
40 void CDC_Device_ProcessControlRequest(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)\r
41 {\r
42         if (!(Endpoint_IsSETUPReceived()))\r
43           return;\r
44 \r
45         if (USB_ControlRequest.wIndex != CDCInterfaceInfo->Config.ControlInterfaceNumber)\r
46           return;\r
47 \r
48         switch (USB_ControlRequest.bRequest)\r
49         {\r
50                 case CDC_REQ_GetLineEncoding:\r
51                         if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))\r
52                         {\r
53                                 Endpoint_ClearSETUP();\r
54 \r
55                                 while (!(Endpoint_IsINReady()));\r
56 \r
57                                 Endpoint_Write_32_LE(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS);\r
58                                 Endpoint_Write_8(CDCInterfaceInfo->State.LineEncoding.CharFormat);\r
59                                 Endpoint_Write_8(CDCInterfaceInfo->State.LineEncoding.ParityType);\r
60                                 Endpoint_Write_8(CDCInterfaceInfo->State.LineEncoding.DataBits);\r
61 \r
62                                 Endpoint_ClearIN();\r
63                                 Endpoint_ClearStatusStage();\r
64                         }\r
65 \r
66                         break;\r
67                 case CDC_REQ_SetLineEncoding:\r
68                         if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))\r
69                         {\r
70                                 Endpoint_ClearSETUP();\r
71 \r
72                                 while (!(Endpoint_IsOUTReceived()))\r
73                                 {\r
74                                         if (USB_DeviceState == DEVICE_STATE_Unattached)\r
75                                           return;\r
76                                 }\r
77                                 \r
78                                 CDCInterfaceInfo->State.LineEncoding.BaudRateBPS = Endpoint_Read_32_LE();\r
79                                 CDCInterfaceInfo->State.LineEncoding.CharFormat  = Endpoint_Read_8();\r
80                                 CDCInterfaceInfo->State.LineEncoding.ParityType  = Endpoint_Read_8();\r
81                                 CDCInterfaceInfo->State.LineEncoding.DataBits    = Endpoint_Read_8();\r
82 \r
83                                 Endpoint_ClearOUT();\r
84                                 Endpoint_ClearStatusStage();\r
85 \r
86                                 EVENT_CDC_Device_LineEncodingChanged(CDCInterfaceInfo);\r
87                         }\r
88 \r
89                         break;\r
90                 case CDC_REQ_SetControlLineState:\r
91                         if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))\r
92                         {\r
93                                 Endpoint_ClearSETUP();\r
94                                 Endpoint_ClearStatusStage();\r
95 \r
96                                 CDCInterfaceInfo->State.ControlLineStates.HostToDevice = USB_ControlRequest.wValue;\r
97 \r
98                                 EVENT_CDC_Device_ControLineStateChanged(CDCInterfaceInfo);\r
99                         }\r
100 \r
101                         break;\r
102                 case CDC_REQ_SendBreak:\r
103                         if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))\r
104                         {\r
105                                 Endpoint_ClearSETUP();\r
106                                 Endpoint_ClearStatusStage();\r
107 \r
108                                 EVENT_CDC_Device_BreakSent(CDCInterfaceInfo, (uint8_t)USB_ControlRequest.wValue);\r
109                         }\r
110 \r
111                         break;\r
112         }\r
113 }\r
114 \r
115 bool CDC_Device_ConfigureEndpoints(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)\r
116 {\r
117         memset(&CDCInterfaceInfo->State, 0x00, sizeof(CDCInterfaceInfo->State));\r
118 \r
119         CDCInterfaceInfo->Config.DataINEndpoint.Type       = EP_TYPE_BULK;\r
120         CDCInterfaceInfo->Config.DataOUTEndpoint.Type      = EP_TYPE_BULK;\r
121         CDCInterfaceInfo->Config.NotificationEndpoint.Type = EP_TYPE_INTERRUPT;\r
122 \r
123         if (!(Endpoint_ConfigureEndpointTable(&CDCInterfaceInfo->Config.DataINEndpoint, 1)))\r
124           return false;\r
125 \r
126         if (!(Endpoint_ConfigureEndpointTable(&CDCInterfaceInfo->Config.DataOUTEndpoint, 1)))\r
127           return false;\r
128 \r
129         if (!(Endpoint_ConfigureEndpointTable(&CDCInterfaceInfo->Config.NotificationEndpoint, 1)))\r
130           return false;\r
131 \r
132         return true;\r
133 }\r
134 \r
135 void CDC_Device_USBTask(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)\r
136 {\r
137         if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))\r
138           return;\r
139 \r
140         #if !defined(NO_CLASS_DRIVER_AUTOFLUSH)\r
141         CDC_Device_Flush(CDCInterfaceInfo);\r
142         #endif\r
143 }\r
144 \r
145 uint8_t CDC_Device_SendString(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,\r
146                               const char* const String)\r
147 {\r
148         if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))\r
149           return ENDPOINT_RWSTREAM_DeviceDisconnected;\r
150 \r
151         Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpoint.Address);\r
152         return Endpoint_Write_Stream_LE(String, strlen(String), NULL);\r
153 }\r
154 \r
155 uint8_t CDC_Device_SendData(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,\r
156                             const char* const Buffer,\r
157                             const uint16_t Length)\r
158 {\r
159         if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))\r
160           return ENDPOINT_RWSTREAM_DeviceDisconnected;\r
161 \r
162         Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpoint.Address);\r
163         return Endpoint_Write_Stream_LE(Buffer, Length, NULL);\r
164 }\r
165 \r
166 uint8_t CDC_Device_SendByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,\r
167                             const uint8_t Data)\r
168 {\r
169         if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))\r
170           return ENDPOINT_RWSTREAM_DeviceDisconnected;\r
171 \r
172         Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpoint.Address);\r
173 \r
174         if (!(Endpoint_IsReadWriteAllowed()))\r
175         {\r
176                 Endpoint_ClearIN();\r
177 \r
178                 uint8_t ErrorCode;\r
179 \r
180                 if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError)\r
181                   return ErrorCode;\r
182         }\r
183 \r
184         Endpoint_Write_8(Data);\r
185         return ENDPOINT_READYWAIT_NoError;\r
186 }\r
187 \r
188 uint8_t CDC_Device_Flush(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)\r
189 {\r
190         if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))\r
191           return ENDPOINT_RWSTREAM_DeviceDisconnected;\r
192 \r
193         uint8_t ErrorCode;\r
194 \r
195         Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpoint.Address);\r
196 \r
197         if (!(Endpoint_BytesInEndpoint()))\r
198           return ENDPOINT_READYWAIT_NoError;\r
199 \r
200         bool BankFull = !(Endpoint_IsReadWriteAllowed());\r
201 \r
202         Endpoint_ClearIN();\r
203 \r
204         if (BankFull)\r
205         {\r
206                 if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError)\r
207                   return ErrorCode;\r
208 \r
209                 Endpoint_ClearIN();\r
210         }\r
211 \r
212         return ENDPOINT_READYWAIT_NoError;\r
213 }\r
214 \r
215 uint16_t CDC_Device_BytesReceived(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)\r
216 {\r
217         if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))\r
218           return 0;\r
219 \r
220         Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataOUTEndpoint.Address);\r
221 \r
222         if (Endpoint_IsOUTReceived())\r
223         {\r
224                 if (!(Endpoint_BytesInEndpoint()))\r
225                 {\r
226                         Endpoint_ClearOUT();\r
227                         return 0;\r
228                 }\r
229                 else\r
230                 {\r
231                         return Endpoint_BytesInEndpoint();\r
232                 }\r
233         }\r
234         else\r
235         {\r
236                 return 0;\r
237         }\r
238 }\r
239 \r
240 int16_t CDC_Device_ReceiveByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)\r
241 {\r
242         if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))\r
243           return -1;\r
244 \r
245         int16_t ReceivedByte = -1;\r
246 \r
247         Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataOUTEndpoint.Address);\r
248 \r
249         if (Endpoint_IsOUTReceived())\r
250         {\r
251                 if (Endpoint_BytesInEndpoint())\r
252                   ReceivedByte = Endpoint_Read_8();\r
253 \r
254                 if (!(Endpoint_BytesInEndpoint()))\r
255                   Endpoint_ClearOUT();\r
256         }\r
257 \r
258         return ReceivedByte;\r
259 }\r
260 \r
261 void CDC_Device_SendControlLineStateChange(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)\r
262 {\r
263         if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))\r
264           return;\r
265 \r
266         Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.NotificationEndpoint.Address);\r
267 \r
268         USB_Request_Header_t Notification = (USB_Request_Header_t)\r
269                 {\r
270                         .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),\r
271                         .bRequest      = CDC_NOTIF_SerialState,\r
272                         .wValue        = CPU_TO_LE16(0),\r
273                         .wIndex        = CPU_TO_LE16(0),\r
274                         .wLength       = CPU_TO_LE16(sizeof(CDCInterfaceInfo->State.ControlLineStates.DeviceToHost)),\r
275                 };\r
276 \r
277         Endpoint_Write_Stream_LE(&Notification, sizeof(USB_Request_Header_t), NULL);\r
278         Endpoint_Write_Stream_LE(&CDCInterfaceInfo->State.ControlLineStates.DeviceToHost,\r
279                                  sizeof(CDCInterfaceInfo->State.ControlLineStates.DeviceToHost),\r
280                                  NULL);\r
281         Endpoint_ClearIN();\r
282 }\r
283 \r
284 #if defined(FDEV_SETUP_STREAM)\r
285 void CDC_Device_CreateStream(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,\r
286                              FILE* const Stream)\r
287 {\r
288         *Stream = (FILE)FDEV_SETUP_STREAM(CDC_Device_putchar, CDC_Device_getchar, _FDEV_SETUP_RW);\r
289         fdev_set_udata(Stream, CDCInterfaceInfo);\r
290 }\r
291 \r
292 void CDC_Device_CreateBlockingStream(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,\r
293                                      FILE* const Stream)\r
294 {\r
295         *Stream = (FILE)FDEV_SETUP_STREAM(CDC_Device_putchar, CDC_Device_getchar_Blocking, _FDEV_SETUP_RW);\r
296         fdev_set_udata(Stream, CDCInterfaceInfo);\r
297 }\r
298 \r
299 static int CDC_Device_putchar(char c,\r
300                               FILE* Stream)\r
301 {\r
302         return CDC_Device_SendByte((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream), c) ? _FDEV_ERR : 0;\r
303 }\r
304 \r
305 static int CDC_Device_getchar(FILE* Stream)\r
306 {\r
307         int16_t ReceivedByte = CDC_Device_ReceiveByte((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream));\r
308 \r
309         if (ReceivedByte < 0)\r
310           return _FDEV_EOF;\r
311 \r
312         return ReceivedByte;\r
313 }\r
314 \r
315 static int CDC_Device_getchar_Blocking(FILE* Stream)\r
316 {\r
317         int16_t ReceivedByte;\r
318 \r
319         while ((ReceivedByte = CDC_Device_ReceiveByte((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream))) < 0)\r
320         {\r
321                 if (USB_DeviceState == DEVICE_STATE_Unattached)\r
322                   return _FDEV_EOF;\r
323 \r
324                 CDC_Device_USBTask((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream));\r
325                 USB_USBTask();\r
326         }\r
327 \r
328         return ReceivedByte;\r
329 }\r
330 #endif\r
331 \r
332 // cppcheck-suppress unusedFunction\r
333 void CDC_Device_Event_Stub(void)\r
334 {\r
335 \r
336 }\r
337 \r
338 #endif\r
339 \r