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