From 81bed958d4f3e80e2bcf17365cccb2021febceb6 Mon Sep 17 00:00:00 2001 From: MUSTARDTIGERFPV Date: Thu, 1 Aug 2024 02:35:42 +0000 Subject: [PATCH] Allow serialpassthrough to set parity & stop bits --- docs/Cli.md | 2 +- src/main/drivers/serial.c | 5 +++ src/main/drivers/serial.h | 3 ++ src/main/drivers/serial_softserial.c | 6 +++ src/main/drivers/serial_tcp.c | 7 +++ src/main/drivers/serial_uart.c | 8 ++++ src/main/drivers/serial_uart_hal.c | 8 ++++ src/main/drivers/serial_uart_hal_at32f43x.c | 8 ++++ src/main/drivers/serial_usb_vcp.c | 9 ++++ src/main/drivers/serial_usb_vcp_at32f43x.c | 7 +++ src/main/fc/cli.c | 49 ++++++++++++++++++++- 11 files changed, 109 insertions(+), 3 deletions(-) diff --git a/docs/Cli.md b/docs/Cli.md index 6a48244a13a..2e45ae138f7 100644 --- a/docs/Cli.md +++ b/docs/Cli.md @@ -107,7 +107,7 @@ While connected to the CLI, all Logical Switches are temporarily disabled (5.1.0 | `save` | Save and reboot | | `sd_info` | Sdcard info | | `serial` | Configure serial ports. [Usage](Serial.md) | -| `serialpassthrough` | Passthrough serial data to port, with ` `, where `id` is the zero based port index, `baud` is a standard baud rate, and mode is `rx`, `tx`, or both (`rxtx`) | +| `serialpassthrough` | Passthrough serial data to port, with ` `, where `id` is the zero based port index, `baud` is a standard baud rate, mode is `rx`, `tx`, or both (`rxtx`), and options is a short string like `8N1` or `8E2` | | `servo` | Configure servos | | `set` | Change setting with name=value or blank or * for list | | `smix` | Custom servo mixer | diff --git a/src/main/drivers/serial.c b/src/main/drivers/serial.c index 165f9c31698..dc625aaa354 100644 --- a/src/main/drivers/serial.c +++ b/src/main/drivers/serial.c @@ -86,6 +86,11 @@ void serialSetMode(serialPort_t *instance, portMode_t mode) instance->vTable->setMode(instance, mode); } +void serialSetOptions(serialPort_t *instance, portOptions_t options) +{ + instance->vTable->setOptions(instance, options); +} + void serialWriteBufShim(void *instance, const uint8_t *data, int count) { serialWriteBuf((serialPort_t *)instance, data, count); diff --git a/src/main/drivers/serial.h b/src/main/drivers/serial.h index fcb787ded99..8e66b5f8445 100644 --- a/src/main/drivers/serial.h +++ b/src/main/drivers/serial.h @@ -95,6 +95,8 @@ struct serialPortVTable { void (*setMode)(serialPort_t *instance, portMode_t mode); + void (*setOptions)(serialPort_t *instance, portOptions_t options); + void (*writeBuf)(serialPort_t *instance, const void *data, int count); bool (*isConnected)(const serialPort_t *instance); @@ -113,6 +115,7 @@ void serialWriteBuf(serialPort_t *instance, const uint8_t *data, int count); uint8_t serialRead(serialPort_t *instance); void serialSetBaudRate(serialPort_t *instance, uint32_t baudRate); void serialSetMode(serialPort_t *instance, portMode_t mode); +void serialSetOptions(serialPort_t *instance, portOptions_t options); bool isSerialTransmitBufferEmpty(const serialPort_t *instance); void serialPrint(serialPort_t *instance, const char *str); uint32_t serialGetBaudRate(serialPort_t *instance); diff --git a/src/main/drivers/serial_softserial.c b/src/main/drivers/serial_softserial.c index 7ce128516f0..09352f4d61b 100644 --- a/src/main/drivers/serial_softserial.c +++ b/src/main/drivers/serial_softserial.c @@ -623,6 +623,11 @@ void softSerialSetMode(serialPort_t *instance, portMode_t mode) instance->mode = mode; } +void softSerialSetOptions(serialPort_t *instance, portOptions_t options) +{ + instance->options = options; +} + bool isSoftSerialTransmitBufferEmpty(const serialPort_t *instance) { return instance->txBufferHead == instance->txBufferTail; @@ -636,6 +641,7 @@ static const struct serialPortVTable softSerialVTable = { .serialSetBaudRate = softSerialSetBaudRate, .isSerialTransmitBufferEmpty = isSoftSerialTransmitBufferEmpty, .setMode = softSerialSetMode, + .setOptions = softSerialSetOptions, .isConnected = NULL, .writeBuf = NULL, .beginWrite = NULL, diff --git a/src/main/drivers/serial_tcp.c b/src/main/drivers/serial_tcp.c index 765f8308cd3..915f2a53605 100644 --- a/src/main/drivers/serial_tcp.c +++ b/src/main/drivers/serial_tcp.c @@ -317,6 +317,12 @@ void tcpSetMode(serialPort_t *instance, portMode_t mode) UNUSED(mode); } +void tcpSetOptions(serialPort_t *instance, portOptions_t options) +{ + UNUSED(instance); + UNUSED(options); +} + static const struct serialPortVTable tcpVTable[] = { { .serialWrite = tcpWrite, @@ -326,6 +332,7 @@ static const struct serialPortVTable tcpVTable[] = { .serialSetBaudRate = tcpSetBaudRate, .isSerialTransmitBufferEmpty = isTcpTransmitBufferEmpty, .setMode = tcpSetMode, + .setOptions = tcpSetOptions, .isConnected = tcpIsConnected, .writeBuf = tcpWritBuf, .beginWrite = NULL, diff --git a/src/main/drivers/serial_uart.c b/src/main/drivers/serial_uart.c index 7b9bbd7128e..9307b0cab8b 100644 --- a/src/main/drivers/serial_uart.c +++ b/src/main/drivers/serial_uart.c @@ -175,6 +175,13 @@ void uartSetMode(serialPort_t *instance, portMode_t mode) uartReconfigure(uartPort); } +void uartSetOptions(serialPort_t *instance, portOptions_t options) +{ + uartPort_t *uartPort = (uartPort_t *)instance; + uartPort->port.options = options; + uartReconfigure(uartPort); +} + uint32_t uartTotalRxBytesWaiting(const serialPort_t *instance) { const uartPort_t *s = (const uartPort_t*)instance; @@ -255,6 +262,7 @@ const struct serialPortVTable uartVTable[] = { .serialSetBaudRate = uartSetBaudRate, .isSerialTransmitBufferEmpty = isUartTransmitBufferEmpty, .setMode = uartSetMode, + .setOptions = uartSetOptions, .isConnected = NULL, .writeBuf = NULL, .beginWrite = NULL, diff --git a/src/main/drivers/serial_uart_hal.c b/src/main/drivers/serial_uart_hal.c index b1df6ed7541..cce38422848 100644 --- a/src/main/drivers/serial_uart_hal.c +++ b/src/main/drivers/serial_uart_hal.c @@ -185,6 +185,13 @@ void uartSetMode(serialPort_t *instance, portMode_t mode) uartReconfigure(uartPort); } +void uartSetOptions(serialPort_t *instance, portOptions_t options) +{ + uartPort_t *uartPort = (uartPort_t *)instance; + uartPort->port.options = options; + uartReconfigure(uartPort); +} + uint32_t uartTotalRxBytesWaiting(const serialPort_t *instance) { uartPort_t *s = (uartPort_t*)instance; @@ -266,6 +273,7 @@ const struct serialPortVTable uartVTable[] = { .serialSetBaudRate = uartSetBaudRate, .isSerialTransmitBufferEmpty = isUartTransmitBufferEmpty, .setMode = uartSetMode, + .setOptions = uartSetOptions, .isConnected = NULL, .writeBuf = NULL, .beginWrite = NULL, diff --git a/src/main/drivers/serial_uart_hal_at32f43x.c b/src/main/drivers/serial_uart_hal_at32f43x.c index 0e0f11b1c13..a06869ba10c 100644 --- a/src/main/drivers/serial_uart_hal_at32f43x.c +++ b/src/main/drivers/serial_uart_hal_at32f43x.c @@ -178,6 +178,13 @@ void uartSetMode(serialPort_t *instance, portMode_t mode) uartReconfigure(uartPort); } +void uartSetOptions(serialPort_t *instance, portOptions_t options) +{ + uartPort_t *uartPort = (uartPort_t *)instance; + uartPort->port.options = options; + uartReconfigure(uartPort); +} + uint32_t uartTotalRxBytesWaiting(const serialPort_t *instance) { const uartPort_t *s = (const uartPort_t*)instance; @@ -260,6 +267,7 @@ const struct serialPortVTable uartVTable[] = { .serialSetBaudRate = uartSetBaudRate, .isSerialTransmitBufferEmpty = isUartTransmitBufferEmpty, .setMode = uartSetMode, + .setOptions = uartSetOptions, .isConnected = NULL, .writeBuf = NULL, .beginWrite = NULL, diff --git a/src/main/drivers/serial_usb_vcp.c b/src/main/drivers/serial_usb_vcp.c index a90633d6cfd..7fdbad2a114 100644 --- a/src/main/drivers/serial_usb_vcp.c +++ b/src/main/drivers/serial_usb_vcp.c @@ -67,6 +67,14 @@ static void usbVcpSetMode(serialPort_t *instance, portMode_t mode) // TODO implement } +static void usbVcpSetOptions(serialPort_t *instance, portOptions_t options) +{ + UNUSED(instance); + UNUSED(options); + + // TODO implement +} + static bool isUsbVcpTransmitBufferEmpty(const serialPort_t *instance) { UNUSED(instance); @@ -184,6 +192,7 @@ static const struct serialPortVTable usbVTable[] = { .serialSetBaudRate = usbVcpSetBaudRate, .isSerialTransmitBufferEmpty = isUsbVcpTransmitBufferEmpty, .setMode = usbVcpSetMode, + .setOptions = usbVcpSetOptions, .isConnected = usbVcpIsConnected, .writeBuf = usbVcpWriteBuf, .beginWrite = usbVcpBeginWrite, diff --git a/src/main/drivers/serial_usb_vcp_at32f43x.c b/src/main/drivers/serial_usb_vcp_at32f43x.c index 29b96d1a2b6..96b283ec363 100644 --- a/src/main/drivers/serial_usb_vcp_at32f43x.c +++ b/src/main/drivers/serial_usb_vcp_at32f43x.c @@ -308,6 +308,12 @@ static void usbVcpSetMode(serialPort_t *instance, portMode_t mode) UNUSED(mode); } +static void usbVcpSetOptions(serialPort_t *instance, portOptions_t options) +{ + UNUSED(instance); + UNUSED(options); +} + static bool isUsbVcpTransmitBufferEmpty(const serialPort_t *instance) { UNUSED(instance); @@ -434,6 +440,7 @@ static const struct serialPortVTable usbVTable[] = { .serialSetBaudRate = usbVcpSetBaudRate, .isSerialTransmitBufferEmpty = isUsbVcpTransmitBufferEmpty, .setMode = usbVcpSetMode, + .setOptions = usbVcpSetOptions, .isConnected = usbVcpIsConnected, .writeBuf = usbVcpWriteBuf, .beginWrite = usbVcpBeginWrite, diff --git a/src/main/fc/cli.c b/src/main/fc/cli.c index 0ea43fd0ce7..b9cc2a993b9 100644 --- a/src/main/fc/cli.c +++ b/src/main/fc/cli.c @@ -913,6 +913,42 @@ static void cliSerial(char *cmdline) } #ifdef USE_SERIAL_PASSTHROUGH + +portOptions_t constructPortOptions(char *options) { + if (strlen(options) != 3 || options[0] != '8') { + // Invalid format + return -1; + } + + portOptions_t result = 0; + + switch (options[1]) { + case 'N': + result |= SERIAL_PARITY_NO; + break; + case 'E': + result |= SERIAL_PARITY_EVEN; + break; + default: + // Invalid format + return -1; + } + + switch (options[2]) { + case '1': + result |= SERIAL_STOPBITS_1; + break; + case '2': + result |= SERIAL_STOPBITS_2; + break; + default: + // Invalid format + return -1; + } + + return result; +} + static void cliSerialPassthrough(char *cmdline) { char * saveptr; @@ -925,6 +961,7 @@ static void cliSerialPassthrough(char *cmdline) int id = -1; uint32_t baud = 0; unsigned mode = 0; + portOptions_t options = SERIAL_NOT_INVERTED; char* tok = strtok_r(cmdline, " ", &saveptr); int index = 0; @@ -942,6 +979,9 @@ static void cliSerialPassthrough(char *cmdline) if (strstr(tok, "tx") || strstr(tok, "TX")) mode |= MODE_TX; break; + case 3: + options |= constructPortOptions(tok); + break; } index++; tok = strtok_r(NULL, " ", &saveptr); @@ -959,7 +999,7 @@ static void cliSerialPassthrough(char *cmdline) passThroughPort = openSerialPort(id, FUNCTION_NONE, NULL, NULL, baud, mode, - SERIAL_NOT_INVERTED); + options); if (!passThroughPort) { tfp_printf("Port %d could not be opened.\r\n", id); return; @@ -975,6 +1015,11 @@ static void cliSerialPassthrough(char *cmdline) passThroughPort->mode, mode); serialSetMode(passThroughPort, mode); } + if (options && passThroughPort->options != options) { + tfp_printf("Adjusting options from %d to %d.\r\n", + passThroughPort->options, options); + serialSetOptions(passThroughPort, options); + } // If this port has a rx callback associated we need to remove it now. // Otherwise no data will be pushed in the serial port buffer! if (passThroughPort->rxCallback) { @@ -4514,7 +4559,7 @@ const clicmd_t cmdTable[] = { CLI_COMMAND_DEF("save", "save and reboot", NULL, cliSave), CLI_COMMAND_DEF("serial", "configure serial ports", NULL, cliSerial), #ifdef USE_SERIAL_PASSTHROUGH - CLI_COMMAND_DEF("serialpassthrough", "passthrough serial data to port", " [baud] [mode] : passthrough to serial", cliSerialPassthrough), + CLI_COMMAND_DEF("serialpassthrough", "passthrough serial data to port", " [baud] [mode] [options]: passthrough to serial", cliSerialPassthrough), #endif CLI_COMMAND_DEF("servo", "configure servos", NULL, cliServo), #ifdef USE_PROGRAMMING_FRAMEWORK