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