diff --git a/core/SConscript.unix b/core/SConscript.unix
index 559f14c2a8..7e70f3dea3 100644
--- a/core/SConscript.unix
+++ b/core/SConscript.unix
@@ -21,7 +21,7 @@ if BENCHMARK and PYOPT != '0':
print("BENCHMARK=1 works only with PYOPT=0.")
exit(1)
-FEATURES_WANTED = ["input", "sd_card", "dma2d", "optiga"]
+FEATURES_WANTED = ["input", "rgb_led", "sd_card", "dma2d", "optiga"]
if not models.has_emulator(TREZOR_MODEL):
# skip unix build
diff --git a/core/embed/io/display/inc/io/display.h b/core/embed/io/display/inc/io/display.h
index afb5252f94..9c52cd6018 100644
--- a/core/embed/io/display/inc/io/display.h
+++ b/core/embed/io/display/inc/io/display.h
@@ -159,4 +159,10 @@ void display_copy_mono1p(const gfx_bitblt_t *bb);
// The function is available only on the emulator.
const char *display_save(const char *prefix);
void display_clear_save(void);
+
+#ifdef USE_RGB_LED
+// Display a color on the LED.
+// The function is available only on the emulator.
+void display_rgb_led(uint32_t color);
+#endif
#endif
diff --git a/core/embed/io/display/unix/display_driver.c b/core/embed/io/display/unix/display_driver.c
index 6b1a8b9ef2..50aafb933f 100644
--- a/core/embed/io/display/unix/display_driver.c
+++ b/core/embed/io/display/unix/display_driver.c
@@ -74,6 +74,9 @@ typedef struct {
// and we have to simulate it
uint8_t mono_framebuf[DISPLAY_RESX * DISPLAY_RESY];
#endif
+#ifdef USE_RGB_LED
+ uint32_t led_color;
+#endif
} display_driver_t;
@@ -319,6 +322,46 @@ static void copy_mono_framebuf(display_driver_t *drv) {
}
#endif
+#ifdef USE_RGB_LED
+void draw_rgb_led(uint32_t color) {
+ display_driver_t *drv = &g_display_driver;
+
+ if (!drv->initialized) {
+ return;
+ }
+ // Extract RGB components
+ uint32_t r = (color >> 16) & 0xFF;
+ uint32_t g = (color >> 8) & 0xFF;
+ uint32_t b = color & 0xFF;
+
+ // Define LED circle properties
+ const int radius = 5;
+ int center_x = DISPLAY_RESX / 2;
+ int center_y = 0;
+
+ // Position based on background
+ if (drv->background) {
+ center_x += TOUCH_OFFSET_X;
+ center_y = TOUCH_OFFSET_Y / 2;
+ } else {
+ center_x += EMULATOR_BORDER;
+ center_y = EMULATOR_BORDER / 2;
+ }
+
+ // Draw the LED
+ SDL_SetRenderDrawColor(drv->renderer, r, g, b, 255);
+ for (int y = -radius; y <= radius; y++) {
+ for (int x = -radius; x <= radius; x++) {
+ if (x * x + y * y <= radius * radius) {
+ SDL_RenderDrawPoint(drv->renderer, center_x + x, center_y + y);
+ }
+ }
+ }
+ SDL_SetRenderDrawColor(drv->renderer, 0, 0, 0, 255);
+ SDL_RenderPresent(drv->renderer);
+}
+#endif
+
void display_refresh(void) {
display_driver_t *drv = &g_display_driver;
@@ -353,6 +396,10 @@ void display_refresh(void) {
SDL_RenderCopyEx(drv->renderer, drv->texture, NULL, &r,
drv->orientation_angle, NULL, 0);
}
+ // Show the LED
+#ifdef USE_RGB_LED
+ draw_rgb_led(drv->led_color);
+#endif
SDL_RenderPresent(drv->renderer);
}
@@ -493,3 +540,14 @@ void display_clear_save(void) {
SDL_FreeSurface(drv->prev_saved);
drv->prev_saved = NULL;
}
+
+#ifdef USE_RGB_LED
+void display_rgb_led(uint32_t color) {
+ display_driver_t *drv = &g_display_driver;
+
+ if (!drv->initialized) {
+ return;
+ }
+ drv->led_color = color;
+}
+#endif
diff --git a/core/embed/io/rgb_led/unix/rgb_led.c b/core/embed/io/rgb_led/unix/rgb_led.c
new file mode 100644
index 0000000000..3c245d9cf6
--- /dev/null
+++ b/core/embed/io/rgb_led/unix/rgb_led.c
@@ -0,0 +1,23 @@
+/*
+ * This file is part of the Trezor project, https://trezor.io/
+ *
+ * Copyright (c) SatoshiLabs
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+#include
+
+void rgb_led_set_color(uint32_t color) { display_rgb_led(color); }
diff --git a/core/site_scons/models/T3W1/emulator.py b/core/site_scons/models/T3W1/emulator.py
index 0aa1eb5beb..4281c57dcb 100644
--- a/core/site_scons/models/T3W1/emulator.py
+++ b/core/site_scons/models/T3W1/emulator.py
@@ -45,6 +45,12 @@ def configure(
paths += ["embed/io/sbu/inc"]
defines += [("USE_SBU", "1")]
+ if "rgb_led" in features_wanted:
+ sources += ["embed/io/rgb_led/unix/rgb_led.c"]
+ paths += ["embed/io/rgb_led/inc"]
+ features_available.append("rgb_led")
+ defines += [("USE_RGB_LED", "1")]
+
if "optiga" in features_wanted:
sources += ["embed/sec/optiga/unix/optiga_hal.c"]
sources += ["embed/sec/optiga/unix/optiga.c"]