Merge pull request #11195 from mathiasvr/pr-elrs-clean
[betaflight.git] / src / main / vcpf4 / usbd_cdc_vcp.c
blob4d7e3677c9c31181a5304ef544581f122d56b277
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 /* Includes ------------------------------------------------------------------*/
24 #include <stdbool.h>
26 #include "platform.h"
28 #include "build/atomic.h"
30 #include "usbd_cdc_vcp.h"
31 #include "stm32f4xx_conf.h"
32 #include "drivers/nvic.h"
33 #include "drivers/time.h"
35 #ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
36 #pragma data_alignment = 4
37 #endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
39 __ALIGN_BEGIN USB_OTG_CORE_HANDLE USB_OTG_dev __ALIGN_END;
41 LINE_CODING g_lc;
43 extern __IO uint8_t USB_Tx_State;
44 __IO uint32_t bDeviceState = UNCONNECTED; /* USB device status */
46 /* These are external variables imported from CDC core to be used for IN transfer management. */
48 /* This is the buffer for data received from the MCU to APP (i.e. MCU TX, APP RX) */
49 extern uint8_t APP_Rx_Buffer[];
50 extern volatile uint32_t APP_Rx_ptr_out;
51 /* Increment this buffer position or roll it back to
52 start address when writing received data
53 in the buffer APP_Rx_Buffer. */
54 extern volatile uint32_t APP_Rx_ptr_in;
57 APP TX is the circular buffer for data that is transmitted from the APP (host)
58 to the USB device (flight controller).
60 static uint8_t APP_Tx_Buffer[APP_TX_DATA_SIZE];
61 static uint32_t APP_Tx_ptr_out = 0;
62 static uint32_t APP_Tx_ptr_in = 0;
64 /* Private function prototypes -----------------------------------------------*/
65 static uint16_t VCP_Init(void);
66 static uint16_t VCP_DeInit(void);
67 static uint16_t VCP_Ctrl(uint32_t Cmd, uint8_t* Buf, uint32_t Len);
68 static uint16_t VCP_DataTx(const uint8_t* Buf, uint32_t Len);
69 static uint16_t VCP_DataRx(uint8_t* Buf, uint32_t Len);
70 static void (*ctrlLineStateCb)(void* context, uint16_t ctrlLineState);
71 static void *ctrlLineStateCbContext;
72 static void (*baudRateCb)(void *context, uint32_t baud);
73 static void *baudRateCbContext;
76 CDC_IF_Prop_TypeDef VCP_fops = {VCP_Init, VCP_DeInit, VCP_Ctrl, VCP_DataTx, VCP_DataRx };
78 /* Private functions ---------------------------------------------------------*/
79 /**
80 * @brief VCP_Init
81 * Initializes the Media on the STM32
82 * @param None
83 * @retval Result of the opeartion (USBD_OK in all cases)
85 static uint16_t VCP_Init(void)
87 bDeviceState = CONFIGURED;
88 ctrlLineStateCb = NULL;
89 baudRateCb = NULL;
90 return USBD_OK;
93 /**
94 * @brief VCP_DeInit
95 * DeInitializes the Media on the STM32
96 * @param None
97 * @retval Result of the opeartion (USBD_OK in all cases)
99 static uint16_t VCP_DeInit(void)
101 bDeviceState = UNCONNECTED;
102 return USBD_OK;
105 void ust_cpy(LINE_CODING* plc2, const LINE_CODING* plc1)
107 plc2->bitrate = plc1->bitrate;
108 plc2->format = plc1->format;
109 plc2->paritytype = plc1->paritytype;
110 plc2->datatype = plc1->datatype;
114 * @brief VCP_Ctrl
115 * Manage the CDC class requests
116 * @param Cmd: Command code
117 * @param Buf: Buffer containing command data (request parameters)
118 * @param Len: Number of data to be sent (in bytes)
119 * @retval Result of the opeartion (USBD_OK in all cases)
121 static uint16_t VCP_Ctrl(uint32_t Cmd, uint8_t* Buf, uint32_t Len)
123 LINE_CODING* plc = (LINE_CODING*)Buf;
125 assert_param(Len>=sizeof(LINE_CODING));
127 switch (Cmd) {
128 /* Not needed for this driver, AT modem commands */
129 case SEND_ENCAPSULATED_COMMAND:
130 case GET_ENCAPSULATED_RESPONSE:
131 break;
133 // Not needed for this driver
134 case SET_COMM_FEATURE:
135 case GET_COMM_FEATURE:
136 case CLEAR_COMM_FEATURE:
137 break;
140 //Note - hw flow control on UART 1-3 and 6 only
141 case SET_LINE_CODING:
142 // If a callback is provided, tell the upper driver of changes in baud rate
143 if (plc && (Len == sizeof(*plc))) {
144 if (baudRateCb) {
145 baudRateCb(baudRateCbContext, plc->bitrate);
147 ust_cpy(&g_lc, plc); //Copy into structure to save for later
149 break;
152 case GET_LINE_CODING:
153 if (plc && (Len == sizeof(*plc))) {
154 ust_cpy(plc, &g_lc);
156 break;
159 case SET_CONTROL_LINE_STATE:
160 // If a callback is provided, tell the upper driver of changes in DTR/RTS state
161 if (plc && (Len == sizeof(uint16_t))) {
162 if (ctrlLineStateCb) {
163 ctrlLineStateCb(ctrlLineStateCbContext, *((uint16_t *)Buf));
166 break;
168 case SEND_BREAK:
169 /* Not needed for this driver */
170 break;
172 default:
173 break;
176 return USBD_OK;
179 /*******************************************************************************
180 * Function Name : Send DATA .
181 * Description : send the data received from the STM32 to the PC through USB
182 * Input : buffer to send, and the length of the buffer.
183 * Output : None.
184 * Return : None.
185 *******************************************************************************/
186 uint32_t CDC_Send_DATA(const uint8_t *ptrBuffer, uint32_t sendLength)
188 VCP_DataTx(ptrBuffer, sendLength);
189 return sendLength;
192 uint32_t CDC_Send_FreeBytes(void)
194 return APP_RX_DATA_SIZE - CDC_Receive_BytesAvailable();
198 * @brief VCP_DataTx
199 * CDC data to be sent to the Host (app) over USB
200 * @param Buf: Buffer of data to be sent
201 * @param Len: Number of data to be sent (in bytes)
202 * @retval Result of the operation: USBD_OK if all operations are OK else VCP_FAIL
204 static uint16_t VCP_DataTx(const uint8_t* Buf, uint32_t Len)
207 make sure that any paragraph end frame is not in play
208 could just check for: USB_CDC_ZLP, but better to be safe
209 and wait for any existing transmission to complete.
211 while (USB_Tx_State != 0);
213 for (uint32_t i = 0; i < Len; i++) {
214 // Stall if the ring buffer is full
215 while (((APP_Rx_ptr_in + 1) % APP_RX_DATA_SIZE) == APP_Rx_ptr_out) {
216 delay(1);
219 APP_Rx_Buffer[APP_Rx_ptr_in] = Buf[i];
220 APP_Rx_ptr_in = (APP_Rx_ptr_in + 1) % APP_RX_DATA_SIZE;
223 return USBD_OK;
226 /*******************************************************************************
227 * Function Name : Receive DATA .
228 * Description : receive the data from the PC to STM32 and send it through USB
229 * Input : None.
230 * Output : None.
231 * Return : None.
232 *******************************************************************************/
233 uint32_t CDC_Receive_DATA(uint8_t* recvBuf, uint32_t len)
235 uint32_t count = 0;
237 while (APP_Tx_ptr_out != APP_Tx_ptr_in && (count < len)) {
238 recvBuf[count] = APP_Tx_Buffer[APP_Tx_ptr_out];
239 APP_Tx_ptr_out = (APP_Tx_ptr_out + 1) % APP_TX_DATA_SIZE;
240 count++;
242 return count;
245 uint32_t CDC_Receive_BytesAvailable(void)
247 /* return the bytes available in the receive circular buffer */
248 return (APP_Tx_ptr_in + APP_TX_DATA_SIZE - APP_Tx_ptr_out) % APP_TX_DATA_SIZE;
252 * @brief VCP_DataRx
253 * Data received over USB OUT endpoint are sent over CDC interface
254 * through this function.
256 * @note
257 * This function will block any OUT packet reception on USB endpoint
258 * until exiting this function. If you exit this function before transfer
259 * is complete on CDC interface (ie. using DMA controller) it will result
260 * in receiving more data while previous ones are still not sent.
262 * @param Buf: Buffer of data to be received
263 * @param Len: Number of data received (in bytes)
264 * @retval Result of the opeartion: USBD_OK if all operations are OK else VCP_FAIL
266 static uint16_t VCP_DataRx(uint8_t* Buf, uint32_t Len)
268 if (CDC_Receive_BytesAvailable() + Len > APP_TX_DATA_SIZE) {
269 return USBD_FAIL;
272 for (uint32_t i = 0; i < Len; i++) {
273 APP_Tx_Buffer[APP_Tx_ptr_in] = Buf[i];
274 APP_Tx_ptr_in = (APP_Tx_ptr_in + 1) % APP_TX_DATA_SIZE;
277 return USBD_OK;
280 /*******************************************************************************
281 * Function Name : usbIsConfigured.
282 * Description : Determines if USB VCP is configured or not
283 * Input : None.
284 * Output : None.
285 * Return : True if configured.
286 *******************************************************************************/
287 uint8_t usbIsConfigured(void)
289 return (bDeviceState == CONFIGURED);
292 /*******************************************************************************
293 * Function Name : usbIsConnected.
294 * Description : Determines if USB VCP is connected ot not
295 * Input : None.
296 * Output : None.
297 * Return : True if connected.
298 *******************************************************************************/
299 uint8_t usbIsConnected(void)
301 return (bDeviceState != UNCONNECTED);
304 /*******************************************************************************
305 * Function Name : CDC_BaudRate.
306 * Description : Get the current baud rate
307 * Input : None.
308 * Output : None.
309 * Return : Baud rate in bps
310 *******************************************************************************/
311 uint32_t CDC_BaudRate(void)
313 return g_lc.bitrate;
316 /*******************************************************************************
317 * Function Name : CDC_SetBaudRateCb
318 * Description : Set a callback to call when baud rate changes
319 * Input : callback function and context.
320 * Output : None.
321 * Return : None.
322 *******************************************************************************/
323 void CDC_SetBaudRateCb(void (*cb)(void *context, uint32_t baud), void *context)
325 baudRateCbContext = context;
326 baudRateCb = cb;
329 /*******************************************************************************
330 * Function Name : CDC_SetCtrlLineStateCb
331 * Description : Set a callback to call when control line state changes
332 * Input : callback function and context.
333 * Output : None.
334 * Return : None.
335 *******************************************************************************/
336 void CDC_SetCtrlLineStateCb(void (*cb)(void *context, uint16_t ctrlLineState), void *context)
338 ctrlLineStateCbContext = context;
339 ctrlLineStateCb = cb;
342 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/