Update UC3 platform driver support to use the bitmasks defined in the header files...
[pub/USBasp.git] / LUFA / Drivers / USB / Class / Device / CDC.c
1 /*
2 LUFA Library
3 Copyright (C) Dean Camera, 2011.
4
5 dean [at] fourwalledcubicle [dot] com
6 www.lufa-lib.org
7 */
8
9 /*
10 Copyright 2011 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 "CDC.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 Endpoint_Write_Control_Stream_LE(&CDCInterfaceInfo->State.LineEncoding, sizeof(CDCInterfaceInfo->State.LineEncoding));
55 Endpoint_ClearOUT();
56 }
57
58 break;
59 case CDC_REQ_SetLineEncoding:
60 if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
61 {
62 Endpoint_ClearSETUP();
63 Endpoint_Read_Control_Stream_LE(&CDCInterfaceInfo->State.LineEncoding, sizeof(CDCInterfaceInfo->State.LineEncoding));
64 Endpoint_ClearIN();
65
66 EVENT_CDC_Device_LineEncodingChanged(CDCInterfaceInfo);
67 }
68
69 break;
70 case CDC_REQ_SetControlLineState:
71 if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
72 {
73 Endpoint_ClearSETUP();
74 Endpoint_ClearStatusStage();
75
76 CDCInterfaceInfo->State.ControlLineStates.HostToDevice = USB_ControlRequest.wValue;
77
78 EVENT_CDC_Device_ControLineStateChanged(CDCInterfaceInfo);
79 }
80
81 break;
82 case CDC_REQ_SendBreak:
83 if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
84 {
85 Endpoint_ClearSETUP();
86 Endpoint_ClearStatusStage();
87
88 EVENT_CDC_Device_BreakSent(CDCInterfaceInfo, (uint8_t)USB_ControlRequest.wValue);
89 }
90
91 break;
92 }
93 }
94
95 bool CDC_Device_ConfigureEndpoints(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
96 {
97 memset(&CDCInterfaceInfo->State, 0x00, sizeof(CDCInterfaceInfo->State));
98
99 for (uint8_t EndpointNum = 1; EndpointNum < ENDPOINT_TOTAL_ENDPOINTS; EndpointNum++)
100 {
101 uint16_t Size;
102 uint8_t Type;
103 uint8_t Direction;
104 bool DoubleBanked;
105
106 if (EndpointNum == CDCInterfaceInfo->Config.DataINEndpointNumber)
107 {
108 Size = CDCInterfaceInfo->Config.DataINEndpointSize;
109 Direction = ENDPOINT_DIR_IN;
110 Type = EP_TYPE_BULK;
111 DoubleBanked = CDCInterfaceInfo->Config.DataINEndpointDoubleBank;
112 }
113 else if (EndpointNum == CDCInterfaceInfo->Config.DataOUTEndpointNumber)
114 {
115 Size = CDCInterfaceInfo->Config.DataOUTEndpointSize;
116 Direction = ENDPOINT_DIR_OUT;
117 Type = EP_TYPE_BULK;
118 DoubleBanked = CDCInterfaceInfo->Config.DataOUTEndpointDoubleBank;
119 }
120 else if (EndpointNum == CDCInterfaceInfo->Config.NotificationEndpointNumber)
121 {
122 Size = CDCInterfaceInfo->Config.NotificationEndpointSize;
123 Direction = ENDPOINT_DIR_IN;
124 Type = EP_TYPE_INTERRUPT;
125 DoubleBanked = CDCInterfaceInfo->Config.NotificationEndpointDoubleBank;
126 }
127 else
128 {
129 continue;
130 }
131
132 if (!(Endpoint_ConfigureEndpoint(EndpointNum, Type, Direction, Size,
133 DoubleBanked ? ENDPOINT_BANK_DOUBLE : ENDPOINT_BANK_SINGLE)))
134 {
135 return false;
136 }
137 }
138
139 return true;
140 }
141
142 void CDC_Device_USBTask(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
143 {
144 if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
145 return;
146
147 #if !defined(NO_CLASS_DRIVER_AUTOFLUSH)
148 CDC_Device_Flush(CDCInterfaceInfo);
149 #endif
150 }
151
152 uint8_t CDC_Device_SendString(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,
153 const char* const String)
154 {
155 if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
156 return ENDPOINT_RWSTREAM_DeviceDisconnected;
157
158 Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpointNumber);
159 return Endpoint_Write_Stream_LE(String, strlen(String), NULL);
160 }
161
162 uint8_t CDC_Device_SendData(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,
163 const char* const Buffer,
164 const uint16_t Length)
165 {
166 if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
167 return ENDPOINT_RWSTREAM_DeviceDisconnected;
168
169 Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpointNumber);
170 return Endpoint_Write_Stream_LE(Buffer, Length, NULL);
171 }
172
173 uint8_t CDC_Device_SendByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,
174 const uint8_t Data)
175 {
176 if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
177 return ENDPOINT_RWSTREAM_DeviceDisconnected;
178
179 Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpointNumber);
180
181 if (!(Endpoint_IsReadWriteAllowed()))
182 {
183 Endpoint_ClearIN();
184
185 uint8_t ErrorCode;
186
187 if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError)
188 return ErrorCode;
189 }
190
191 Endpoint_Write_8(Data);
192 return ENDPOINT_READYWAIT_NoError;
193 }
194
195 uint8_t CDC_Device_Flush(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
196 {
197 if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
198 return ENDPOINT_RWSTREAM_DeviceDisconnected;
199
200 uint8_t ErrorCode;
201
202 Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpointNumber);
203
204 if (!(Endpoint_BytesInEndpoint()))
205 return ENDPOINT_READYWAIT_NoError;
206
207 bool BankFull = !(Endpoint_IsReadWriteAllowed());
208
209 Endpoint_ClearIN();
210
211 if (BankFull)
212 {
213 if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError)
214 return ErrorCode;
215
216 Endpoint_ClearIN();
217 }
218
219 return ENDPOINT_READYWAIT_NoError;
220 }
221
222 uint16_t CDC_Device_BytesReceived(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
223 {
224 if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
225 return 0;
226
227 Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataOUTEndpointNumber);
228
229 if (Endpoint_IsOUTReceived())
230 {
231 if (!(Endpoint_BytesInEndpoint()))
232 {
233 Endpoint_ClearOUT();
234 return 0;
235 }
236 else
237 {
238 return Endpoint_BytesInEndpoint();
239 }
240 }
241 else
242 {
243 return 0;
244 }
245 }
246
247 int16_t CDC_Device_ReceiveByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
248 {
249 if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
250 return -1;
251
252 int16_t ReceivedByte = -1;
253
254 Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataOUTEndpointNumber);
255
256 if (Endpoint_IsOUTReceived())
257 {
258 if (Endpoint_BytesInEndpoint())
259 ReceivedByte = Endpoint_Read_8();
260
261 if (!(Endpoint_BytesInEndpoint()))
262 Endpoint_ClearOUT();
263 }
264
265 return ReceivedByte;
266 }
267
268 void CDC_Device_SendControlLineStateChange(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
269 {
270 if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
271 return;
272
273 Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.NotificationEndpointNumber);
274
275 USB_Request_Header_t Notification = (USB_Request_Header_t)
276 {
277 .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
278 .bRequest = CDC_NOTIF_SerialState,
279 .wValue = CPU_TO_LE16(0),
280 .wIndex = CPU_TO_LE16(0),
281 .wLength = CPU_TO_LE16(sizeof(CDCInterfaceInfo->State.ControlLineStates.DeviceToHost)),
282 };
283
284 Endpoint_Write_Stream_LE(&Notification, sizeof(USB_Request_Header_t), NULL);
285 Endpoint_Write_Stream_LE(&CDCInterfaceInfo->State.ControlLineStates.DeviceToHost,
286 sizeof(CDCInterfaceInfo->State.ControlLineStates.DeviceToHost),
287 NULL);
288 Endpoint_ClearIN();
289 }
290
291 #if defined(FDEV_SETUP_STREAM)
292 void CDC_Device_CreateStream(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,
293 FILE* const Stream)
294 {
295 *Stream = (FILE)FDEV_SETUP_STREAM(CDC_Device_putchar, CDC_Device_getchar, _FDEV_SETUP_RW);
296 fdev_set_udata(Stream, CDCInterfaceInfo);
297 }
298
299 void CDC_Device_CreateBlockingStream(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,
300 FILE* const Stream)
301 {
302 *Stream = (FILE)FDEV_SETUP_STREAM(CDC_Device_putchar, CDC_Device_getchar_Blocking, _FDEV_SETUP_RW);
303 fdev_set_udata(Stream, CDCInterfaceInfo);
304 }
305
306 static int CDC_Device_putchar(char c,
307 FILE* Stream)
308 {
309 return CDC_Device_SendByte((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream), c) ? _FDEV_ERR : 0;
310 }
311
312 static int CDC_Device_getchar(FILE* Stream)
313 {
314 int16_t ReceivedByte = CDC_Device_ReceiveByte((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream));
315
316 if (ReceivedByte < 0)
317 return _FDEV_EOF;
318
319 return ReceivedByte;
320 }
321
322 static int CDC_Device_getchar_Blocking(FILE* Stream)
323 {
324 int16_t ReceivedByte;
325
326 while ((ReceivedByte = CDC_Device_ReceiveByte((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream))) < 0)
327 {
328 if (USB_DeviceState == DEVICE_STATE_Unattached)
329 return _FDEV_EOF;
330
331 CDC_Device_USBTask((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream));
332 USB_USBTask();
333 }
334
335 return ReceivedByte;
336 }
337 #endif
338
339 void CDC_Device_Event_Stub(void)
340 {
341
342 }
343
344 #endif
345