diff --git a/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_driver.c b/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_driver.c index 5395f44f5..559d1182e 100644 --- a/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_driver.c +++ b/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_driver.c @@ -41,10 +41,17 @@ #endif // Display driver instance -display_driver_t g_display_driver; +display_driver_t g_display_driver = { + .initialized = false, +}; void display_init(display_content_mode_t mode) { display_driver_t* drv = &g_display_driver; + + if (drv->initialized) { + return; + } + memset(drv, 0, sizeof(display_driver_t)); if (mode == DISPLAY_RESET_CONTENT) { @@ -67,9 +74,17 @@ void display_init(display_content_mode_t mode) { #ifdef XFRAMEBUFFER display_io_init_te_interrupt(); #endif + + drv->initialized = true; } void display_deinit(display_content_mode_t mode) { + display_driver_t* drv = &g_display_driver; + + if (!drv->initialized) { + return; + } + #ifdef XFRAMEBUFFER #ifndef BOARDLOADER // Ensure that the ready frame buffer is transfered to @@ -80,7 +95,8 @@ void display_deinit(display_content_mode_t mode) { #endif #endif - backlight_pwm_deinit(mode == DISPLAY_RESET_CONTENT ? BACKLIGHT_RESET : BACKLIGHT_RETAIN); + backlight_pwm_deinit(mode == DISPLAY_RESET_CONTENT ? BACKLIGHT_RESET + : BACKLIGHT_RETAIN); #ifdef TREZOR_MODEL_T // This ensures backward compatibility with legacy bootloader/firmware @@ -90,9 +106,17 @@ void display_deinit(display_content_mode_t mode) { } display_panel_set_big_endian(); #endif + + drv->initialized = false; } int display_set_backlight(int level) { + display_driver_t* drv = &g_display_driver; + + if (!drv->initialized) { + return 0; + } + #ifdef XFRAMEBUFFER #ifndef BOARDLOADER // if turning on the backlight, wait until the panel is refreshed @@ -110,6 +134,10 @@ int display_get_backlight(void) { return backlight_pwm_get(); } int display_set_orientation(int angle) { display_driver_t* drv = &g_display_driver; + if (!drv->initialized) { + return 0; + } + if (angle != drv->orientation_angle) { if (angle == 0 || angle == 90 || angle == 180 || angle == 270) { drv->orientation_angle = angle; @@ -135,5 +163,9 @@ int display_set_orientation(int angle) { int display_get_orientation(void) { display_driver_t* drv = &g_display_driver; + if (!drv->initialized) { + return 0; + } + return drv->orientation_angle; } diff --git a/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_fb.c b/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_fb.c index fe3ae1d17..5d33219cf 100644 --- a/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_fb.c +++ b/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_fb.c @@ -139,6 +139,14 @@ void DISPLAY_TE_INTERRUPT_HANDLER(void) { display_fb_info_t display_get_frame_buffer(void) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + display_fb_info_t fb = { + .ptr = NULL, + .stride = 0, + }; + return fb; + } + frame_buffer_state_t state; // We have to wait if the buffer was passed for copying @@ -191,6 +199,10 @@ static void wait_for_te_signal(void) { void display_refresh(void) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return; + } + if (drv->queue.entry[drv->queue.wix] != FB_STATE_PREPARING) { // No refresh needed as the frame buffer is not in // the state to be copied to the display @@ -234,6 +246,10 @@ void display_ensure_refreshed(void) { #ifndef BOARDLOADER display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return; + } + if (!is_mode_handler()) { bool copy_pending; @@ -265,6 +281,10 @@ void display_ensure_refreshed(void) { void display_fill(const gfx_bitblt_t *bb) { display_fb_info_t fb = display_get_frame_buffer(); + if (fb.ptr == NULL) { + return; + } + gfx_bitblt_t bb_new = *bb; bb_new.dst_row = (uint16_t *)((uintptr_t)fb.ptr + fb.stride * bb_new.dst_y); bb_new.dst_stride = fb.stride; @@ -275,6 +295,10 @@ void display_fill(const gfx_bitblt_t *bb) { void display_copy_rgb565(const gfx_bitblt_t *bb) { display_fb_info_t fb = display_get_frame_buffer(); + if (fb.ptr == NULL) { + return; + } + gfx_bitblt_t bb_new = *bb; bb_new.dst_row = (uint16_t *)((uintptr_t)fb.ptr + fb.stride * bb_new.dst_y); bb_new.dst_stride = fb.stride; @@ -285,6 +309,10 @@ void display_copy_rgb565(const gfx_bitblt_t *bb) { void display_copy_mono1p(const gfx_bitblt_t *bb) { display_fb_info_t fb = display_get_frame_buffer(); + if (fb.ptr == NULL) { + return; + } + gfx_bitblt_t bb_new = *bb; bb_new.dst_row = (uint16_t *)((uintptr_t)fb.ptr + fb.stride * bb_new.dst_y); bb_new.dst_stride = fb.stride; @@ -295,6 +323,10 @@ void display_copy_mono1p(const gfx_bitblt_t *bb) { void display_copy_mono4(const gfx_bitblt_t *bb) { display_fb_info_t fb = display_get_frame_buffer(); + if (fb.ptr == NULL) { + return; + } + gfx_bitblt_t bb_new = *bb; bb_new.dst_row = (uint16_t *)((uintptr_t)fb.ptr + fb.stride * bb_new.dst_y); bb_new.dst_stride = fb.stride; diff --git a/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_internal.h b/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_internal.h index 611e02e0c..bb6d7805a 100644 --- a/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_internal.h +++ b/core/embed/trezorhal/stm32f4/xdisplay/st-7789/display_internal.h @@ -41,6 +41,9 @@ typedef struct { // Display driver state typedef struct { + // Set if the driver is initialized + bool initialized; + #ifdef XFRAMEBUFFER // Framebuffer queue // (accessed & updated in the context of the main thread diff --git a/core/embed/trezorhal/stm32f4/xdisplay/stm32f429i-disc1/display_driver.c b/core/embed/trezorhal/stm32f4/xdisplay/stm32f429i-disc1/display_driver.c index 28d576336..24e13a998 100644 --- a/core/embed/trezorhal/stm32f4/xdisplay/stm32f429i-disc1/display_driver.c +++ b/core/embed/trezorhal/stm32f4/xdisplay/stm32f429i-disc1/display_driver.c @@ -33,6 +33,8 @@ // Display driver context. typedef struct { + // Set if the driver is initialized + bool initialized; // Pointer to the frame buffer uint16_t *framebuf; // Current display orientation (0, 90, 180, 270) @@ -42,10 +44,17 @@ typedef struct { } display_driver_t; // Display driver instance -static display_driver_t g_display_driver; +static display_driver_t g_display_driver = { + .initialized = false, +}; void display_init(display_content_mode_t mode) { display_driver_t *drv = &g_display_driver; + + if (drv->initialized) { + return; + } + memset(drv, 0, sizeof(display_driver_t)); drv->framebuf = (uint16_t *)FRAME_BUFFER_ADDR; @@ -55,15 +64,23 @@ void display_init(display_content_mode_t mode) { // Initialize external display controller ili9341_init(); } + + drv->initialized = true; } void display_deinit(display_content_mode_t mode) { - // Not used and intentionally left empty + display_driver_t *drv = &g_display_driver; + + drv->initialized = false; } int display_set_backlight(int level) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return 0; + } + // Just emulation, not doing anything drv->backlight_level = level; return level; @@ -72,12 +89,20 @@ int display_set_backlight(int level) { int display_get_backlight(void) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return 0; + } + return drv->backlight_level; } int display_set_orientation(int angle) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return 0; + } + if (angle == 0 || angle == 90 || angle == 180 || angle == 270) { // Just emulation, not doing anything drv->orientation_angle = angle; @@ -89,18 +114,29 @@ int display_set_orientation(int angle) { int display_get_orientation(void) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return 0; + } + return drv->orientation_angle; } display_fb_info_t display_get_frame_buffer(void) { display_driver_t *drv = &g_display_driver; - display_fb_info_t fb = { - .ptr = (void *)drv->framebuf, - .stride = DISPLAY_RESX * sizeof(uint16_t), - }; - - return fb; + if (!drv->initialized) { + display_fb_info_t fb = { + .ptr = NULL, + .stride = 0, + }; + return fb; + } else { + display_fb_info_t fb = { + .ptr = (void *)drv->framebuf, + .stride = DISPLAY_RESX * sizeof(uint16_t), + }; + return fb; + } } void display_refresh(void) { @@ -110,6 +146,10 @@ void display_refresh(void) { void display_fill(const gfx_bitblt_t *bb) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return; + } + gfx_bitblt_t bb_new = *bb; bb_new.dst_row = drv->framebuf + (DISPLAY_RESX * bb_new.dst_y); bb_new.dst_stride = DISPLAY_RESX * sizeof(uint16_t); @@ -120,6 +160,10 @@ void display_fill(const gfx_bitblt_t *bb) { void display_copy_rgb565(const gfx_bitblt_t *bb) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return; + } + gfx_bitblt_t bb_new = *bb; bb_new.dst_row = drv->framebuf + (DISPLAY_RESX * bb_new.dst_y); bb_new.dst_stride = DISPLAY_RESX * sizeof(uint16_t); @@ -130,6 +174,10 @@ void display_copy_rgb565(const gfx_bitblt_t *bb) { void display_copy_mono1p(const gfx_bitblt_t *bb) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return; + } + gfx_bitblt_t bb_new = *bb; bb_new.dst_row = drv->framebuf + (DISPLAY_RESX * bb_new.dst_y); bb_new.dst_stride = DISPLAY_RESX * sizeof(uint16_t); @@ -140,6 +188,10 @@ void display_copy_mono1p(const gfx_bitblt_t *bb) { void display_copy_mono4(const gfx_bitblt_t *bb) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return; + } + gfx_bitblt_t bb_new = *bb; bb_new.dst_row = drv->framebuf + (DISPLAY_RESX * bb_new.dst_y); bb_new.dst_stride = DISPLAY_RESX * sizeof(uint16_t); diff --git a/core/embed/trezorhal/stm32f4/xdisplay/ug-2828/display_driver.c b/core/embed/trezorhal/stm32f4/xdisplay/ug-2828/display_driver.c index b249a58fa..dfdf9041c 100644 --- a/core/embed/trezorhal/stm32f4/xdisplay/ug-2828/display_driver.c +++ b/core/embed/trezorhal/stm32f4/xdisplay/ug-2828/display_driver.c @@ -37,6 +37,8 @@ // Display driver context. typedef struct { + // Set if the driver is initialized + bool initialized; // Frame buffer (8-bit Mono) uint8_t framebuf[DISPLAY_RESX * DISPLAY_RESY]; // Current display orientation (0 or 180) @@ -46,7 +48,9 @@ typedef struct { } display_driver_t; // Display driver instance -static display_driver_t g_display_driver; +static display_driver_t g_display_driver = { + .initialized = false, +}; // Macros to access display parallel interface @@ -179,6 +183,10 @@ static void display_set_page_and_col(uint8_t page, uint8_t col) { static void display_sync_with_fb(void) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return NULL; + } + for (int y = 0; y < DISPLAY_RESY / 8; y++) { display_set_page_and_col(y, 0); uint8_t *src = &drv->framebuf[y * DISPLAY_RESX * 8]; @@ -293,6 +301,11 @@ static void display_init_interface(void) { void display_init(display_content_mode_t mode) { display_driver_t *drv = &g_display_driver; + + if (drv->initialized) { + return; + } + memset(drv, 0, sizeof(display_driver_t)); if (mode == DISPLAY_RESET_CONTENT) { @@ -301,15 +314,23 @@ void display_init(display_content_mode_t mode) { // Initialize display controller display_init_controller(); } + + drv->initialized = true; } void display_deinit(display_content_mode_t mode) { - // Not used and intentionally left empty + display_driver_t *drv = &g_display_driver; + + drv->initialized = false; } int display_set_backlight(int level) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return 0; + } + if (level != drv->backlight_level) { if (level >= 0 && level <= 255) { drv->backlight_level = level; @@ -325,12 +346,20 @@ int display_set_backlight(int level) { int display_get_backlight(void) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return 0; + } + return drv->backlight_level; } int display_set_orientation(int angle) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return 0; + } + if (angle != drv->orientation_angle) { if (angle == 0 || angle == 180) { drv->orientation_angle = angle; @@ -354,25 +383,48 @@ int display_set_orientation(int angle) { int display_get_orientation(void) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return 0; + } + return drv->orientation_angle; } display_fb_info_t display_get_frame_buffer(void) { display_driver_t *drv = &g_display_driver; - display_fb_info_t fb = { - .ptr = &drv->framebuf[0], - .stride = DISPLAY_RESX, - }; - - return fb; + if (!drv->initialized) { + const static display_fb_info_t fb = { + .ptr = NULL, + .stride = 0, + }; + return fb; + } else { + display_fb_info_t fb = { + .ptr = &drv->framebuf[0], + .stride = DISPLAY_RESX, + }; + return fb; + } } -void display_refresh(void) { display_sync_with_fb(); } +void display_refresh(void) { + display_driver_t *drv = &g_display_driver; + + if (!drv->initialized) { + return NULL; + } + + display_sync_with_fb(); +} void display_fill(const gfx_bitblt_t *bb) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return NULL; + } + gfx_bitblt_t bb_new = *bb; bb_new.dst_row = &drv->framebuf[DISPLAY_RESX * bb_new.dst_y]; bb_new.dst_stride = DISPLAY_RESX; @@ -383,6 +435,10 @@ void display_fill(const gfx_bitblt_t *bb) { void display_copy_mono1p(const gfx_bitblt_t *bb) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return NULL; + } + gfx_bitblt_t bb_new = *bb; bb_new.dst_row = &drv->framebuf[DISPLAY_RESX * bb_new.dst_y]; bb_new.dst_stride = DISPLAY_RESX; diff --git a/core/embed/trezorhal/stm32f4/xdisplay/vg-2864/display_driver.c b/core/embed/trezorhal/stm32f4/xdisplay/vg-2864/display_driver.c index d922e4462..40b99e6f7 100644 --- a/core/embed/trezorhal/stm32f4/xdisplay/vg-2864/display_driver.c +++ b/core/embed/trezorhal/stm32f4/xdisplay/vg-2864/display_driver.c @@ -42,6 +42,8 @@ // Display driver context. typedef struct { + // Set if the driver is initialized + bool initialized; // SPI driver instance SPI_HandleTypeDef spi; // Frame buffer (8-bit Mono) @@ -53,7 +55,9 @@ typedef struct { } display_driver_t; // Display driver instance -static display_driver_t g_display_driver; +static display_driver_t g_display_driver = { + .initialized = false, +}; // Display controller registers #define OLED_SETCONTRAST 0x81 @@ -223,6 +227,10 @@ static void display_sync_with_fb(display_driver_t *drv) { void display_init(display_content_mode_t mode) { display_driver_t *drv = &g_display_driver; + if (drv->initialized) { + return; + } + memset(drv, 0, sizeof(display_driver_t)); drv->backlight_level = 255; @@ -289,15 +297,23 @@ void display_init(display_content_mode_t mode) { } else { display_init_spi(drv); } + + drv->initialized = true; } void display_deinit(display_content_mode_t mode) { - // Not used and intentionally left empty + display_driver_t *drv = &g_display_driver; + + drv->initialized = false; } int display_set_backlight(int level) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return 0; + } + drv->backlight_level = 255; return drv->backlight_level; } @@ -305,12 +321,20 @@ int display_set_backlight(int level) { int display_get_backlight(void) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return 0; + } + return drv->backlight_level; } int display_set_orientation(int angle) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return 0; + } + if (angle != drv->orientation_angle) { if (angle == 0 || angle == 180) { drv->orientation_angle = angle; @@ -324,23 +348,38 @@ int display_set_orientation(int angle) { int display_get_orientation(void) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return 0; + } + return drv->orientation_angle; } display_fb_info_t display_get_frame_buffer(void) { display_driver_t *drv = &g_display_driver; - display_fb_info_t fb = { - .ptr = &drv->framebuf[0], - .stride = DISPLAY_RESX, - }; - - return fb; + if (!drv->initialized) { + static const display_fb_info_t fb = { + .ptr = NULL, + .stride = 0, + }; + return fb; + } else { + display_fb_info_t fb = { + .ptr = &drv->framebuf[0], + .stride = DISPLAY_RESX, + }; + return fb; + } } void display_refresh(void) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return; + } + #if defined USE_CONSUMPTION_MASK && !defined BOARDLOADER // This is an intentional randomization of the consumption masking algorithm // after every change on the display @@ -354,6 +393,10 @@ void display_refresh(void) { void display_fill(const gfx_bitblt_t *bb) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return; + } + gfx_bitblt_t bb_new = *bb; bb_new.dst_row = &drv->framebuf[DISPLAY_RESX * bb_new.dst_y]; bb_new.dst_stride = DISPLAY_RESX; @@ -364,6 +407,10 @@ void display_fill(const gfx_bitblt_t *bb) { void display_copy_mono1p(const gfx_bitblt_t *bb) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return; + } + gfx_bitblt_t bb_new = *bb; bb_new.dst_row = &drv->framebuf[DISPLAY_RESX * bb_new.dst_y]; bb_new.dst_stride = DISPLAY_RESX; diff --git a/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_driver.c b/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_driver.c index d60c4fd0b..f39df353c 100644 --- a/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_driver.c +++ b/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_driver.c @@ -30,18 +30,18 @@ #error "Incompatible display resolution" #endif -// Display driver context. -typedef struct { - // Current display orientation (0, 90, 180, 270) - int orientation_angle; - // Current backlight level ranging from 0 to 255 - int backlight_level; -} display_driver_t; - // Display driver instance -static display_driver_t g_display_driver; +display_driver_t g_display_driver = { + .initialized = false, +}; void display_init(display_content_mode_t mode) { + display_driver_t *drv = &g_display_driver; + + if (drv->initialized) { + return; + } + if (mode == DISPLAY_RESET_CONTENT) { RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; @@ -76,19 +76,33 @@ void display_init(display_content_mode_t mode) { BSP_LCD_SetFrameBuffer(0, GFXMMU_VIRTUAL_BUFFER0_BASE_S); } } + + drv->initialized = true; } void display_deinit(display_content_mode_t mode) { + display_driver_t *drv = &g_display_driver; + + if (!drv->initialized) { + return; + } + if (mode == DISPLAY_RESET_CONTENT) { BSP_LCD_DisplayOff(0); BSP_LCD_SetBrightness(0, 0); BSP_LCD_DeInit(0); } + + drv->initialized = false; } int display_set_backlight(int level) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return 0; + } + // Just emulation, not doing anything drv->backlight_level = level; return level; @@ -97,12 +111,20 @@ int display_set_backlight(int level) { int display_get_backlight(void) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return 0; + } + return drv->orientation_angle; } int display_set_orientation(int angle) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return 0; + } + if (angle == 0 || angle == 90 || angle == 180 || angle == 270) { // Just emulation, not doing anything drv->orientation_angle = angle; @@ -114,12 +136,20 @@ int display_set_orientation(int angle) { int display_get_orientation(void) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return 0; + } + return drv->orientation_angle; } void display_fill(const gfx_bitblt_t *bb) { display_fb_info_t fb = display_get_frame_buffer(); + if (fb.ptr == NULL) { + return; + } + gfx_bitblt_t bb_new = *bb; bb_new.dst_row = (uint8_t *)fb.ptr + (fb.stride * bb_new.dst_y); bb_new.dst_stride = fb.stride; @@ -130,6 +160,10 @@ void display_fill(const gfx_bitblt_t *bb) { void display_copy_rgb565(const gfx_bitblt_t *bb) { display_fb_info_t fb = display_get_frame_buffer(); + if (fb.ptr == NULL) { + return; + } + gfx_bitblt_t bb_new = *bb; bb_new.dst_row = (uint8_t *)fb.ptr + (fb.stride * bb_new.dst_y); bb_new.dst_stride = fb.stride; @@ -140,6 +174,10 @@ void display_copy_rgb565(const gfx_bitblt_t *bb) { void display_copy_mono1p(const gfx_bitblt_t *bb) { display_fb_info_t fb = display_get_frame_buffer(); + if (fb.ptr == NULL) { + return; + } + gfx_bitblt_t bb_new = *bb; bb_new.dst_row = (uint8_t *)fb.ptr + (fb.stride * bb_new.dst_y); bb_new.dst_stride = fb.stride; @@ -150,6 +188,10 @@ void display_copy_mono1p(const gfx_bitblt_t *bb) { void display_copy_mono4(const gfx_bitblt_t *bb) { display_fb_info_t fb = display_get_frame_buffer(); + if (fb.ptr == NULL) { + return; + } + gfx_bitblt_t bb_new = *bb; bb_new.dst_row = (uint8_t *)fb.ptr + (fb.stride * bb_new.dst_y); bb_new.dst_stride = fb.stride; diff --git a/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_fb.c b/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_fb.c index 5b425176c..598dfc464 100644 --- a/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_fb.c +++ b/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_fb.c @@ -39,6 +39,16 @@ __attribute__((section(".framebuffer_select"))) uint32_t current_frame_buffer = 0; display_fb_info_t display_get_frame_buffer(void) { + display_driver_t *drv = &g_display_driver; + + if (!drv->initialized) { + display_fb_info_t fb = { + .ptr = NULL, + .stride = 0, + }; + return fb; + } + uintptr_t addr; if (current_frame_buffer == 0) { @@ -63,6 +73,12 @@ display_fb_info_t display_get_frame_buffer(void) { } void display_refresh(void) { + display_driver_t *drv = &g_display_driver; + + if (!drv->initialized) { + return; + } + if (current_frame_buffer == 0) { current_frame_buffer = 1; BSP_LCD_SetFrameBuffer(0, GFXMMU_VIRTUAL_BUFFER1_BASE_S); diff --git a/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_internal.h b/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_internal.h index 4ebe2cea2..bb7d5582a 100644 --- a/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_internal.h +++ b/core/embed/trezorhal/stm32u5/xdisplay/stm32u5a9j-dk/display_internal.h @@ -20,8 +20,22 @@ #ifndef TREZOR_HAL_DISPLAY_INTERNAL_H #define TREZOR_HAL_DISPLAY_INTERNAL_H +#include #include +// Display driver context. +typedef struct { + // Set if the driver is initialized + bool initialized; + // Current display orientation (0, 90, 180, 270) + int orientation_angle; + // Current backlight level ranging from 0 to 255 + int backlight_level; +} display_driver_t; + +// Display driver instance +extern display_driver_t g_display_driver; + // Size of the physical frame buffer in bytes // // It's smaller than size of the virtual frame buffer diff --git a/core/embed/trezorhal/unix/display_driver.c b/core/embed/trezorhal/unix/display_driver.c index bcaada40f..5cb7b2314 100644 --- a/core/embed/trezorhal/unix/display_driver.c +++ b/core/embed/trezorhal/unix/display_driver.c @@ -32,6 +32,8 @@ #define EMULATOR_BORDER 16 typedef struct { + // Set if the driver is initialized + bool initialized; // Current display orientation (0 or 180) int orientation_angle; // Current backlight level ranging from 0 to 255 @@ -52,7 +54,9 @@ typedef struct { } display_driver_t; -static display_driver_t g_display_driver; +static display_driver_t g_display_driver = { + .initialized = false, +}; //!@# TODO get rid of this... int sdl_display_res_x = DISPLAY_RESX, sdl_display_res_y = DISPLAY_RESY; @@ -65,6 +69,10 @@ static void display_exit_handler(void) { void display_init(display_content_mode_t mode) { display_driver_t *drv = &g_display_driver; + if (drv->initialized) { + return; + } + if (SDL_Init(SDL_INIT_VIDEO) != 0) { printf("%s\n", SDL_GetError()); error_shutdown("SDL_Init error"); @@ -144,11 +152,16 @@ void display_init(display_content_mode_t mode) { #else drv->orientation_angle = 0; #endif + drv->initialized = true; } void display_deinit(display_content_mode_t mode) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return; + } + SDL_FreeSurface(drv->prev_saved); SDL_FreeSurface(drv->buffer); if (drv->background != NULL) { @@ -164,11 +177,17 @@ void display_deinit(display_content_mode_t mode) { SDL_DestroyWindow(drv->window); } SDL_Quit(); + + drv->initialized = false; } int display_set_backlight(int level) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return 0; + } + #if !USE_BACKLIGHT level = 255; #endif @@ -183,11 +202,21 @@ int display_set_backlight(int level) { int display_get_backlight(void) { display_driver_t *drv = &g_display_driver; + + if (!drv->initialized) { + return 0; + } + return drv->backlight_level; } int display_set_orientation(int angle) { display_driver_t *drv = &g_display_driver; + + if (!drv->initialized) { + return 0; + } + if (angle != drv->orientation_angle) { #if defined ORIENTATION_NSEW if (angle == 0 || angle == 90 || angle == 180 || angle == 270) { @@ -205,6 +234,11 @@ int display_set_orientation(int angle) { int display_get_orientation(void) { display_driver_t *drv = &g_display_driver; + + if (!drv->initialized) { + return 0; + } + return drv->orientation_angle; } @@ -212,25 +246,32 @@ int display_get_orientation(void) { display_fb_info_t display_get_frame_buffer(void) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + display_fb_info_t fb = { + .ptr = NULL, + .stride = 0, + }; + return fb; + } else { #ifdef DISPLAY_MONO - display_fb_info_t fb = { - .ptr = drv->mono_framebuf, - .stride = DISPLAY_RESX, - }; + display_fb_info_t fb = { + .ptr = drv->mono_framebuf, + .stride = DISPLAY_RESX, + }; #else - display_fb_info_t fb = { - .ptr = drv->buffer->pixels, - .stride = DISPLAY_RESX * sizeof(uint16_t), - }; + display_fb_info_t fb = { + .ptr = drv->buffer->pixels, + .stride = DISPLAY_RESX * sizeof(uint16_t), + }; #endif - - return fb; + return fb; + } } #else // XFRAMEBUFFER void display_wait_for_sync(void) { - // not used + // not implemented in the emulator } #endif @@ -253,7 +294,7 @@ static void copy_mono_framebuf(display_driver_t *drv) { void display_refresh(void) { display_driver_t *drv = &g_display_driver; - if (!drv->renderer) { + if (!drv->initialized) { return; } @@ -292,6 +333,10 @@ void display_refresh(void) { void display_fill(const gfx_bitblt_t *bb) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return; + } + gfx_bitblt_t bb_new = *bb; bb_new.dst_row = (uint8_t *)drv->buffer->pixels + (drv->buffer->pitch * bb_new.dst_y); @@ -303,6 +348,10 @@ void display_fill(const gfx_bitblt_t *bb) { void display_copy_rgb565(const gfx_bitblt_t *bb) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return; + } + gfx_bitblt_t bb_new = *bb; bb_new.dst_row = (uint8_t *)drv->buffer->pixels + (drv->buffer->pitch * bb_new.dst_y); @@ -314,6 +363,10 @@ void display_copy_rgb565(const gfx_bitblt_t *bb) { void display_copy_mono1p(const gfx_bitblt_t *bb) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return; + } + gfx_bitblt_t bb_new = *bb; bb_new.dst_row = (uint8_t *)drv->buffer->pixels + (drv->buffer->pitch * bb_new.dst_y); @@ -325,6 +378,10 @@ void display_copy_mono1p(const gfx_bitblt_t *bb) { void display_copy_mono4(const gfx_bitblt_t *bb) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return; + } + gfx_bitblt_t bb_new = *bb; bb_new.dst_row = (uint8_t *)drv->buffer->pixels + (drv->buffer->pitch * bb_new.dst_y); @@ -338,6 +395,10 @@ void display_copy_mono4(const gfx_bitblt_t *bb) { void display_fill(const gfx_bitblt_t *bb) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return; + } + gfx_bitblt_t bb_new = *bb; bb_new.dst_row = drv->mono_framebuf + (DISPLAY_RESX * bb_new.dst_y); bb_new.dst_stride = DISPLAY_RESX; @@ -348,6 +409,10 @@ void display_fill(const gfx_bitblt_t *bb) { void display_copy_mono1p(const gfx_bitblt_t *bb) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return; + } + gfx_bitblt_t bb_new = *bb; bb_new.dst_row = drv->mono_framebuf + (DISPLAY_RESX * bb_new.dst_y); bb_new.dst_stride = DISPLAY_RESX; @@ -360,7 +425,7 @@ void display_copy_mono1p(const gfx_bitblt_t *bb) { const char *display_save(const char *prefix) { display_driver_t *drv = &g_display_driver; - if (!drv->renderer) { + if (!drv->initialized) { return NULL; } @@ -396,6 +461,10 @@ const char *display_save(const char *prefix) { void display_clear_save(void) { display_driver_t *drv = &g_display_driver; + if (!drv->initialized) { + return; + } + SDL_FreeSurface(drv->prev_saved); drv->prev_saved = NULL; }