Set blackbox file handler to NULL after closing file
[inav.git] / src / main / drivers / serial_usb_vcp.c
bloba90633d6cfd94ec898478e8942fdc681424a4722
1 /*
2 * This file is part of Cleanflight.
4 * Cleanflight is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * Cleanflight is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
18 #include <stdint.h>
19 #include <stdbool.h>
21 #include "platform.h"
23 #ifdef USE_VCP
25 #include "build/build_config.h"
27 #include "common/utils.h"
28 #include "drivers/io.h"
30 #if defined(STM32F4)
31 #include "usb_core.h"
32 #include "usbd_cdc_vcp.h"
33 #include "usb_io.h"
34 #elif defined(STM32F7) || defined(STM32H7)
35 #include "vcp_hal/usbd_cdc_interface.h"
36 #include "usb_io.h"
37 USBD_HandleTypeDef USBD_Device;
38 #else
39 #include "usb_core.h"
40 #include "usb_init.h"
41 #include "hw_config.h"
42 #endif
44 #include "drivers/time.h"
46 #include "serial.h"
47 #include "serial_usb_vcp.h"
50 #define USB_TIMEOUT 50
52 static vcpPort_t vcpPort;
54 static void usbVcpSetBaudRate(serialPort_t *instance, uint32_t baudRate)
56 UNUSED(instance);
57 UNUSED(baudRate);
59 // TODO implement
62 static void usbVcpSetMode(serialPort_t *instance, portMode_t mode)
64 UNUSED(instance);
65 UNUSED(mode);
67 // TODO implement
70 static bool isUsbVcpTransmitBufferEmpty(const serialPort_t *instance)
72 UNUSED(instance);
73 return true;
76 static uint32_t usbVcpAvailable(const serialPort_t *instance)
78 UNUSED(instance);
80 return CDC_Receive_BytesAvailable();
83 static uint8_t usbVcpRead(serialPort_t *instance)
85 UNUSED(instance);
87 uint8_t buf[1];
89 while (true) {
90 if (CDC_Receive_DATA(buf, 1))
91 return buf[0];
95 static bool usbVcpIsConnected(const serialPort_t *instance)
97 (void)instance;
98 return usbIsConnected() && usbIsConfigured();
101 static void usbVcpWriteBuf(serialPort_t *instance, const void *data, int count)
103 UNUSED(instance);
105 if (!usbVcpIsConnected(instance)) {
106 return;
109 uint32_t start = millis();
110 const uint8_t *p = data;
111 while (count > 0) {
112 uint32_t txed = CDC_Send_DATA(p, count);
113 count -= txed;
114 p += txed;
116 if (millis() - start > USB_TIMEOUT) {
117 break;
122 static bool usbVcpFlush(vcpPort_t *port)
124 uint32_t count = port->txAt;
125 port->txAt = 0;
127 if (count == 0) {
128 return true;
131 if (!usbIsConnected() || !usbIsConfigured()) {
132 return false;
135 uint32_t start = millis();
136 uint8_t *p = port->txBuf;
137 while (count > 0) {
138 uint32_t txed = CDC_Send_DATA(p, count);
139 count -= txed;
140 p += txed;
142 if (millis() - start > USB_TIMEOUT) {
143 break;
146 return count == 0;
149 static void usbVcpWrite(serialPort_t *instance, uint8_t c)
151 vcpPort_t *port = container_of(instance, vcpPort_t, port);
153 port->txBuf[port->txAt++] = c;
154 if (!port->buffering || port->txAt >= ARRAYLEN(port->txBuf)) {
155 usbVcpFlush(port);
159 static void usbVcpBeginWrite(serialPort_t *instance)
161 vcpPort_t *port = container_of(instance, vcpPort_t, port);
162 port->buffering = true;
165 static uint32_t usbTxBytesFree(const serialPort_t *instance)
167 UNUSED(instance);
168 return CDC_Send_FreeBytes();
171 static void usbVcpEndWrite(serialPort_t *instance)
173 vcpPort_t *port = container_of(instance, vcpPort_t, port);
174 port->buffering = false;
175 usbVcpFlush(port);
178 static const struct serialPortVTable usbVTable[] = {
180 .serialWrite = usbVcpWrite,
181 .serialTotalRxWaiting = usbVcpAvailable,
182 .serialTotalTxFree = usbTxBytesFree,
183 .serialRead = usbVcpRead,
184 .serialSetBaudRate = usbVcpSetBaudRate,
185 .isSerialTransmitBufferEmpty = isUsbVcpTransmitBufferEmpty,
186 .setMode = usbVcpSetMode,
187 .isConnected = usbVcpIsConnected,
188 .writeBuf = usbVcpWriteBuf,
189 .beginWrite = usbVcpBeginWrite,
190 .endWrite = usbVcpEndWrite,
191 .isIdle = NULL,
195 void usbVcpInitHardware(void)
197 #if defined(STM32F4)
198 usbGenerateDisconnectPulse();
200 IOInit(IOGetByTag(IO_TAG(PA11)), OWNER_USB, RESOURCE_INPUT, 0);
201 IOInit(IOGetByTag(IO_TAG(PA12)), OWNER_USB, RESOURCE_OUTPUT, 0);
202 USBD_Init(&USB_OTG_dev, USB_OTG_FS_CORE_ID, &USR_desc, &USBD_CDC_cb, &USR_cb);
203 #elif defined(STM32F7) || defined(STM32H7)
204 usbGenerateDisconnectPulse();
206 IOInit(IOGetByTag(IO_TAG(PA11)), OWNER_USB, RESOURCE_INPUT, 0);
207 IOInit(IOGetByTag(IO_TAG(PA12)), OWNER_USB, RESOURCE_OUTPUT, 0);
208 /* Init Device Library */
209 USBD_Init(&USBD_Device, &VCP_Desc, 0);
211 /* Add Supported Class */
212 USBD_RegisterClass(&USBD_Device, USBD_CDC_CLASS);
214 /* Add CDC Interface Class */
215 USBD_CDC_RegisterInterface(&USBD_Device, &USBD_CDC_fops);
217 /* Start Device Process */
218 USBD_Start(&USBD_Device);
220 #ifdef STM32H7
221 HAL_PWREx_EnableUSBVoltageDetector();
222 delay(100); // Cold boot failures observed without this, even when USB cable is not connected
223 #endif
225 #else
226 Set_System();
227 Set_USBClock();
228 USB_Interrupts_Config();
229 USB_Init();
230 #endif
233 serialPort_t *usbVcpOpen(void)
235 vcpPort_t *s;
237 s = &vcpPort;
238 s->port.vTable = usbVTable;
240 return (serialPort_t *)s;
243 uint32_t usbVcpGetBaudRate(serialPort_t *instance)
245 UNUSED(instance);
247 return CDC_BaudRate();
250 #endif