diff --git a/src/main/io/serial.c b/src/main/io/serial.c index 901f14d2d2..2765cfb575 100644 --- a/src/main/io/serial.c +++ b/src/main/io/serial.c @@ -36,6 +36,9 @@ #include "drivers/serial_uart.h" #endif +#include "drivers/gpio.h" +#include "drivers/light_led.h" + #if defined(USE_VCP) #include "drivers/serial_usb_vcp.h" #endif @@ -92,7 +95,7 @@ baudRate_e lookupBaudRateIndex(uint32_t baudRate) return BAUD_AUTO; } -static serialPortUsage_t *findSerialPortUsageByIdentifier(serialPortIdentifier_e identifier) +serialPortUsage_t *findSerialPortUsageByIdentifier(serialPortIdentifier_e identifier) { uint8_t index; for (index = 0; index < SERIAL_PORT_COUNT; index++) { @@ -421,3 +424,55 @@ void evaluateOtherData(serialPort_t *serialPort, uint8_t receivedChar) systemResetToBootloader(); } } + +#if defined(GPS) || ! defined(SKIP_SERIAL_PASSTHROUGH) +// Default data consumer for serialPassThrough. +static void nopConsumer(uint8_t data) +{ + UNUSED(data); +} + +/* + A high-level serial passthrough implementation. Used by cli to start an + arbitrary serial passthrough "proxy". Optional callbacks can be given to allow + for specialized data processing. + */ +void serialPassthrough(serialPort_t *left, serialPort_t *right, serialConsumer + *leftC, serialConsumer *rightC) +{ + waitForSerialPortToFinishTransmitting(left); + waitForSerialPortToFinishTransmitting(right); + + if (!leftC) + leftC = &nopConsumer; + if (!rightC) + rightC = &nopConsumer; + + LED0_OFF; + LED1_OFF; + + // Either port might be open in a mode other than MODE_RXTX. We rely on + // serialRxBytesWaiting() to do the right thing for a TX only port. No + // special handling is necessary OR performed. + while(1) { + // TODO: maintain a timestamp of last data received. Use this to + // implement a guard interval and check for `+++` as an escape sequence + // to return to CLI command mode. + // https://en.wikipedia.org/wiki/Escape_sequence#Modem_control + if (serialRxBytesWaiting(left)) { + LED0_ON; + uint8_t c = serialRead(left); + serialWrite(right, c); + leftC(c); + LED0_OFF; + } + if (serialRxBytesWaiting(right)) { + LED0_ON; + uint8_t c = serialRead(right); + serialWrite(left, c); + rightC(c); + LED0_OFF; + } + } + } + #endif