From f3e696240824fc48e07d6ab767272aafe953d686 Mon Sep 17 00:00:00 2001 From: Raphael Hunziker Date: Thu, 10 Sep 2026 07:26:18 +0200 Subject: [PATCH] LED rainbow overlay: keep COLOR_WHITE white, bound the CLI led string Follow-ups to the rainbow overlay review: - COLOR_WHITE was changed to {0, 0, 255}; hsvToRgb24() stores saturation inverted, so that renders pure red and would have hit every user of the palette entry after the PG bump. Restore {0, 255, 255}. - With eight overlays the CLI led string can reach 25 characters ("15,15:NESWUD:CTOBNIWEV:15"), more than the 20-byte stack buffers in printLed(). Size them with LED_CONFIG_STRING_LENGTH (32) and format with tfp_snprintf() so generateLedConfig() can never overrun its buffer. - The rainbow layer overwrote every field of the colour it read; build the colour directly. - Restore the executable bit on update_cli_docs.py. --- src/main/fc/cli.c | 4 ++-- src/main/io/ledstrip.c | 15 +++++++-------- src/main/io/ledstrip.h | 3 +++ src/utils/update_cli_docs.py | 0 4 files changed, 12 insertions(+), 10 deletions(-) mode change 100644 => 100755 src/utils/update_cli_docs.py diff --git a/src/main/fc/cli.c b/src/main/fc/cli.c index 3f85979a788..cfb89c18ee7 100644 --- a/src/main/fc/cli.c +++ b/src/main/fc/cli.c @@ -2043,8 +2043,8 @@ static void cliWaypoints(char *cmdline) static void printLed(uint8_t dumpMask, const ledConfig_t *ledConfigs, const ledConfig_t *defaultLedConfigs) { const char *format = "led %u %s"; - char ledConfigBuffer[20]; - char ledConfigDefaultBuffer[20]; + char ledConfigBuffer[LED_CONFIG_STRING_LENGTH]; + char ledConfigDefaultBuffer[LED_CONFIG_STRING_LENGTH]; for (uint32_t i = 0; i < LED_MAX_STRIP_LENGTH; i++) { ledConfig_t ledConfig = ledConfigs[i]; generateLedConfig(&ledConfig, ledConfigBuffer, sizeof(ledConfigBuffer)); diff --git a/src/main/io/ledstrip.c b/src/main/io/ledstrip.c index 1d454888a1d..8001bdff5d6 100644 --- a/src/main/io/ledstrip.c +++ b/src/main/io/ledstrip.c @@ -92,7 +92,7 @@ static void ledStripDisable(void); const hsvColor_t hsv[] = { // H S V [COLOR_BLACK] = { 0, 0, 0}, - [COLOR_WHITE] = { 0, 0, 255}, + [COLOR_WHITE] = { 0, 255, 255}, [COLOR_RED] = { 0, 0, 255}, [COLOR_ORANGE] = { 30, 0, 255}, [COLOR_YELLOW] = { 60, 0, 255}, @@ -342,8 +342,7 @@ void generateLedConfig(ledConfig_t *ledConfig, char *ledConfigBuffer, size_t buf } *fptr = 0; - // TODO - check buffer length - tfp_sprintf(ledConfigBuffer, "%u,%u:%s:%s:%u", ledGetX(ledConfig), ledGetY(ledConfig), directions, baseFunctionOverlays, ledGetColor(ledConfig)); + tfp_snprintf(ledConfigBuffer, bufferSize, "%u,%u:%s:%s:%u", ledGetX(ledConfig), ledGetY(ledConfig), directions, baseFunctionOverlays, ledGetColor(ledConfig)); } typedef enum { @@ -871,11 +870,11 @@ static void applyLedRainbowLayer(bool updateNow, timeUs_t *timer) const ledConfig_t *ledConfig = &ledStripConfig()->ledConfigs[i]; if (ledGetOverlayBit(ledConfig, LED_OVERLAY_RAINBOW)) { - hsvColor_t ledColor; - getLedHsv(i, &ledColor); - ledColor.h = (rainbowHue + (rainbowIndex * rainbowDelta)) % 360; - ledColor.s = 0; // Force full color saturation (Required) - ledColor.v = 255; // Force full brightness (Required) + const hsvColor_t ledColor = { + .h = (rainbowHue + (rainbowIndex * rainbowDelta)) % 360, + .s = 0, // full saturation (INAV stores saturation inverted) + .v = 255, // full brightness + }; setLedHsv(i, &ledColor); rainbowIndex++; } diff --git a/src/main/io/ledstrip.h b/src/main/io/ledstrip.h index ff3c2fcec44..aa426e5865d 100644 --- a/src/main/io/ledstrip.h +++ b/src/main/io/ledstrip.h @@ -27,6 +27,9 @@ #define LED_DIRECTION_COUNT 6 #define LED_BASEFUNCTION_COUNT 8 #define LED_OVERLAY_COUNT 8 + +// Longest CLI representation of one LED, e.g. "15,15:NESWUD:CTOBNIWEV:15" (25 characters) plus the terminator +#define LED_CONFIG_STRING_LENGTH 32 #define LED_SPECIAL_COLOR_COUNT 9 #define LED_FUNCTION_OFFSET 8 diff --git a/src/utils/update_cli_docs.py b/src/utils/update_cli_docs.py old mode 100644 new mode 100755