From caacadc3d03a13dd4dfe1eefb2626faa2d3bbbe3 Mon Sep 17 00:00:00 2001 From: tychovrahe <brunam@seznam.cz> Date: Wed, 12 Mar 2025 02:26:28 +0100 Subject: [PATCH] button hibernation prodtest --- .../projects/prodtest/cmd/prodtest_rgbled.c | 24 +++ .../projects/prodtest/cmd/prodtest_rgbled.h | 24 +++ core/embed/projects/prodtest/main.c | 39 ++++- core/embed/rtl/cli.c | 137 +++++++++--------- core/embed/rtl/inc/rtl/cli.h | 7 +- 5 files changed, 160 insertions(+), 71 deletions(-) create mode 100644 core/embed/projects/prodtest/cmd/prodtest_rgbled.h diff --git a/core/embed/projects/prodtest/cmd/prodtest_rgbled.c b/core/embed/projects/prodtest/cmd/prodtest_rgbled.c index 56ac01ef66..e14ee341e0 100644 --- a/core/embed/projects/prodtest/cmd/prodtest_rgbled.c +++ b/core/embed/projects/prodtest/cmd/prodtest_rgbled.c @@ -23,6 +23,29 @@ #include <io/rgb_led.h> #include <rtl/cli.h> +#include <sys/systimer.h> + +static bool g_prodtest_rgbled_start = false; + +static void prodtest_rgbled_timer_cb(void* context) { + if (g_prodtest_rgbled_start) { + rgb_led_set_color(0); + g_prodtest_rgbled_start = false; + } +} + +void prodtest_rgbled_init(void) { + static systimer_t* timer = NULL; + + timer = systimer_create(prodtest_rgbled_timer_cb, NULL); + + if (timer == NULL) { + return; + } + systimer_set(timer, 1000); + rgb_led_set_color(0xFF00); + g_prodtest_rgbled_start = true; +} static void prodtest_rgbled_set(cli_t* cli) { uint32_t r = 0; @@ -53,6 +76,7 @@ static void prodtest_rgbled_set(cli_t* cli) { uint32_t rgb = (r << 16) | (g << 8) | b; + g_prodtest_rgbled_start = false; rgb_led_set_color(rgb); cli_ok(cli, ""); diff --git a/core/embed/projects/prodtest/cmd/prodtest_rgbled.h b/core/embed/projects/prodtest/cmd/prodtest_rgbled.h new file mode 100644 index 0000000000..5992f9cfb3 --- /dev/null +++ b/core/embed/projects/prodtest/cmd/prodtest_rgbled.h @@ -0,0 +1,24 @@ +/* + * 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 <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include <trezor_types.h> + +void prodtest_rgbled_init(void); diff --git a/core/embed/projects/prodtest/main.c b/core/embed/projects/prodtest/main.c index 7e4abee60a..526f01d24c 100644 --- a/core/embed/projects/prodtest/main.c +++ b/core/embed/projects/prodtest/main.c @@ -24,6 +24,7 @@ #include <io/usb.h> #include <rtl/cli.h> #include <sys/system.h> +#include <sys/systick.h> #include <util/flash_otp.h> #include <util/rsod.h> #include <util/unit_properties.h> @@ -66,6 +67,7 @@ #ifdef USE_RGB_LED #include <io/rgb_led.h> +#include "cmd/prodtest_rgbled.h" #endif #ifdef USE_HASH_PROCESSOR @@ -105,6 +107,10 @@ cli_t g_cli = {0}; #define VCP_IFACE 0 +static bool console_can_read(void *context) { + return usb_vcp_can_read(VCP_IFACE); +} + static size_t console_read(void *context, char *buf, size_t size) { return usb_vcp_read_blocking(VCP_IFACE, (uint8_t *)buf, size, -1); } @@ -208,6 +214,7 @@ static void drivers_init(void) { #endif #ifdef USE_RGB_LED rgb_led_init(); + prodtest_rgbled_init(); #endif #ifdef USE_BLE unit_properties_init(); @@ -232,7 +239,7 @@ int main(void) { show_welcome_screen(); // Initialize command line interface - cli_init(&g_cli, console_read, console_write, NULL); + cli_init(&g_cli, console_can_read, console_read, console_write, NULL); extern cli_command_t _prodtest_cli_cmd_section_start; extern cli_command_t _prodtest_cli_cmd_section_end; @@ -247,7 +254,35 @@ int main(void) { pair_optiga(&g_cli); #endif - cli_run_loop(&g_cli); + while (true) { + cli_run_loop(&g_cli); + + button_event_t btn_event = {0}; + + bool btn = button_get_event(&btn_event); + + if (btn) { + bool hibernate = true; + uint32_t deadline = ticks_timeout(1000); + while (!ticks_expired(deadline)) { + button_get_event(&btn_event); + if (!button_is_down(BTN_POWER)) { + hibernate = false; + break; + } + } + + if (hibernate) { + // todo only + rgb_led_set_color(0xff0000); + systick_delay_ms(1000); + powerctl_hibernate(); + rgb_led_set_color(0xffff00); + systick_delay_ms(1000); + rgb_led_set_color(0); + } + } + } return 0; } diff --git a/core/embed/rtl/cli.c b/core/embed/rtl/cli.c index f513fd5011..900b38259b 100644 --- a/core/embed/rtl/cli.c +++ b/core/embed/rtl/cli.c @@ -11,9 +11,10 @@ #define ESC_COLOR_GRAY "\e[37m" #define ESC_COLOR_RESET "\e[39m" -bool cli_init(cli_t* cli, cli_read_cb_t read, cli_write_cb_t write, - void* callback_context) { +bool cli_init(cli_t* cli, cli_can_read_cb_t can_read, cli_read_cb_t read, + cli_write_cb_t write, void* callback_context) { memset(cli, 0, sizeof(cli_t)); + cli->can_read = can_read; cli->read = read; cli->write = write; cli->callback_context = callback_context; @@ -527,77 +528,79 @@ static bool cli_split_args(cli_t* cli) { } void cli_run_loop(cli_t* cli) { - while (true) { + if (!cli->can_read(cli->callback_context)) { + return; + } + + if (cli->interactive) { + if (cli->final_status) { + // Finalize the last command with an empty line + cli_printf(cli, "\r\n"); + } + // Print the prompt + cli_printf(cli, "> "); + } + + cli->final_status = false; + cli->aborted = false; + + // Read the next line + if (!cli_readln(cli)) { + cli_error(cli, CLI_ERROR_FATAL, "Input line too long."); + return; + } + + cli_history_add(cli, cli->line_buffer); + + // Split command line into arguments + if (!cli_split_args(cli)) { + cli_error(cli, CLI_ERROR_FATAL, "Too many arguments."); + return; + } + + // Empty line? + if (*cli->cmd_name == '\0') { + // Switch to interactive mode if two empty lines are entered + if (++cli->empty_lines >= 2 && !cli->interactive) { + cli->interactive = true; + // Print the welcome message + const cli_command_t* cmd = cli_find_command(cli, "$intro"); + if (cmd != NULL) { + cmd->func(cli); + } + } + return; + } + cli->empty_lines = 0; + + // Quit interactive mode on `.+ENTER` + if ((strcmp(cli->cmd_name, ".") == 0)) { if (cli->interactive) { - if (cli->final_status) { - // Finalize the last command with an empty line - cli_printf(cli, "\r\n"); - } - // Print the prompt - cli_printf(cli, "> "); + cli->interactive = false; + cli_trace(cli, "Exiting interactive mode..."); } + return; + } - cli->final_status = false; - cli->aborted = false; + // Find the command handler + cli->current_cmd = cli_find_command(cli, cli->cmd_name); - // Read the next line - if (!cli_readln(cli)) { - cli_error(cli, CLI_ERROR_FATAL, "Input line too long."); - continue; - } + if (cli->current_cmd == NULL) { + cli_error(cli, CLI_ERROR_INVALID_CMD, "Invalid command '%s', try 'help'.", + cli->cmd_name); + return; + } - cli_history_add(cli, cli->line_buffer); + // Call the command handler + cli->current_cmd->func(cli); - // Split command line into arguments - if (!cli_split_args(cli)) { - cli_error(cli, CLI_ERROR_FATAL, "Too many arguments."); - continue; - } - - // Empty line? - if (*cli->cmd_name == '\0') { - // Switch to interactive mode if two empty lines are entered - if (++cli->empty_lines >= 2 && !cli->interactive) { - cli->interactive = true; - // Print the welcome message - const cli_command_t* cmd = cli_find_command(cli, "$intro"); - if (cmd != NULL) { - cmd->func(cli); - } - } - continue; - } - cli->empty_lines = 0; - - // Quit interactive mode on `.+ENTER` - if ((strcmp(cli->cmd_name, ".") == 0)) { - if (cli->interactive) { - cli->interactive = false; - cli_trace(cli, "Exiting interactive mode..."); - } - continue; - } - - // Find the command handler - cli->current_cmd = cli_find_command(cli, cli->cmd_name); - - if (cli->current_cmd == NULL) { - cli_error(cli, CLI_ERROR_INVALID_CMD, "Invalid command '%s', try 'help'.", - cli->cmd_name); - continue; - } - - // Call the command handler - cli->current_cmd->func(cli); - - if (!cli->final_status) { - // Command handler hasn't send final status - if (cli->aborted) { - cli_error(cli, CLI_ERROR_ABORT, ""); - } else { - cli_error(cli, CLI_ERROR_FATAL, - "Command handler didn't finish properly."); - } + if (!cli->final_status) { + // Command handler hasn't send final status + if (cli->aborted) { + cli_error(cli, CLI_ERROR_ABORT, ""); + } else { + cli_error(cli, CLI_ERROR_FATAL, + "Command handler didn't finish properly."); } } } diff --git a/core/embed/rtl/inc/rtl/cli.h b/core/embed/rtl/inc/rtl/cli.h index af0f420bc0..abd12e594a 100644 --- a/core/embed/rtl/inc/rtl/cli.h +++ b/core/embed/rtl/inc/rtl/cli.h @@ -77,9 +77,12 @@ typedef struct { typedef size_t (*cli_write_cb_t)(void* ctx, const char* buf, size_t len); // Callback for reading characters from console input typedef size_t (*cli_read_cb_t)(void* ctx, char* buf, size_t len); +// Callback for can read assessment +typedef bool (*cli_can_read_cb_t)(void* ctx); struct cli { // I/O callbacks + cli_can_read_cb_t can_read; cli_read_cb_t read; cli_write_cb_t write; void* callback_context; @@ -116,8 +119,8 @@ struct cli { }; // Initializes the command line structure -bool cli_init(cli_t* cli, cli_read_cb_t read, cli_write_cb_t write, - void* callback_context); +bool cli_init(cli_t* cli, cli_can_read_cb_t can_read, cli_read_cb_t read, + cli_write_cb_t write, void* callback_context); // Registers the command handlers void cli_set_commands(cli_t* cli, const cli_command_t* cmd_array,