From f0d51db58b0d8a867f1e701063c667c510114f51 Mon Sep 17 00:00:00 2001 From: Hermes Date: Wed, 30 Sep 2026 18:19:46 +0200 Subject: [PATCH] fix(gx12): persist Ground Station AUX1 serial mode across reboot The YAML serializer's UART mode lookup table had no entry for UART_MODE_GROUND_STATION, so the AUX1 selection was written with an empty value and read back as OFF after a power cycle. Add the missing table entry and regression tests for the save/reload roundtrip of all AUX1 modes and the legacy auxSerialMode migration. --- .../storage/yaml/yaml_datastructs_funcs.cpp | 1 + radio/src/tests/serial_mode.cpp | 110 ++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 radio/src/tests/serial_mode.cpp diff --git a/radio/src/storage/yaml/yaml_datastructs_funcs.cpp b/radio/src/storage/yaml/yaml_datastructs_funcs.cpp index 9f1406b6b..696651b20 100644 --- a/radio/src/storage/yaml/yaml_datastructs_funcs.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_funcs.cpp @@ -2683,6 +2683,7 @@ static const struct YamlIdStr enum_UartModes[] = { { UART_MODE_DEBUG, "DEBUG" }, { UART_MODE_SPACEMOUSE, "SPACEMOUSE" }, { UART_MODE_EXT_MODULE, "EXT_MODULE" }, + { UART_MODE_GROUND_STATION, "GROUND_STATION" }, { 0, NULL } }; diff --git a/radio/src/tests/serial_mode.cpp b/radio/src/tests/serial_mode.cpp new file mode 100644 index 000000000..4c3c5275f --- /dev/null +++ b/radio/src/tests/serial_mode.cpp @@ -0,0 +1,110 @@ +/* + * Copyright (C) EdgeTX + * + * Based on code named + * opentx - https://github.com/opentx/opentx + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "gtests.h" + +#include "storage/yaml/yaml_tree_walker.h" +#include "storage/yaml/yaml_parser.h" +#include "storage/yaml/yaml_datastructs.h" + +static bool yamlStringWriter(void* opaque, const char* str, size_t len) +{ + auto* out = reinterpret_cast(opaque); + out->append(str, len); + return true; +} + +static std::string serialPortToYaml() +{ + std::string out; + YamlTreeWalker tree; + tree.reset(get_radiodata_nodes(), (uint8_t*)&g_eeGeneral); + EXPECT_TRUE(tree.generate(yamlStringWriter, &out)); + return out; +} + +static void loadRadioYamlStr(const char* str) +{ + YamlTreeWalker tree; + tree.reset(get_radiodata_nodes(), (uint8_t*)&g_eeGeneral); + + YamlParser yp; + yp.init(YamlTreeWalker::get_parser_calls(), &tree); + + yp.parse(str, strlen(str)); +} + +static int getPortMode(uint8_t port_nr) +{ + uint32_t cfg = g_eeGeneral.serialPort; + cfg >>= (port_nr * SERIAL_CONF_BITS_PER_PORT); + return cfg & SERIAL_CONF_MODE_MASK; +} + +class SerialModeTest : public EdgeTxTest {}; + +// Regression: the Ground Station mode on AUX1 was dropped when the radio +// settings YAML was written, so the selection reset to OFF after a reboot. +TEST(SerialModeTest, GroundStationAux1ModeSurvivesSaveReload) +{ + uint32_t savedSerialPort = g_eeGeneral.serialPort; + + serialSetMode(SP_AUX1, UART_MODE_GROUND_STATION); + + std::string yaml = serialPortToYaml(); + EXPECT_NE(yaml.find("mode: GROUND_STATION"), std::string::npos) + << yaml; + + // simulate a reboot: defaults are loaded, then the YAML file is read back + g_eeGeneral.serialPort = 0; + loadRadioYamlStr(yaml.c_str()); + EXPECT_EQ(getPortMode(SP_AUX1), UART_MODE_GROUND_STATION); + EXPECT_EQ(getPortMode(SP_AUX2), (int)UART_MODE_NONE); + + g_eeGeneral.serialPort = savedSerialPort; +} + +// The mode table change must not disturb the other AUX1 modes. +TEST(SerialModeTest, AllAux1ModesSurviveSaveReload) +{ + uint32_t savedSerialPort = g_eeGeneral.serialPort; + + for (int mode = 0; mode <= UART_MODE_MAX; mode++) { + g_eeGeneral.serialPort = 0; + serialSetMode(SP_AUX1, mode); + + std::string yaml = serialPortToYaml(); + + g_eeGeneral.serialPort = 0; + loadRadioYamlStr(yaml.c_str()); + EXPECT_EQ(getPortMode(SP_AUX1), mode) << "mode " << mode << ", yaml:" << yaml; + } + + g_eeGeneral.serialPort = savedSerialPort; +} + +// Legacy attribute (pre serialPort array) must still be migrated on load. +TEST(SerialModeTest, LegacyAuxSerialModeAttrStillMigrates) +{ + static const char _legacy[] = "auxSerialMode: MODE_LUA\r\n"; + loadRadioYamlStr(_legacy); + EXPECT_EQ(getPortMode(SP_AUX1), (int)UART_MODE_LUA); +} -- 2.54.0