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