3 Copyright (C) Dean Camera, 2012.
\r
5 dean [at] fourwalledcubicle [dot] com
\r
10 Copyright 2012 Dean Camera (dean [at] fourwalledcubicle [dot] com)
\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
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
31 #define __INCLUDE_FROM_USB_DRIVER
\r
32 #include "../../Core/USBMode.h"
\r
34 #if defined(USB_CAN_BE_DEVICE)
\r
36 #define __INCLUDE_FROM_CDC_DRIVER
\r
37 #define __INCLUDE_FROM_CDC_DEVICE_C
\r
38 #include "CDCClassDevice.h"
\r
40 void CDC_Device_ProcessControlRequest(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
\r
42 if (!(Endpoint_IsSETUPReceived()))
\r
45 if (USB_ControlRequest.wIndex != CDCInterfaceInfo->Config.ControlInterfaceNumber)
\r
48 switch (USB_ControlRequest.bRequest)
\r
50 case CDC_REQ_GetLineEncoding:
\r
51 if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
\r
53 Endpoint_ClearSETUP();
\r
55 while (!(Endpoint_IsINReady()));
\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
63 Endpoint_ClearStatusStage();
\r
67 case CDC_REQ_SetLineEncoding:
\r
68 if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
\r
70 Endpoint_ClearSETUP();
\r
72 while (!(Endpoint_IsOUTReceived()))
\r
74 if (USB_DeviceState == DEVICE_STATE_Unattached)
\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
83 Endpoint_ClearOUT();
\r
84 Endpoint_ClearStatusStage();
\r
86 EVENT_CDC_Device_LineEncodingChanged(CDCInterfaceInfo);
\r
90 case CDC_REQ_SetControlLineState:
\r
91 if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
\r
93 Endpoint_ClearSETUP();
\r
94 Endpoint_ClearStatusStage();
\r
96 CDCInterfaceInfo->State.ControlLineStates.HostToDevice = USB_ControlRequest.wValue;
\r
98 EVENT_CDC_Device_ControLineStateChanged(CDCInterfaceInfo);
\r
102 case CDC_REQ_SendBreak:
\r
103 if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
\r
105 Endpoint_ClearSETUP();
\r
106 Endpoint_ClearStatusStage();
\r
108 EVENT_CDC_Device_BreakSent(CDCInterfaceInfo, (uint8_t)USB_ControlRequest.wValue);
\r
115 bool CDC_Device_ConfigureEndpoints(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
\r
117 memset(&CDCInterfaceInfo->State, 0x00, sizeof(CDCInterfaceInfo->State));
\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
123 if (!(Endpoint_ConfigureEndpointTable(&CDCInterfaceInfo->Config.DataINEndpoint, 1)))
\r
126 if (!(Endpoint_ConfigureEndpointTable(&CDCInterfaceInfo->Config.DataOUTEndpoint, 1)))
\r
129 if (!(Endpoint_ConfigureEndpointTable(&CDCInterfaceInfo->Config.NotificationEndpoint, 1)))
\r
135 void CDC_Device_USBTask(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
\r
137 if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
\r
140 #if !defined(NO_CLASS_DRIVER_AUTOFLUSH)
\r
141 CDC_Device_Flush(CDCInterfaceInfo);
\r
145 uint8_t CDC_Device_SendString(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,
\r
146 const char* const String)
\r
148 if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
\r
149 return ENDPOINT_RWSTREAM_DeviceDisconnected;
\r
151 Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpoint.Address);
\r
152 return Endpoint_Write_Stream_LE(String, strlen(String), NULL);
\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
159 if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
\r
160 return ENDPOINT_RWSTREAM_DeviceDisconnected;
\r
162 Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpoint.Address);
\r
163 return Endpoint_Write_Stream_LE(Buffer, Length, NULL);
\r
166 uint8_t CDC_Device_SendByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,
\r
167 const uint8_t Data)
\r
169 if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
\r
170 return ENDPOINT_RWSTREAM_DeviceDisconnected;
\r
172 Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpoint.Address);
\r
174 if (!(Endpoint_IsReadWriteAllowed()))
\r
176 Endpoint_ClearIN();
\r
180 if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError)
\r
184 Endpoint_Write_8(Data);
\r
185 return ENDPOINT_READYWAIT_NoError;
\r
188 uint8_t CDC_Device_Flush(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
\r
190 if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
\r
191 return ENDPOINT_RWSTREAM_DeviceDisconnected;
\r
195 Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpoint.Address);
\r
197 if (!(Endpoint_BytesInEndpoint()))
\r
198 return ENDPOINT_READYWAIT_NoError;
\r
200 bool BankFull = !(Endpoint_IsReadWriteAllowed());
\r
202 Endpoint_ClearIN();
\r
206 if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError)
\r
209 Endpoint_ClearIN();
\r
212 return ENDPOINT_READYWAIT_NoError;
\r
215 uint16_t CDC_Device_BytesReceived(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
\r
217 if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
\r
220 Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataOUTEndpoint.Address);
\r
222 if (Endpoint_IsOUTReceived())
\r
224 if (!(Endpoint_BytesInEndpoint()))
\r
226 Endpoint_ClearOUT();
\r
231 return Endpoint_BytesInEndpoint();
\r
240 int16_t CDC_Device_ReceiveByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
\r
242 if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
\r
245 int16_t ReceivedByte = -1;
\r
247 Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataOUTEndpoint.Address);
\r
249 if (Endpoint_IsOUTReceived())
\r
251 if (Endpoint_BytesInEndpoint())
\r
252 ReceivedByte = Endpoint_Read_8();
\r
254 if (!(Endpoint_BytesInEndpoint()))
\r
255 Endpoint_ClearOUT();
\r
258 return ReceivedByte;
\r
261 void CDC_Device_SendControlLineStateChange(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
\r
263 if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
\r
266 Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.NotificationEndpoint.Address);
\r
268 USB_Request_Header_t Notification = (USB_Request_Header_t)
\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
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
281 Endpoint_ClearIN();
\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
288 *Stream = (FILE)FDEV_SETUP_STREAM(CDC_Device_putchar, CDC_Device_getchar, _FDEV_SETUP_RW);
\r
289 fdev_set_udata(Stream, CDCInterfaceInfo);
\r
292 void CDC_Device_CreateBlockingStream(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,
\r
293 FILE* const Stream)
\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
299 static int CDC_Device_putchar(char c,
\r
302 return CDC_Device_SendByte((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream), c) ? _FDEV_ERR : 0;
\r
305 static int CDC_Device_getchar(FILE* Stream)
\r
307 int16_t ReceivedByte = CDC_Device_ReceiveByte((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream));
\r
309 if (ReceivedByte < 0)
\r
312 return ReceivedByte;
\r
315 static int CDC_Device_getchar_Blocking(FILE* Stream)
\r
317 int16_t ReceivedByte;
\r
319 while ((ReceivedByte = CDC_Device_ReceiveByte((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream))) < 0)
\r
321 if (USB_DeviceState == DEVICE_STATE_Unattached)
\r
324 CDC_Device_USBTask((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream));
\r
328 return ReceivedByte;
\r
332 // cppcheck-suppress unusedFunction
\r
333 void CDC_Device_Event_Stub(void)
\r