New SPI API supporting DMA
[betaflight.git] / src / main / vcpf4 / usbd_cdc_vcp.c
blobdccf0eddbf55d216dfd3b0c5251e17afe5a816d6
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 "platform.h"
26 #include "usbd_cdc_vcp.h"
27 #include "stm32f4xx_conf.h"
28 #include "stdbool.h"
29 #include "drivers/time.h"
31 #ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
32 #pragma data_alignment = 4
33 #endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
35 __ALIGN_BEGIN USB_OTG_CORE_HANDLE USB_OTG_dev __ALIGN_END;
37 LINE_CODING g_lc;
39 extern __IO uint8_t USB_Tx_State;
40 __IO uint32_t bDeviceState = UNCONNECTED; /* USB device status */
42 /* These are external variables imported from CDC core to be used for IN transfer management. */
44 /* This is the buffer for data received from the MCU to APP (i.e. MCU TX, APP RX) */
45 extern uint8_t APP_Rx_Buffer[];
46 extern uint32_t APP_Rx_ptr_out;
47 /* Increment this buffer position or roll it back to
48 start address when writing received data
49 in the buffer APP_Rx_Buffer. */
50 extern uint32_t APP_Rx_ptr_in;
53 APP TX is the circular buffer for data that is transmitted from the APP (host)
54 to the USB device (flight controller).
56 static uint8_t APP_Tx_Buffer[APP_TX_DATA_SIZE];
57 static uint32_t APP_Tx_ptr_out = 0;
58 static uint32_t APP_Tx_ptr_in = 0;
60 /* Private function prototypes -----------------------------------------------*/
61 static uint16_t VCP_Init(void);
62 static uint16_t VCP_DeInit(void);
63 static uint16_t VCP_Ctrl(uint32_t Cmd, uint8_t* Buf, uint32_t Len);
64 static uint16_t VCP_DataTx(const uint8_t* Buf, uint32_t Len);
65 static uint16_t VCP_DataRx(uint8_t* Buf, uint32_t Len);
66 static void (*ctrlLineStateCb)(void* context, uint16_t ctrlLineState);
67 static void *ctrlLineStateCbContext;
68 static void (*baudRateCb)(void *context, uint32_t baud);
69 static void *baudRateCbContext;
72 CDC_IF_Prop_TypeDef VCP_fops = {VCP_Init, VCP_DeInit, VCP_Ctrl, VCP_DataTx, VCP_DataRx };
74 /* Private functions ---------------------------------------------------------*/
75 /**
76 * @brief VCP_Init
77 * Initializes the Media on the STM32
78 * @param None
79 * @retval Result of the opeartion (USBD_OK in all cases)
81 static uint16_t VCP_Init(void)
83 bDeviceState = CONFIGURED;
84 ctrlLineStateCb = NULL;
85 baudRateCb = NULL;
86 return USBD_OK;
89 /**
90 * @brief VCP_DeInit
91 * DeInitializes the Media on the STM32
92 * @param None
93 * @retval Result of the opeartion (USBD_OK in all cases)
95 static uint16_t VCP_DeInit(void)
97 bDeviceState = UNCONNECTED;
98 return USBD_OK;
101 void ust_cpy(LINE_CODING* plc2, const LINE_CODING* plc1)
103 plc2->bitrate = plc1->bitrate;
104 plc2->format = plc1->format;
105 plc2->paritytype = plc1->paritytype;
106 plc2->datatype = plc1->datatype;
110 * @brief VCP_Ctrl
111 * Manage the CDC class requests
112 * @param Cmd: Command code
113 * @param Buf: Buffer containing command data (request parameters)
114 * @param Len: Number of data to be sent (in bytes)
115 * @retval Result of the opeartion (USBD_OK in all cases)
117 static uint16_t VCP_Ctrl(uint32_t Cmd, uint8_t* Buf, uint32_t Len)
119 LINE_CODING* plc = (LINE_CODING*)Buf;
121 assert_param(Len>=sizeof(LINE_CODING));
123 switch (Cmd) {
124 /* Not needed for this driver, AT modem commands */
125 case SEND_ENCAPSULATED_COMMAND:
126 case GET_ENCAPSULATED_RESPONSE:
127 break;
129 // Not needed for this driver
130 case SET_COMM_FEATURE:
131 case GET_COMM_FEATURE:
132 case CLEAR_COMM_FEATURE:
133 break;
136 //Note - hw flow control on UART 1-3 and 6 only
137 case SET_LINE_CODING:
138 // If a callback is provided, tell the upper driver of changes in baud rate
139 if (plc && (Len == sizeof (*plc))) {
140 if (baudRateCb) {
141 baudRateCb(baudRateCbContext, plc->bitrate);
143 ust_cpy(&g_lc, plc); //Copy into structure to save for later
145 break;
148 case GET_LINE_CODING:
149 if (plc && (Len == sizeof (*plc))) {
150 ust_cpy(plc, &g_lc);
152 break;
155 case SET_CONTROL_LINE_STATE:
156 // If a callback is provided, tell the upper driver of changes in DTR/RTS state
157 if (plc && (Len == sizeof (uint16_t))) {
158 if (ctrlLineStateCb) {
159 ctrlLineStateCb(ctrlLineStateCbContext, *((uint16_t *)Buf));
162 break;
164 case SEND_BREAK:
165 /* Not needed for this driver */
166 break;
168 default:
169 break;
172 return USBD_OK;
175 /*******************************************************************************
176 * Function Name : Send DATA .
177 * Description : send the data received from the STM32 to the PC through USB
178 * Input : buffer to send, and the length of the buffer.
179 * Output : None.
180 * Return : None.
181 *******************************************************************************/
182 uint32_t CDC_Send_DATA(const uint8_t *ptrBuffer, uint32_t sendLength)
184 VCP_DataTx(ptrBuffer, sendLength);
185 return sendLength;
188 uint32_t CDC_Send_FreeBytes(void)
191 return the bytes free in the circular buffer
193 functionally equivalent to:
194 (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)
195 but without the impact of the condition check.
197 return ((APP_Rx_ptr_out - APP_Rx_ptr_in) + (-((int)(APP_Rx_ptr_out <= APP_Rx_ptr_in)) & APP_RX_DATA_SIZE)) - 1;
201 * @brief VCP_DataTx
202 * CDC data to be sent to the Host (app) over USB
203 * @param Buf: Buffer of data to be sent
204 * @param Len: Number of data to be sent (in bytes)
205 * @retval Result of the operation: USBD_OK if all operations are OK else VCP_FAIL
207 static uint16_t VCP_DataTx(const uint8_t* Buf, uint32_t Len)
210 make sure that any paragraph end frame is not in play
211 could just check for: USB_CDC_ZLP, but better to be safe
212 and wait for any existing transmission to complete.
214 while (USB_Tx_State != 0);
216 for (uint32_t i = 0; i < Len; i++) {
217 APP_Rx_Buffer[APP_Rx_ptr_in] = Buf[i];
218 APP_Rx_ptr_in = (APP_Rx_ptr_in + 1) % APP_RX_DATA_SIZE;
220 while (CDC_Send_FreeBytes() == 0) {
221 delay(1);
225 return USBD_OK;
228 /*******************************************************************************
229 * Function Name : Receive DATA .
230 * Description : receive the data from the PC to STM32 and send it through USB
231 * Input : None.
232 * Output : None.
233 * Return : None.
234 *******************************************************************************/
235 uint32_t CDC_Receive_DATA(uint8_t* recvBuf, uint32_t len)
237 uint32_t count = 0;
239 while (APP_Tx_ptr_out != APP_Tx_ptr_in && count < len) {
240 recvBuf[count] = APP_Tx_Buffer[APP_Tx_ptr_out];
241 APP_Tx_ptr_out = (APP_Tx_ptr_out + 1) % APP_TX_DATA_SIZE;
242 count++;
244 return count;
247 uint32_t CDC_Receive_BytesAvailable(void)
249 /* return the bytes available in the receive circular buffer */
250 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;
254 * @brief VCP_DataRx
255 * Data received over USB OUT endpoint are sent over CDC interface
256 * through this function.
258 * @note
259 * This function will block any OUT packet reception on USB endpoint
260 * until exiting this function. If you exit this function before transfer
261 * is complete on CDC interface (ie. using DMA controller) it will result
262 * in receiving more data while previous ones are still not sent.
264 * @param Buf: Buffer of data to be received
265 * @param Len: Number of data received (in bytes)
266 * @retval Result of the opeartion: USBD_OK if all operations are OK else VCP_FAIL
268 static uint16_t VCP_DataRx(uint8_t* Buf, uint32_t Len)
270 if (CDC_Receive_BytesAvailable() + Len > APP_TX_DATA_SIZE) {
271 return USBD_FAIL;
274 for (uint32_t i = 0; i < Len; i++) {
275 APP_Tx_Buffer[APP_Tx_ptr_in] = Buf[i];
276 APP_Tx_ptr_in = (APP_Tx_ptr_in + 1) % APP_TX_DATA_SIZE;
279 return USBD_OK;
282 /*******************************************************************************
283 * Function Name : usbIsConfigured.
284 * Description : Determines if USB VCP is configured or not
285 * Input : None.
286 * Output : None.
287 * Return : True if configured.
288 *******************************************************************************/
289 uint8_t usbIsConfigured(void)
291 return (bDeviceState == CONFIGURED);
294 /*******************************************************************************
295 * Function Name : usbIsConnected.
296 * Description : Determines if USB VCP is connected ot not
297 * Input : None.
298 * Output : None.
299 * Return : True if connected.
300 *******************************************************************************/
301 uint8_t usbIsConnected(void)
303 return (bDeviceState != UNCONNECTED);
306 /*******************************************************************************
307 * Function Name : CDC_BaudRate.
308 * Description : Get the current baud rate
309 * Input : None.
310 * Output : None.
311 * Return : Baud rate in bps
312 *******************************************************************************/
313 uint32_t CDC_BaudRate(void)
315 return g_lc.bitrate;
318 /*******************************************************************************
319 * Function Name : CDC_SetBaudRateCb
320 * Description : Set a callback to call when baud rate changes
321 * Input : callback function and context.
322 * Output : None.
323 * Return : None.
324 *******************************************************************************/
325 void CDC_SetBaudRateCb(void (*cb)(void *context, uint32_t baud), void *context)
327 baudRateCbContext = context;
328 baudRateCb = cb;
331 /*******************************************************************************
332 * Function Name : CDC_SetCtrlLineStateCb
333 * Description : Set a callback to call when control line state changes
334 * Input : callback function and context.
335 * Output : None.
336 * Return : None.
337 *******************************************************************************/
338 void CDC_SetCtrlLineStateCb(void (*cb)(void *context, uint16_t ctrlLineState), void *context)
340 ctrlLineStateCbContext = context;
341 ctrlLineStateCb = cb;
344 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/