Support programming of Arduino devices in serial passthrough mode (#5129)
[betaflight.git] / src / main / vcpf4 / usbd_cdc_vcp.c
blob4f1dcd88e3f772e0e61e69d8d2595b66f96c4b36
1 /**
2 ******************************************************************************
3 * @file usbd_cdc_vcp.c
4 * @author MCD Application Team
5 * @version V1.0.0
6 * @date 22-July-2011
7 * @brief Generic media access Layer.
8 ******************************************************************************
9 * @attention
11 * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
12 * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
13 * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
14 * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
15 * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
16 * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
18 * <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
19 ******************************************************************************
22 #ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
23 #pragma data_alignment = 4
24 #endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
26 /* Includes ------------------------------------------------------------------*/
27 #include "usbd_cdc_vcp.h"
28 #include "stm32f4xx_conf.h"
29 #include "stdbool.h"
30 #include "drivers/time.h"
32 LINE_CODING g_lc;
34 extern __IO uint8_t USB_Tx_State;
35 __IO uint32_t bDeviceState = UNCONNECTED; /* USB device status */
37 /* These are external variables imported from CDC core to be used for IN transfer management. */
39 /* This is the buffer for data received from the MCU to APP (i.e. MCU TX, APP RX) */
40 extern uint8_t APP_Rx_Buffer[];
41 extern uint32_t APP_Rx_ptr_out;
42 /* Increment this buffer position or roll it back to
43 start address when writing received data
44 in the buffer APP_Rx_Buffer. */
45 extern uint32_t APP_Rx_ptr_in;
48 APP TX is the circular buffer for data that is transmitted from the APP (host)
49 to the USB device (flight controller).
51 static uint8_t APP_Tx_Buffer[APP_TX_DATA_SIZE];
52 static uint32_t APP_Tx_ptr_out = 0;
53 static uint32_t APP_Tx_ptr_in = 0;
55 /* Private function prototypes -----------------------------------------------*/
56 static uint16_t VCP_Init(void);
57 static uint16_t VCP_DeInit(void);
58 static uint16_t VCP_Ctrl(uint32_t Cmd, uint8_t* Buf, uint32_t Len);
59 static uint16_t VCP_DataTx(const uint8_t* Buf, uint32_t Len);
60 static uint16_t VCP_DataRx(uint8_t* Buf, uint32_t Len);
61 static void (*ctrlLineStateCb)(void* context, uint16_t ctrlLineState);
62 static void *ctrlLineStateCbContext;
63 static void (*baudRateCb)(void *context, uint32_t baud);
64 static void *baudRateCbContext;
67 CDC_IF_Prop_TypeDef VCP_fops = {VCP_Init, VCP_DeInit, VCP_Ctrl, VCP_DataTx, VCP_DataRx };
69 /* Private functions ---------------------------------------------------------*/
70 /**
71 * @brief VCP_Init
72 * Initializes the Media on the STM32
73 * @param None
74 * @retval Result of the opeartion (USBD_OK in all cases)
76 static uint16_t VCP_Init(void)
78 bDeviceState = CONFIGURED;
79 ctrlLineStateCb = NULL;
80 baudRateCb = NULL;
81 return USBD_OK;
84 /**
85 * @brief VCP_DeInit
86 * DeInitializes the Media on the STM32
87 * @param None
88 * @retval Result of the opeartion (USBD_OK in all cases)
90 static uint16_t VCP_DeInit(void)
92 bDeviceState = UNCONNECTED;
93 return USBD_OK;
96 void ust_cpy(LINE_CODING* plc2, const LINE_CODING* plc1)
98 plc2->bitrate = plc1->bitrate;
99 plc2->format = plc1->format;
100 plc2->paritytype = plc1->paritytype;
101 plc2->datatype = plc1->datatype;
105 * @brief VCP_Ctrl
106 * Manage the CDC class requests
107 * @param Cmd: Command code
108 * @param Buf: Buffer containing command data (request parameters)
109 * @param Len: Number of data to be sent (in bytes)
110 * @retval Result of the opeartion (USBD_OK in all cases)
112 static uint16_t VCP_Ctrl(uint32_t Cmd, uint8_t* Buf, uint32_t Len)
114 LINE_CODING* plc = (LINE_CODING*)Buf;
116 assert_param(Len>=sizeof(LINE_CODING));
118 switch (Cmd) {
119 /* Not needed for this driver, AT modem commands */
120 case SEND_ENCAPSULATED_COMMAND:
121 case GET_ENCAPSULATED_RESPONSE:
122 break;
124 // Not needed for this driver
125 case SET_COMM_FEATURE:
126 case GET_COMM_FEATURE:
127 case CLEAR_COMM_FEATURE:
128 break;
131 //Note - hw flow control on UART 1-3 and 6 only
132 case SET_LINE_CODING:
133 // If a callback is provided, tell the upper driver of changes in baud rate
134 if (plc && (Len == sizeof (*plc))) {
135 if (baudRateCb) {
136 baudRateCb(baudRateCbContext, plc->bitrate);
139 ust_cpy(&g_lc, plc); //Copy into structure to save for later
140 break;
143 case GET_LINE_CODING:
144 ust_cpy(plc, &g_lc);
145 break;
148 case SET_CONTROL_LINE_STATE:
149 // If a callback is provided, tell the upper driver of changes in DTR/RTS state
150 if (plc && (Len == sizeof (uint16_t))) {
151 if (ctrlLineStateCb) {
152 ctrlLineStateCb(ctrlLineStateCbContext, *((uint16_t *)Buf));
155 break;
157 case SEND_BREAK:
158 /* Not needed for this driver */
159 break;
161 default:
162 break;
165 return USBD_OK;
168 /*******************************************************************************
169 * Function Name : Send DATA .
170 * Description : send the data received from the STM32 to the PC through USB
171 * Input : buffer to send, and the length of the buffer.
172 * Output : None.
173 * Return : None.
174 *******************************************************************************/
175 uint32_t CDC_Send_DATA(const uint8_t *ptrBuffer, uint32_t sendLength)
177 VCP_DataTx(ptrBuffer, sendLength);
178 return sendLength;
181 uint32_t CDC_Send_FreeBytes(void)
184 return the bytes free in the circular buffer
186 functionally equivalent to:
187 (APP_Rx_ptr_out > APP_Rx_ptr_in ? APP_Rx_ptr_out - APP_Rx_ptr_in : APP_RX_DATA_SIZE - APP_Rx_ptr_in + APP_Rx_ptr_in)
188 but without the impact of the condition check.
190 return ((APP_Rx_ptr_out - APP_Rx_ptr_in) + (-((int)(APP_Rx_ptr_out <= APP_Rx_ptr_in)) & APP_RX_DATA_SIZE)) - 1;
194 * @brief VCP_DataTx
195 * CDC data to be sent to the Host (app) over USB
196 * @param Buf: Buffer of data to be sent
197 * @param Len: Number of data to be sent (in bytes)
198 * @retval Result of the operation: USBD_OK if all operations are OK else VCP_FAIL
200 static uint16_t VCP_DataTx(const uint8_t* Buf, uint32_t Len)
203 make sure that any paragraph end frame is not in play
204 could just check for: USB_CDC_ZLP, but better to be safe
205 and wait for any existing transmission to complete.
207 while (USB_Tx_State != 0);
209 for (uint32_t i = 0; i < Len; i++) {
210 APP_Rx_Buffer[APP_Rx_ptr_in] = Buf[i];
211 APP_Rx_ptr_in = (APP_Rx_ptr_in + 1) % APP_RX_DATA_SIZE;
213 while (CDC_Send_FreeBytes() == 0) {
214 delay(1);
218 return USBD_OK;
221 /*******************************************************************************
222 * Function Name : Receive DATA .
223 * Description : receive the data from the PC to STM32 and send it through USB
224 * Input : None.
225 * Output : None.
226 * Return : None.
227 *******************************************************************************/
228 uint32_t CDC_Receive_DATA(uint8_t* recvBuf, uint32_t len)
230 uint32_t count = 0;
232 while (APP_Tx_ptr_out != APP_Tx_ptr_in && count < len) {
233 recvBuf[count] = APP_Tx_Buffer[APP_Tx_ptr_out];
234 APP_Tx_ptr_out = (APP_Tx_ptr_out + 1) % APP_TX_DATA_SIZE;
235 count++;
237 return count;
240 uint32_t CDC_Receive_BytesAvailable(void)
242 /* return the bytes available in the receive circular buffer */
243 return APP_Tx_ptr_out > APP_Tx_ptr_in ? APP_TX_DATA_SIZE - APP_Tx_ptr_out + APP_Tx_ptr_in : APP_Tx_ptr_in - APP_Tx_ptr_out;
247 * @brief VCP_DataRx
248 * Data received over USB OUT endpoint are sent over CDC interface
249 * through this function.
251 * @note
252 * This function will block any OUT packet reception on USB endpoint
253 * until exiting this function. If you exit this function before transfer
254 * is complete on CDC interface (ie. using DMA controller) it will result
255 * in receiving more data while previous ones are still not sent.
257 * @param Buf: Buffer of data to be received
258 * @param Len: Number of data received (in bytes)
259 * @retval Result of the opeartion: USBD_OK if all operations are OK else VCP_FAIL
261 static uint16_t VCP_DataRx(uint8_t* Buf, uint32_t Len)
263 if (CDC_Receive_BytesAvailable() + Len > APP_TX_DATA_SIZE) {
264 return USBD_FAIL;
267 for (uint32_t i = 0; i < Len; i++) {
268 APP_Tx_Buffer[APP_Tx_ptr_in] = Buf[i];
269 APP_Tx_ptr_in = (APP_Tx_ptr_in + 1) % APP_TX_DATA_SIZE;
272 return USBD_OK;
275 /*******************************************************************************
276 * Function Name : usbIsConfigured.
277 * Description : Determines if USB VCP is configured or not
278 * Input : None.
279 * Output : None.
280 * Return : True if configured.
281 *******************************************************************************/
282 uint8_t usbIsConfigured(void)
284 return (bDeviceState == CONFIGURED);
287 /*******************************************************************************
288 * Function Name : usbIsConnected.
289 * Description : Determines if USB VCP is connected ot not
290 * Input : None.
291 * Output : None.
292 * Return : True if connected.
293 *******************************************************************************/
294 uint8_t usbIsConnected(void)
296 return (bDeviceState != UNCONNECTED);
299 /*******************************************************************************
300 * Function Name : CDC_BaudRate.
301 * Description : Get the current baud rate
302 * Input : None.
303 * Output : None.
304 * Return : Baud rate in bps
305 *******************************************************************************/
306 uint32_t CDC_BaudRate(void)
308 return g_lc.bitrate;
311 /*******************************************************************************
312 * Function Name : CDC_SetBaudRateCb
313 * Description : Set a callback to call when baud rate changes
314 * Input : callback function and context.
315 * Output : None.
316 * Return : None.
317 *******************************************************************************/
318 void CDC_SetBaudRateCb(void (*cb)(void *context, uint32_t baud), void *context)
320 baudRateCbContext = context;
321 baudRateCb = cb;
324 /*******************************************************************************
325 * Function Name : CDC_SetCtrlLineStateCb
326 * Description : Set a callback to call when control line state changes
327 * Input : callback function and context.
328 * Output : None.
329 * Return : None.
330 *******************************************************************************/
331 void CDC_SetCtrlLineStateCb(void (*cb)(void *context, uint16_t ctrlLineState), void *context)
333 ctrlLineStateCbContext = context;
334 ctrlLineStateCb = cb;
337 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/