From 104a1998a5e2f77cea99c31311541864fb98d4c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=82=E3=81=8F?= Date: Tue, 1 Nov 2022 19:27:25 +0900 Subject: [PATCH 01/23] Furi: raise bkpt only if debug session initiated, add debug support for release builds (#1957) * Fix hard crash on some custom firmwares in RELEASE mode * Furi: anya wa erai, anya wa eleganto, raise bkpt only if debug session initiated, add debug support for release builds Co-authored-by: DerSkythe --- furi/core/check.c | 59 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 18 deletions(-) diff --git a/furi/core/check.c b/furi/core/check.c index 00c20575a..1c2a005f3 100644 --- a/furi/core/check.c +++ b/furi/core/check.c @@ -1,6 +1,7 @@ #include "check.h" #include "common_defines.h" +#include #include #include #include @@ -24,16 +25,30 @@ PLACE_IN_SECTION("MB_MEM2") uint32_t __furi_check_registers[12] = {0}; : \ : "memory"); -// Restore registers and halt MCU -#define RESTORE_REGISTERS_AND_HALT_MCU() \ - asm volatile("ldr r12, =__furi_check_registers \n" \ - "ldm r12, {r0-r11} \n" \ +/** Restore registers and halt MCU + * + * - Always use it with GET_MESSAGE_AND_STORE_REGISTERS + * - If debugger is(was) connected this routine will raise bkpt + * - If debugger is not connected then endless loop + * + */ +#define RESTORE_REGISTERS_AND_HALT_MCU(debug) \ + register const bool r0 asm("r0") = debug; \ + asm volatile("cbnz r0, with_debugger%= \n" \ + "ldr r12, =__furi_check_registers\n" \ + "ldm r12, {r0-r11} \n" \ "loop%=: \n" \ - "bkpt 0x00 \n" \ "wfi \n" \ - "b loop%= \n" \ - : \ + "b loop%= \n" \ + "with_debugger%=: \n" \ + "ldr r12, =__furi_check_registers\n" \ + "ldm r12, {r0-r11} \n" \ + "debug_loop%=: \n" \ + "bkpt 0x00 \n" \ + "wfi \n" \ + "b debug_loop%= \n" \ : \ + : "r"(r0) \ : "memory"); extern size_t xPortGetTotalHeapSize(void); @@ -96,16 +111,19 @@ FURI_NORETURN void __furi_crash() { } __furi_print_heap_info(); -#ifdef FURI_DEBUG - furi_hal_console_puts("\r\nSystem halted. Connect debugger for more info\r\n"); - furi_hal_console_puts("\033[0m\r\n"); - RESTORE_REGISTERS_AND_HALT_MCU(); -#else - furi_hal_rtc_set_fault_data((uint32_t)__furi_check_message); - furi_hal_console_puts("\r\nRebooting system.\r\n"); - furi_hal_console_puts("\033[0m\r\n"); - furi_hal_power_reset(); -#endif + // Check if debug enabled by DAP + // https://developer.arm.com/documentation/ddi0403/d/Debug-Architecture/ARMv7-M-Debug/Debug-register-support-in-the-SCS/Debug-Halting-Control-and-Status-Register--DHCSR?lang=en + bool debug = CoreDebug->DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk; + if(debug) { + furi_hal_console_puts("\r\nSystem halted. Connect debugger for more info\r\n"); + furi_hal_console_puts("\033[0m\r\n"); + RESTORE_REGISTERS_AND_HALT_MCU(debug); + } else { + furi_hal_rtc_set_fault_data((uint32_t)__furi_check_message); + furi_hal_console_puts("\r\nRebooting system.\r\n"); + furi_hal_console_puts("\033[0m\r\n"); + furi_hal_power_reset(); + } __builtin_unreachable(); } @@ -124,6 +142,11 @@ FURI_NORETURN void __furi_halt() { furi_hal_console_puts(__furi_check_message); furi_hal_console_puts("\r\nSystem halted. Bye-bye!\r\n"); furi_hal_console_puts("\033[0m\r\n"); - RESTORE_REGISTERS_AND_HALT_MCU(); + + // Check if debug enabled by DAP + // https://developer.arm.com/documentation/ddi0403/d/Debug-Architecture/ARMv7-M-Debug/Debug-register-support-in-the-SCS/Debug-Halting-Control-and-Status-Register--DHCSR?lang=en + bool debug = CoreDebug->DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk; + RESTORE_REGISTERS_AND_HALT_MCU(debug); + __builtin_unreachable(); } From 165d9972e7721965fdf7b59c2bcf994a4b64b26b Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Wed, 2 Nov 2022 01:05:05 +0300 Subject: [PATCH 02/23] SubGHz Fixes: BFT fix, other small fixes --- .../subghz/scenes/subghz_scene_set_seed_bft.c | 2 + lib/subghz/protocols/faac_slh.c | 10 +-- lib/subghz/protocols/keeloq.c | 66 ++++++++++++------- lib/subghz/protocols/nice_flor_s.c | 4 +- 4 files changed, 53 insertions(+), 29 deletions(-) diff --git a/applications/main/subghz/scenes/subghz_scene_set_seed_bft.c b/applications/main/subghz/scenes/subghz_scene_set_seed_bft.c index dcb7e6850..1d6f9d70b 100644 --- a/applications/main/subghz/scenes/subghz_scene_set_seed_bft.c +++ b/applications/main/subghz/scenes/subghz_scene_set_seed_bft.c @@ -67,6 +67,8 @@ bool subghz_scene_set_seed_bft_on_event(void* context, SceneManagerEvent event) flipper_format_write_hex( subghz->txrx->fff_data, "Seed", seed_data, sizeof(uint32_t)); + flipper_format_write_string_cstr(subghz->txrx->fff_data, "Manufacture", "BFT"); + generated_protocol = true; } else { generated_protocol = false; diff --git a/lib/subghz/protocols/faac_slh.c b/lib/subghz/protocols/faac_slh.c index 0533172c3..7572bd8ab 100644 --- a/lib/subghz/protocols/faac_slh.c +++ b/lib/subghz/protocols/faac_slh.c @@ -462,10 +462,7 @@ bool subghz_protocol_decoder_faac_slh_deserialize(void* context, FlipperFormat* FURI_LOG_E(TAG, "Wrong number of bits in key"); break; } - if(!flipper_format_rewind(flipper_format)) { - FURI_LOG_E(TAG, "Rewind error"); - break; - } + uint8_t seed_data[sizeof(uint32_t)] = {0}; for(size_t i = 0; i < sizeof(uint32_t); i++) { seed_data[sizeof(uint32_t) - i - 1] = (instance->generic.seed >> i * 8) & 0xFF; @@ -476,6 +473,11 @@ bool subghz_protocol_decoder_faac_slh_deserialize(void* context, FlipperFormat* } instance->generic.seed = seed_data[0] << 24 | seed_data[1] << 16 | seed_data[2] << 8 | seed_data[3]; + + if(!flipper_format_rewind(flipper_format)) { + FURI_LOG_E(TAG, "Rewind error"); + break; + } res = true; } while(false); diff --git a/lib/subghz/protocols/keeloq.c b/lib/subghz/protocols/keeloq.c index 6887218d7..10993d706 100644 --- a/lib/subghz/protocols/keeloq.c +++ b/lib/subghz/protocols/keeloq.c @@ -371,15 +371,6 @@ bool subghz_protocol_encoder_keeloq_deserialize(void* context, FlipperFormat* fl break; } - // Read manufacturer from file - if(flipper_format_read_string( - flipper_format, "Manufacture", instance->manufacture_from_file)) { - instance->manufacture_name = furi_string_get_cstr(instance->manufacture_from_file); - mfname = furi_string_get_cstr(instance->manufacture_from_file); - } else { - FURI_LOG_D(TAG, "ENCODER: Missing Manufacture"); - } - uint8_t seed_data[sizeof(uint32_t)] = {0}; for(size_t i = 0; i < sizeof(uint32_t); i++) { seed_data[sizeof(uint32_t) - i - 1] = (instance->generic.seed >> i * 8) & 0xFF; @@ -390,6 +381,20 @@ bool subghz_protocol_encoder_keeloq_deserialize(void* context, FlipperFormat* fl instance->generic.seed = seed_data[0] << 24 | seed_data[1] << 16 | seed_data[2] << 8 | seed_data[3]; + // Read manufacturer from file + if(flipper_format_read_string( + flipper_format, "Manufacture", instance->manufacture_from_file)) { + instance->manufacture_name = furi_string_get_cstr(instance->manufacture_from_file); + mfname = furi_string_get_cstr(instance->manufacture_from_file); + } else { + FURI_LOG_D(TAG, "ENCODER: Missing Manufacture"); + } + + if(!flipper_format_rewind(flipper_format)) { + FURI_LOG_E(TAG, "Rewind error"); + break; + } + subghz_protocol_keeloq_check_remote_controller( &instance->generic, instance->keystore, &instance->manufacture_name); @@ -979,9 +984,22 @@ bool subghz_protocol_decoder_keeloq_serialize( subghz_protocol_keeloq_check_remote_controller( &instance->generic, instance->keystore, &instance->manufacture_name); + if(strcmp(instance->manufacture_name, "BFT") == 0) { + uint8_t seed_data[sizeof(uint32_t)] = {0}; + for(size_t i = 0; i < sizeof(uint32_t); i++) { + seed_data[sizeof(uint32_t) - i - 1] = (instance->generic.seed >> i * 8) & 0xFF; + } + if(res && !flipper_format_write_hex(flipper_format, "Seed", seed_data, sizeof(uint32_t))) { + FURI_LOG_E(TAG, "DECODER Serialize: Unable to add Seed"); + res = false; + } + instance->generic.seed = seed_data[0] << 24 | seed_data[1] << 16 | seed_data[2] << 8 | + seed_data[3]; + } + if(res && !flipper_format_write_string_cstr( flipper_format, "Manufacture", instance->manufacture_name)) { - FURI_LOG_E(TAG, "Unable to add manufacture name"); + FURI_LOG_E(TAG, "DECODER Serialize: Unable to add manufacture name"); res = false; } return res; @@ -1001,19 +1019,6 @@ bool subghz_protocol_decoder_keeloq_deserialize(void* context, FlipperFormat* fl FURI_LOG_E(TAG, "Wrong number of bits in key"); break; } - if(!flipper_format_rewind(flipper_format)) { - FURI_LOG_E(TAG, "Rewind error"); - break; - } - - // Read manufacturer from file - if(flipper_format_read_string( - flipper_format, "Manufacture", instance->manufacture_from_file)) { - instance->manufacture_name = furi_string_get_cstr(instance->manufacture_from_file); - mfname = furi_string_get_cstr(instance->manufacture_from_file); - } else { - FURI_LOG_D(TAG, "DECODER: Missing Manufacture"); - } uint8_t seed_data[sizeof(uint32_t)] = {0}; for(size_t i = 0; i < sizeof(uint32_t); i++) { @@ -1024,6 +1029,21 @@ bool subghz_protocol_decoder_keeloq_deserialize(void* context, FlipperFormat* fl } instance->generic.seed = seed_data[0] << 24 | seed_data[1] << 16 | seed_data[2] << 8 | seed_data[3]; + + // Read manufacturer from file + if(flipper_format_read_string( + flipper_format, "Manufacture", instance->manufacture_from_file)) { + instance->manufacture_name = furi_string_get_cstr(instance->manufacture_from_file); + mfname = furi_string_get_cstr(instance->manufacture_from_file); + } else { + FURI_LOG_D(TAG, "DECODER: Missing Manufacture"); + } + + if(!flipper_format_rewind(flipper_format)) { + FURI_LOG_E(TAG, "Rewind error"); + break; + } + res = true; } while(false); diff --git a/lib/subghz/protocols/nice_flor_s.c b/lib/subghz/protocols/nice_flor_s.c index c6bb8e040..bcc5c7466 100644 --- a/lib/subghz/protocols/nice_flor_s.c +++ b/lib/subghz/protocols/nice_flor_s.c @@ -92,7 +92,7 @@ void* subghz_protocol_encoder_nice_flor_s_alloc(SubGhzEnvironment* environment) instance->nice_flor_s_rainbow_table_file_name = subghz_environment_get_nice_flor_s_rainbow_table_file_name(environment); if(instance->nice_flor_s_rainbow_table_file_name) { - FURI_LOG_I( + FURI_LOG_D( TAG, "Loading rainbow table from %s", instance->nice_flor_s_rainbow_table_file_name); } instance->encoder.repeat = 10; @@ -343,7 +343,7 @@ void* subghz_protocol_decoder_nice_flor_s_alloc(SubGhzEnvironment* environment) instance->nice_flor_s_rainbow_table_file_name = subghz_environment_get_nice_flor_s_rainbow_table_file_name(environment); if(instance->nice_flor_s_rainbow_table_file_name) { - FURI_LOG_I( + FURI_LOG_D( TAG, "Loading rainbow table from %s", instance->nice_flor_s_rainbow_table_file_name); } return instance; From 46bffba498582124c3770a4f8dc69dc886f03e79 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Wed, 2 Nov 2022 01:08:54 +0300 Subject: [PATCH 03/23] replace furi check hotfix with ofw proper fix --- furi/core/check.c | 72 +++++++++++++++++++++++++++-------------------- 1 file changed, 41 insertions(+), 31 deletions(-) diff --git a/furi/core/check.c b/furi/core/check.c index cf1b790e8..1c2a005f3 100644 --- a/furi/core/check.c +++ b/furi/core/check.c @@ -1,6 +1,7 @@ #include "check.h" #include "common_defines.h" +#include #include #include #include @@ -24,30 +25,31 @@ PLACE_IN_SECTION("MB_MEM2") uint32_t __furi_check_registers[12] = {0}; : \ : "memory"); -#ifdef FURI_DEBUG -// Restore registers and halt MCU with bkpt mcu debug state -#define RESTORE_REGISTERS_AND_HALT_MCU() \ - asm volatile("ldr r12, =__furi_check_registers \n" \ - "ldm r12, {r0-r11} \n" \ - "loop%=: \n" \ - "bkpt 0x00 \n" \ - "wfi \n" \ - "b loop%= \n" \ - : \ - : \ - : "memory"); -#else -// Restore registers and halt MCU for release builds without bkpt instruction -#define RESTORE_REGISTERS_AND_HALT_MCU() \ - asm volatile("ldr r12, =__furi_check_registers \n" \ - "ldm r12, {r0-r11} \n" \ +/** Restore registers and halt MCU + * + * - Always use it with GET_MESSAGE_AND_STORE_REGISTERS + * - If debugger is(was) connected this routine will raise bkpt + * - If debugger is not connected then endless loop + * + */ +#define RESTORE_REGISTERS_AND_HALT_MCU(debug) \ + register const bool r0 asm("r0") = debug; \ + asm volatile("cbnz r0, with_debugger%= \n" \ + "ldr r12, =__furi_check_registers\n" \ + "ldm r12, {r0-r11} \n" \ "loop%=: \n" \ "wfi \n" \ - "b loop%= \n" \ - : \ + "b loop%= \n" \ + "with_debugger%=: \n" \ + "ldr r12, =__furi_check_registers\n" \ + "ldm r12, {r0-r11} \n" \ + "debug_loop%=: \n" \ + "bkpt 0x00 \n" \ + "wfi \n" \ + "b debug_loop%= \n" \ : \ + : "r"(r0) \ : "memory"); -#endif extern size_t xPortGetTotalHeapSize(void); extern size_t xPortGetFreeHeapSize(void); @@ -109,16 +111,19 @@ FURI_NORETURN void __furi_crash() { } __furi_print_heap_info(); -#ifdef FURI_DEBUG - furi_hal_console_puts("\r\nSystem halted. Connect debugger for more info\r\n"); - furi_hal_console_puts("\033[0m\r\n"); - RESTORE_REGISTERS_AND_HALT_MCU(); -#else - furi_hal_rtc_set_fault_data((uint32_t)__furi_check_message); - furi_hal_console_puts("\r\nRebooting system.\r\n"); - furi_hal_console_puts("\033[0m\r\n"); - furi_hal_power_reset(); -#endif + // Check if debug enabled by DAP + // https://developer.arm.com/documentation/ddi0403/d/Debug-Architecture/ARMv7-M-Debug/Debug-register-support-in-the-SCS/Debug-Halting-Control-and-Status-Register--DHCSR?lang=en + bool debug = CoreDebug->DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk; + if(debug) { + furi_hal_console_puts("\r\nSystem halted. Connect debugger for more info\r\n"); + furi_hal_console_puts("\033[0m\r\n"); + RESTORE_REGISTERS_AND_HALT_MCU(debug); + } else { + furi_hal_rtc_set_fault_data((uint32_t)__furi_check_message); + furi_hal_console_puts("\r\nRebooting system.\r\n"); + furi_hal_console_puts("\033[0m\r\n"); + furi_hal_power_reset(); + } __builtin_unreachable(); } @@ -137,6 +142,11 @@ FURI_NORETURN void __furi_halt() { furi_hal_console_puts(__furi_check_message); furi_hal_console_puts("\r\nSystem halted. Bye-bye!\r\n"); furi_hal_console_puts("\033[0m\r\n"); - RESTORE_REGISTERS_AND_HALT_MCU(); + + // Check if debug enabled by DAP + // https://developer.arm.com/documentation/ddi0403/d/Debug-Architecture/ARMv7-M-Debug/Debug-register-support-in-the-SCS/Debug-Halting-Control-and-Status-Register--DHCSR?lang=en + bool debug = CoreDebug->DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk; + RESTORE_REGISTERS_AND_HALT_MCU(debug); + __builtin_unreachable(); } From 92b8a256e4cdeddff34e0eef5e6f868db024b6cd Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Wed, 2 Nov 2022 01:29:01 +0300 Subject: [PATCH 04/23] Snake game: Fix food spawn bug --- applications/plugins/snake_game/snake_game.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/applications/plugins/snake_game/snake_game.c b/applications/plugins/snake_game/snake_game.c index 2867134bc..2713cd0b1 100644 --- a/applications/plugins/snake_game/snake_game.c +++ b/applications/plugins/snake_game/snake_game.c @@ -196,8 +196,8 @@ static Point snake_game_get_new_fruit(SnakeState const* const snake_state) { if((buffer[y] & mask) == 0) { if(newFruit == 0) { Point p = { - .x = x, - .y = y, + .x = x * 2, + .y = y * 2, }; return p; } From 0f1e03fa512312b0f6ac554a0ccbe8403be77ffa Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Wed, 2 Nov 2022 03:42:38 +0300 Subject: [PATCH 05/23] Fix: proper deinit of gpio and spi bus in NRF24 driver --- applications/plugins/mousejacker/mousejacker.c | 2 +- applications/plugins/nrfsniff/nrfsniff.c | 2 +- firmware/targets/f7/api_symbols.csv | 3 ++- lib/drivers/nrf24.c | 7 +++++++ lib/drivers/nrf24.h | 5 +++++ 5 files changed, 16 insertions(+), 3 deletions(-) diff --git a/applications/plugins/mousejacker/mousejacker.c b/applications/plugins/mousejacker/mousejacker.c index e050f0a25..79067bce3 100644 --- a/applications/plugins/mousejacker/mousejacker.c +++ b/applications/plugins/mousejacker/mousejacker.c @@ -382,7 +382,7 @@ int32_t mousejacker_app(void* p) { } furi_thread_free(plugin_state->mjthread); - furi_hal_spi_release(nrf24_HANDLE); + nrf24_deinit(); view_port_enabled_set(view_port, false); gui_remove_view_port(gui, view_port); furi_record_close(RECORD_GUI); diff --git a/applications/plugins/nrfsniff/nrfsniff.c b/applications/plugins/nrfsniff/nrfsniff.c index acf413d65..315db831c 100644 --- a/applications/plugins/nrfsniff/nrfsniff.c +++ b/applications/plugins/nrfsniff/nrfsniff.c @@ -440,7 +440,7 @@ int32_t nrfsniff_app(void* p) { sample_time = DEFAULT_SAMPLE_TIME; target_rate = 8; // rate can be either 8 (2Mbps) or 0 (1Mbps) sniffing_state = false; - furi_hal_spi_release(nrf24_HANDLE); + nrf24_deinit(); view_port_enabled_set(view_port, false); gui_remove_view_port(gui, view_port); furi_record_close(RECORD_GUI); diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index a05319b9d..77e93c0ca 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,8.2,, +Version,+,8.3,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -1790,6 +1790,7 @@ Function,+,notification_message,void,"NotificationApp*, const NotificationSequen Function,+,notification_message_block,void,"NotificationApp*, const NotificationSequence*" Function,-,nrand48,long,unsigned short[3] Function,-,nrf24_configure,void,"FuriHalSpiBusHandle*, uint8_t, uint8_t*, uint8_t*, uint8_t, uint8_t, _Bool, _Bool" +Function,+,nrf24_deinit,void, Function,+,nrf24_find_channel,uint8_t,"FuriHalSpiBusHandle*, uint8_t*, uint8_t*, uint8_t, uint8_t, uint8_t, uint8_t, _Bool" Function,-,nrf24_flush_rx,uint8_t,FuriHalSpiBusHandle* Function,-,nrf24_flush_tx,uint8_t,FuriHalSpiBusHandle* diff --git a/lib/drivers/nrf24.c b/lib/drivers/nrf24.c index 2905072d3..8b3776445 100644 --- a/lib/drivers/nrf24.c +++ b/lib/drivers/nrf24.c @@ -12,6 +12,13 @@ void nrf24_init() { furi_hal_gpio_write(nrf24_CE_PIN, false); } +void nrf24_deinit() { + furi_hal_spi_release(nrf24_HANDLE); + furi_hal_spi_bus_handle_deinit(nrf24_HANDLE); + furi_hal_gpio_write(nrf24_CE_PIN, false); + furi_hal_gpio_init(nrf24_CE_PIN, GpioModeAnalog, GpioPullNo, GpioSpeedLow); +} + void nrf24_spi_trx( FuriHalSpiBusHandle* handle, uint8_t* tx, diff --git a/lib/drivers/nrf24.h b/lib/drivers/nrf24.h index 584eaaea7..3cfcfe089 100644 --- a/lib/drivers/nrf24.h +++ b/lib/drivers/nrf24.h @@ -116,6 +116,11 @@ uint8_t nrf24_set_tx_mode(FuriHalSpiBusHandle* handle); */ void nrf24_init(); +/** Must call this when we end using nrf24 device + * + */ +void nrf24_deinit(); + /** Send flush rx command * * @param handle - pointer to FuriHalSpiHandle From a22b107335b2d847b370943e05aa975a8e49a157 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Wed, 2 Nov 2022 13:28:43 +0300 Subject: [PATCH 06/23] Plugins: Update Wifi Marauder https://github.com/0xchocolate/flipperzero-firmware-with-wifi-marauder-companion --- .../scenes/wifi_marauder_scene_console_output.c | 2 +- .../scenes/wifi_marauder_scene_start.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/applications/plugins/wifi_marauder_companion/scenes/wifi_marauder_scene_console_output.c b/applications/plugins/wifi_marauder_companion/scenes/wifi_marauder_scene_console_output.c index c5afa6502..55e6f63a4 100644 --- a/applications/plugins/wifi_marauder_companion/scenes/wifi_marauder_scene_console_output.c +++ b/applications/plugins/wifi_marauder_companion/scenes/wifi_marauder_scene_console_output.c @@ -34,7 +34,7 @@ void wifi_marauder_scene_console_output_on_enter(void* context) { app->text_box_store_strlen = 0; if(0 == strncmp("help", app->selected_tx_string, strlen("help"))) { const char* help_msg = - "For app support/feedback,\nreach out to me:\n@cococode#6011 (discord)\n0xchocolate (github)\n"; + "Marauder companion v0.2.1\nFor app support/feedback,\nreach out to me:\n@cococode#6011 (discord)\n0xchocolate (github)\n"; furi_string_cat_str(app->text_box_store, help_msg); app->text_box_store_strlen += strlen(help_msg); } diff --git a/applications/plugins/wifi_marauder_companion/scenes/wifi_marauder_scene_start.c b/applications/plugins/wifi_marauder_companion/scenes/wifi_marauder_scene_start.c index b6d3f7059..a2dbf4b02 100644 --- a/applications/plugins/wifi_marauder_companion/scenes/wifi_marauder_scene_start.c +++ b/applications/plugins/wifi_marauder_companion/scenes/wifi_marauder_scene_start.c @@ -10,7 +10,7 @@ typedef enum { FOCUS_CONSOLE_END = 0, FOCUS_CONSOLE_START, FOCUS_CONSOLE_TOGGLE #define SHOW_STOPSCAN_TIP (true) #define NO_TIP (false) -#define MAX_OPTIONS (6) +#define MAX_OPTIONS (7) typedef struct { const char* item_string; const char* options_menu[MAX_OPTIONS]; @@ -56,9 +56,9 @@ const WifiMarauderItem items[NUM_MENU_ITEMS] = { FOCUS_CONSOLE_END, SHOW_STOPSCAN_TIP}, {"Sniff", - {"beacon", "deauth", "esp", "pmkid", "pwn"}, - 5, - {"sniffbeacon", "sniffdeauth", "sniffesp", "sniffpmkid", "sniffpwn"}, + {"beacon", "deauth", "esp", "pmkid", "probe", "pwn", "raw"}, + 7, + {"sniffbeacon", "sniffdeauth", "sniffesp", "sniffpmkid", "sniffprobe", "sniffpwn", "sniffraw"}, NO_ARGS, FOCUS_CONSOLE_END, SHOW_STOPSCAN_TIP}, From abfa804ae0bf8c126b5dd78a92cc59c9cec14103 Mon Sep 17 00:00:00 2001 From: "Vasyl \"vk\" Kaigorodov" Date: Wed, 2 Nov 2022 15:36:17 +0100 Subject: [PATCH 07/23] Gui: refactor buttons remapping (#1949) * Gui: refactor buttons remapping Instead of calling 3 separate functions with a ton of switch/case statements, use a 2-dimensional lookup table to remap buttons based on the orientation. * Gui: cleanup input mapping and fix incorrect asserts * SnakeGame: handle input special case Co-authored-by: Aleksandr Kutuzov --- applications/plugins/snake_game/snake_game.c | 2 + applications/services/gui/view_port.c | 110 +++++++----------- applications/services/gui/view_port.h | 1 + applications/services/input/input.c | 3 +- applications/services/input/input.h | 1 + .../targets/f7/furi_hal/furi_hal_resources.h | 1 + 6 files changed, 51 insertions(+), 67 deletions(-) diff --git a/applications/plugins/snake_game/snake_game.c b/applications/plugins/snake_game/snake_game.c index 283d017ed..f9309c280 100644 --- a/applications/plugins/snake_game/snake_game.c +++ b/applications/plugins/snake_game/snake_game.c @@ -380,6 +380,8 @@ int32_t snake_game_app(void* p) { case InputKeyBack: processing = false; break; + default: + break; } } } else if(event.type == EventTypeTick) { diff --git a/applications/services/gui/view_port.c b/applications/services/gui/view_port.c index baa8f7bd2..ffd01450b 100644 --- a/applications/services/gui/view_port.c +++ b/applications/services/gui/view_port.c @@ -7,61 +7,51 @@ // TODO add mutex to view_port ops -static void view_port_remap_buttons_vertical(InputEvent* event) { - switch(event->key) { - case InputKeyUp: - event->key = InputKeyRight; - break; - case InputKeyDown: - event->key = InputKeyLeft; - break; - case InputKeyRight: - event->key = InputKeyDown; - break; - case InputKeyLeft: - event->key = InputKeyUp; - break; - default: - break; - } -} +_Static_assert(ViewPortOrientationMAX == 4, "Incorrect ViewPortOrientation count"); +_Static_assert( + (ViewPortOrientationHorizontal == 0 && ViewPortOrientationHorizontalFlip == 1 && + ViewPortOrientationVertical == 2 && ViewPortOrientationVerticalFlip == 3), + "Incorrect ViewPortOrientation order"); +_Static_assert(InputKeyMAX == 6, "Incorrect InputKey count"); +_Static_assert( + (InputKeyUp == 0 && InputKeyDown == 1 && InputKeyRight == 2 && InputKeyLeft == 3 && + InputKeyOk == 4 && InputKeyBack == 5), + "Incorrect InputKey order"); -static void view_port_remap_buttons_vertical_flip(InputEvent* event) { - switch(event->key) { - case InputKeyUp: - event->key = InputKeyLeft; - break; - case InputKeyDown: - event->key = InputKeyRight; - break; - case InputKeyRight: - event->key = InputKeyUp; - break; - case InputKeyLeft: - event->key = InputKeyDown; - break; - default: - break; - } -} +/** InputKey directional keys mappings for different screen orientations +* +*/ +static const InputKey view_port_input_mapping[ViewPortOrientationMAX][InputKeyMAX] = { + {InputKeyUp, + InputKeyDown, + InputKeyRight, + InputKeyLeft, + InputKeyOk, + InputKeyBack}, //ViewPortOrientationHorizontal + {InputKeyDown, + InputKeyUp, + InputKeyLeft, + InputKeyRight, + InputKeyOk, + InputKeyBack}, //ViewPortOrientationHorizontalFlip + {InputKeyRight, + InputKeyLeft, + InputKeyDown, + InputKeyUp, + InputKeyOk, + InputKeyBack}, //ViewPortOrientationVertical + {InputKeyLeft, + InputKeyRight, + InputKeyUp, + InputKeyDown, + InputKeyOk, + InputKeyBack}, //ViewPortOrientationVerticalFlip +}; -static void view_port_remap_buttons_horizontal_flip(InputEvent* event) { - switch(event->key) { - case InputKeyUp: - event->key = InputKeyDown; - break; - case InputKeyDown: - event->key = InputKeyUp; - break; - case InputKeyRight: - event->key = InputKeyLeft; - break; - case InputKeyLeft: - event->key = InputKeyRight; - break; - default: - break; - } +// Remaps directional pad buttons on Flipper based on ViewPort orientation +static void view_port_map_input(InputEvent* event, ViewPortOrientation orientation) { + furi_assert(orientation < ViewPortOrientationMAX && event->key < InputKeyMAX); + event->key = view_port_input_mapping[orientation][event->key]; } static void view_port_setup_canvas_orientation(const ViewPort* view_port, Canvas* canvas) { @@ -170,19 +160,7 @@ void view_port_input(ViewPort* view_port, InputEvent* event) { if(view_port->input_callback) { ViewPortOrientation orientation = view_port_get_orientation(view_port); - switch(orientation) { - case ViewPortOrientationHorizontalFlip: - view_port_remap_buttons_horizontal_flip(event); - break; - case ViewPortOrientationVertical: - view_port_remap_buttons_vertical(event); - break; - case ViewPortOrientationVerticalFlip: - view_port_remap_buttons_vertical_flip(event); - break; - default: - break; - } + view_port_map_input(event, orientation); view_port->input_callback(event, view_port->input_callback_context); } } diff --git a/applications/services/gui/view_port.h b/applications/services/gui/view_port.h index 169681ac0..703e99248 100644 --- a/applications/services/gui/view_port.h +++ b/applications/services/gui/view_port.h @@ -19,6 +19,7 @@ typedef enum { ViewPortOrientationHorizontalFlip, ViewPortOrientationVertical, ViewPortOrientationVerticalFlip, + ViewPortOrientationMAX, /**< Special value, don't use it */ } ViewPortOrientation; /** ViewPort Draw callback diff --git a/applications/services/input/input.c b/applications/services/input/input.c index 7b8433aef..d1aef9e8a 100644 --- a/applications/services/input/input.c +++ b/applications/services/input/input.c @@ -60,8 +60,9 @@ const char* input_get_type_name(InputType type) { return "Long"; case InputTypeRepeat: return "Repeat"; + default: + return "Unknown"; } - return "Unknown"; } int32_t input_srv(void* p) { diff --git a/applications/services/input/input.h b/applications/services/input/input.h index bd0ba3902..172b16361 100644 --- a/applications/services/input/input.h +++ b/applications/services/input/input.h @@ -22,6 +22,7 @@ typedef enum { InputTypeShort, /**< Short event, emitted after InputTypeRelease done withing INPUT_LONG_PRESS interval */ InputTypeLong, /**< Long event, emmited after INPUT_LONG_PRESS interval, asynchronouse to InputTypeRelease */ InputTypeRepeat, /**< Repeat event, emmited with INPUT_REPEATE_PRESS period after InputTypeLong event */ + InputTypeMAX, /**< Special value for exceptional */ } InputType; /** Input Event, dispatches with FuriPubSub */ diff --git a/firmware/targets/f7/furi_hal/furi_hal_resources.h b/firmware/targets/f7/furi_hal/furi_hal_resources.h index d16c567e6..8d53ec48a 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_resources.h +++ b/firmware/targets/f7/furi_hal/furi_hal_resources.h @@ -20,6 +20,7 @@ typedef enum { InputKeyLeft, InputKeyOk, InputKeyBack, + InputKeyMAX, /**< Special value */ } InputKey; /* Light */ From ebc2b66372091d811278bcb6180bfa16b62cd46f Mon Sep 17 00:00:00 2001 From: hedger Date: Wed, 2 Nov 2022 19:15:40 +0400 Subject: [PATCH 08/23] fbt fixes for mfbt pt2 (#1951) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fbt: split sdk management code * scripts: fixed import handling * fbt: sdk: reformatted paths * scrips: dist: bundling libs as a build artifact * fbt: sdk: better path management * typo fix * fbt: sdk: minor path handling fixes * toolchain: fixed windows toolchain download * fbt: minor refactorin * fbt: moved sdk management code to extapps.scons * fbt: fixed sdk symbols header path; disabled -fstack-usage * fbt: changed pathing for .py scripts * fbt: changed SDK_HEADERS pathing; added libusb to SDK; added icon_i.h to SDK; added hw target to SDK meta * fbt: added libusb headers to SDK * picopass: include cleanup; api: added subghz/registry.h; api: added mbedtls to exported headers * picopass: fixed formatting * fbt: fixed COPRO_ASSETS_SCRIPT * sdk: added basic infrared apis * toolchain: added ufbt to list of legal fbtenv callers; updated error messages * fbt: changed manifest collection & icon processing code * fbt: simpler srcdir lookup * toolchain: path management fixes; fbt: fixes for fap private libs paths * scripts: toolchain: reworked download on Windows * toolchain: v17 * scripts: added colorlog for logging * Github: fix unit tests Co-authored-by: あく --- .github/workflows/unit_tests.yml | 8 +- SConstruct | 10 +- applications/plugins/picopass/125_10px.png | Bin 0 -> 308 bytes applications/plugins/picopass/application.fam | 2 +- .../plugins/picopass/picopass_worker_i.h | 2 - applications/plugins/picopass/rfal_picopass.c | 7 +- applications/services/gui/application.fam | 1 + firmware.scons | 66 ++++------ firmware/SConscript | 7 +- firmware/targets/f7/api_symbols.csv | 124 +++++++++++++++++- lib/SConscript | 12 +- lib/STM32CubeWB.scons | 2 +- lib/flipper_application/SConscript | 2 +- lib/flipper_format/SConscript | 4 +- lib/infrared/SConscript | 5 + lib/lfrfid/SConscript | 12 +- lib/libusb_stm32.scons | 4 + lib/mbedtls.scons | 4 + lib/misc.scons | 2 +- lib/print/SConscript | 2 +- lib/subghz/SConscript | 25 ++-- lib/subghz/registry.h | 8 ++ lib/toolbox/SConscript | 34 ++--- scripts/fbt/util.py | 15 ++- scripts/fbt_tools/crosscc.py | 15 +++ scripts/fbt_tools/fbt_apps.py | 38 +++--- scripts/fbt_tools/fbt_assets.py | 20 ++- scripts/fbt_tools/fbt_dist.py | 9 +- scripts/fbt_tools/fbt_extapps.py | 24 +++- scripts/fbt_tools/fbt_sdk.py | 46 ++++--- scripts/fbt_tools/fbt_version.py | 5 +- scripts/fbt_tools/fwbin.py | 3 +- scripts/flipper/app.py | 16 ++- scripts/sconsdist.py | 6 +- scripts/testing/await_flipper.py | 0 scripts/testing/units.py | 0 scripts/toolchain/fbtenv.cmd | 13 +- scripts/toolchain/fbtenv.sh | 24 ++-- .../toolchain/windows-toolchain-download.ps1 | 38 ++++-- site_scons/cc.scons | 5 +- site_scons/environ.scons | 36 ++--- site_scons/extapps.scons | 38 +++++- 42 files changed, 459 insertions(+), 235 deletions(-) create mode 100644 applications/plugins/picopass/125_10px.png mode change 100644 => 100755 scripts/testing/await_flipper.py mode change 100644 => 100755 scripts/testing/units.py diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml index b5bf10004..a7671f0f9 100644 --- a/.github/workflows/unit_tests.yml +++ b/.github/workflows/unit_tests.yml @@ -31,22 +31,26 @@ jobs: id: connect if: steps.compile.outcome == 'success' run: | - python3 ./scripts/testing/await_flipper.py ${{steps.device.outputs.flipper}} + . scripts/toolchain/fbtenv.sh + ./scripts/testing/await_flipper.py ${{steps.device.outputs.flipper}} - name: 'Format flipper SD card' id: format if: steps.connect.outcome == 'success' run: | + . scripts/toolchain/fbtenv.sh ./scripts/storage.py -p ${{steps.device.outputs.flipper}} format_ext - name: 'Copy assets and unit tests data to flipper' id: copy if: steps.format.outcome == 'success' run: | + . scripts/toolchain/fbtenv.sh ./scripts/storage.py -p ${{steps.device.outputs.flipper}} send assets/resources /ext ./scripts/storage.py -p ${{steps.device.outputs.flipper}} send assets/unit_tests /ext/unit_tests - name: 'Run units and validate results' if: steps.copy.outcome == 'success' run: | - python3 ./scripts/testing/units.py ${{steps.device.outputs.flipper}} + . scripts/toolchain/fbtenv.sh + ./scripts/testing/units.py ${{steps.device.outputs.flipper}} diff --git a/SConstruct b/SConstruct index 448df9715..13a698c81 100644 --- a/SConstruct +++ b/SConstruct @@ -33,10 +33,6 @@ coreenv = SConscript( ) SConscript("site_scons/cc.scons", exports={"ENV": coreenv}) -# Store root dir in environment for certain tools -coreenv["ROOT_DIR"] = Dir(".") - - # Create a separate "dist" environment and add construction envs to it distenv = coreenv.Clone( tools=[ @@ -233,13 +229,13 @@ distenv.PhonyTarget( # Linter distenv.PhonyTarget( "lint", - "${PYTHON3} scripts/lint.py check ${LINT_SOURCES}", + "${PYTHON3} ${FBT_SCRIPT_DIR}/lint.py check ${LINT_SOURCES}", LINT_SOURCES=firmware_env["LINT_SOURCES"], ) distenv.PhonyTarget( "format", - "${PYTHON3} scripts/lint.py format ${LINT_SOURCES}", + "${PYTHON3} ${FBT_SCRIPT_DIR}/lint.py format ${LINT_SOURCES}", LINT_SOURCES=firmware_env["LINT_SOURCES"], ) @@ -280,7 +276,7 @@ distenv.PhonyTarget( ) # Start Flipper CLI via PySerial's miniterm -distenv.PhonyTarget("cli", "${PYTHON3} scripts/serial_cli.py") +distenv.PhonyTarget("cli", "${PYTHON3} ${FBT_SCRIPT_DIR}/serial_cli.py") # Find blackmagic probe diff --git a/applications/plugins/picopass/125_10px.png b/applications/plugins/picopass/125_10px.png new file mode 100644 index 0000000000000000000000000000000000000000..ce01284a2c1f3eb413f581b84f1fb3f3a2a7223b GIT binary patch literal 308 zcmeAS@N?(olHy`uVBq!ia0vp^AT}2xkYHHq`AGmsv7|ftIx;Y9?C1WI$O_~uBzpw; zGB8xBF)%c=FfjZA3N^f7U???UV0e|lz+g3lfkC`r&aOZkpafHrx4R1i<>&pI=m5)bWZjP>yH&963)5S4_<9hOs!iI #include -#include -#include #include #include diff --git a/applications/plugins/picopass/rfal_picopass.c b/applications/plugins/picopass/rfal_picopass.c index 50cd4e95d..ac66cb92d 100644 --- a/applications/plugins/picopass/rfal_picopass.c +++ b/applications/plugins/picopass/rfal_picopass.c @@ -1,5 +1,4 @@ #include "rfal_picopass.h" -#include "utils.h" #define RFAL_PICOPASS_TXRX_FLAGS \ (FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_TX_MANUAL | FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON | \ @@ -97,7 +96,7 @@ FuriHalNfcReturn rfalPicoPassPollerSelect(uint8_t* csn, rfalPicoPassSelectRes* s rfalPicoPassSelectReq selReq; selReq.CMD = RFAL_PICOPASS_CMD_SELECT; - ST_MEMCPY(selReq.CSN, csn, RFAL_PICOPASS_UID_LEN); + memcpy(selReq.CSN, csn, RFAL_PICOPASS_UID_LEN); uint16_t recvLen = 0; uint32_t flags = RFAL_PICOPASS_TXRX_FLAGS; uint32_t fwt = furi_hal_nfc_ll_ms2fc(20); @@ -146,8 +145,8 @@ FuriHalNfcReturn rfalPicoPassPollerCheck(uint8_t* mac, rfalPicoPassCheckRes* chk FuriHalNfcReturn ret; rfalPicoPassCheckReq chkReq; chkReq.CMD = RFAL_PICOPASS_CMD_CHECK; - ST_MEMCPY(chkReq.mac, mac, 4); - ST_MEMSET(chkReq.null, 0, 4); + memcpy(chkReq.mac, mac, 4); + memset(chkReq.null, 0, 4); uint16_t recvLen = 0; uint32_t flags = RFAL_PICOPASS_TXRX_FLAGS; uint32_t fwt = furi_hal_nfc_ll_ms2fc(20); diff --git a/applications/services/gui/application.fam b/applications/services/gui/application.fam index 7fad7b4ea..869d964dd 100644 --- a/applications/services/gui/application.fam +++ b/applications/services/gui/application.fam @@ -12,6 +12,7 @@ App( order=70, sdk_headers=[ "gui.h", + "icon_i.h", "elements.h", "view_dispatcher.h", "view_stack.h", diff --git a/firmware.scons b/firmware.scons index 63a1aa3f7..a0c1ab339 100644 --- a/firmware.scons +++ b/firmware.scons @@ -1,6 +1,7 @@ Import("ENV", "fw_build_meta") from SCons.Errors import UserError +from SCons.Node import FS import itertools from fbt_extra.util import ( @@ -14,7 +15,6 @@ env = ENV.Clone( ("compilation_db", {"COMPILATIONDB_COMSTR": "\tCDB\t${TARGET}"}), "fwbin", "fbt_apps", - "fbt_sdk", ], COMPILATIONDB_USE_ABSPATH=False, BUILD_DIR=fw_build_meta["build_dir"], @@ -112,7 +112,9 @@ lib_targets = env.BuildModules( # Now, env is fully set up with everything to build apps -fwenv = env.Clone() +fwenv = env.Clone(FW_ARTIFACTS=[]) + +fw_artifacts = fwenv["FW_ARTIFACTS"] # Set up additional app-specific build flags SConscript("site_scons/firmwareopts.scons", exports={"ENV": fwenv}) @@ -130,7 +132,14 @@ if extra_int_apps := GetOption("extra_int_apps"): if fwenv["FAP_EXAMPLES"]: fwenv.Append(APPDIRS=[("applications/examples", False)]) -fwenv.LoadApplicationManifests() +for app_dir, _ in env["APPDIRS"]: + app_dir_node = env.Dir("#").Dir(app_dir) + + for entry in app_dir_node.glob("*"): + if isinstance(entry, FS.Dir) and not str(entry).startswith("."): + fwenv.LoadAppManifest(entry) + + fwenv.PrepareApplicationsBuild() # Build external apps @@ -138,6 +147,7 @@ if env["IS_BASE_FIRMWARE"]: extapps = fwenv["FW_EXTAPPS"] = SConscript( "site_scons/extapps.scons", exports={"ENV": fwenv} ) + fw_artifacts.append(extapps["sdk_tree"]) # Add preprocessor definitions for current set of apps @@ -220,7 +230,10 @@ Depends(fwelf, lib_targets) AddPostAction(fwelf, fwenv["APPBUILD_DUMP"]) AddPostAction( fwelf, - Action('${PYTHON3} "${ROOT_DIR}/scripts/fwsize.py" elf ${TARGET}', "Firmware size"), + Action( + '${PYTHON3} "${BIN_SIZE_SCRIPT}" elf ${TARGET}', + "Firmware size", + ), ) # Produce extra firmware files @@ -228,7 +241,7 @@ fwhex = fwenv["FW_HEX"] = fwenv.HEXBuilder("${FIRMWARE_BUILD_CFG}") fwbin = fwenv["FW_BIN"] = fwenv.BINBuilder("${FIRMWARE_BUILD_CFG}") AddPostAction( fwbin, - Action('@${PYTHON3} "${ROOT_DIR}/scripts/fwsize.py" bin ${TARGET}'), + Action('@${PYTHON3} "${BIN_SIZE_SCRIPT}" bin ${TARGET}'), ) fwdfu = fwenv["FW_DFU"] = fwenv.DFUBuilder("${FIRMWARE_BUILD_CFG}") @@ -238,12 +251,14 @@ fwdump = fwenv.ObjDump("${FIRMWARE_BUILD_CFG}") Alias(fwenv["FIRMWARE_BUILD_CFG"] + "_list", fwdump) -fw_artifacts = fwenv["FW_ARTIFACTS"] = [ - fwhex, - fwbin, - fwdfu, - fwenv["FW_VERSION_JSON"], -] +fw_artifacts.extend( + [ + fwhex, + fwbin, + fwdfu, + fwenv["FW_VERSION_JSON"], + ] +) fwcdb = fwenv.CompilationDatabase() @@ -272,34 +287,5 @@ if should_gen_cdb_and_link_dir(fwenv, BUILD_TARGETS): Alias(fwenv["FIRMWARE_BUILD_CFG"] + "_all", fw_artifacts) -if fwenv["IS_BASE_FIRMWARE"]: - sdk_source = fwenv.SDKPrebuilder( - "sdk_origin", - # Deps on root SDK headers and generated files - (fwenv["SDK_HEADERS"], fwenv["FW_ASSETS_HEADERS"]), - ) - # Extra deps on headers included in deeper levels - Depends(sdk_source, fwenv.ProcessSdkDepends("sdk_origin.d")) - - fwenv["SDK_DIR"] = fwenv.Dir("sdk") - sdk_tree = fwenv.SDKTree(fwenv["SDK_DIR"], "sdk_origin") - fw_artifacts.append(sdk_tree) - # AlwaysBuild(sdk_tree) - Alias("sdk_tree", sdk_tree) - - sdk_apicheck = fwenv.SDKSymUpdater(fwenv["SDK_DEFINITION"], "sdk_origin") - Precious(sdk_apicheck) - NoClean(sdk_apicheck) - AlwaysBuild(sdk_apicheck) - Alias("sdk_check", sdk_apicheck) - - sdk_apisyms = fwenv.SDKSymGenerator( - "assets/compiled/symbols.h", fwenv["SDK_DEFINITION"] - ) - Alias("api_syms", sdk_apisyms) - - if fwenv["FORCE"]: - fwenv.AlwaysBuild(sdk_source, sdk_tree, sdk_apicheck, sdk_apisyms) - Return("fwenv") diff --git a/firmware/SConscript b/firmware/SConscript index 2285a6f2c..19dde2e4c 100644 --- a/firmware/SConscript +++ b/firmware/SConscript @@ -2,11 +2,10 @@ Import("env") env.Append( LINT_SOURCES=["firmware"], - # SDK_HEADERS=[env.File("#/firmware/targets/furi_hal_include/furi_hal.h")], SDK_HEADERS=[ - *env.GlobRecursive("*.h", "#/firmware/targets/furi_hal_include", "*_i.h"), - *env.GlobRecursive("*.h", "#/firmware/targets/f${TARGET_HW}/furi_hal", "*_i.h"), - File("#/firmware/targets/f7/platform_specific/intrinsic_export.h"), + *env.GlobRecursive("*.h", "targets/furi_hal_include", "*_i.h"), + *env.GlobRecursive("*.h", "targets/f${TARGET_HW}/furi_hal", "*_i.h"), + File("targets/f7/platform_specific/intrinsic_export.h"), ], ) diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 00ba30c24..0d9a5b561 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,7.0,, +Version,+,7.2,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -7,6 +7,7 @@ Header,+,applications/services/dialogs/dialogs.h,, Header,+,applications/services/dolphin/dolphin.h,, Header,+,applications/services/gui/elements.h,, Header,+,applications/services/gui/gui.h,, +Header,+,applications/services/gui/icon_i.h,, Header,+,applications/services/gui/modules/button_menu.h,, Header,+,applications/services/gui/modules/button_panel.h,, Header,+,applications/services/gui/modules/byte_input.h,, @@ -110,12 +111,42 @@ Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_wwdg.h,, Header,+,lib/flipper_application/flipper_application.h,, Header,+,lib/flipper_format/flipper_format.h,, Header,+,lib/flipper_format/flipper_format_i.h,, +Header,+,lib/infrared/encoder_decoder/infrared.h,, +Header,+,lib/infrared/worker/infrared_transmit.h,, +Header,+,lib/infrared/worker/infrared_worker.h,, Header,+,lib/lfrfid/lfrfid_dict_file.h,, Header,+,lib/lfrfid/lfrfid_raw_file.h,, Header,+,lib/lfrfid/lfrfid_raw_worker.h,, Header,+,lib/lfrfid/lfrfid_worker.h,, Header,+,lib/lfrfid/protocols/lfrfid_protocols.h,, Header,+,lib/lfrfid/tools/bit_lib.h,, +Header,+,lib/libusb_stm32/inc/hid_usage_button.h,, +Header,+,lib/libusb_stm32/inc/hid_usage_consumer.h,, +Header,+,lib/libusb_stm32/inc/hid_usage_desktop.h,, +Header,+,lib/libusb_stm32/inc/hid_usage_device.h,, +Header,+,lib/libusb_stm32/inc/hid_usage_game.h,, +Header,+,lib/libusb_stm32/inc/hid_usage_keyboard.h,, +Header,+,lib/libusb_stm32/inc/hid_usage_led.h,, +Header,+,lib/libusb_stm32/inc/hid_usage_ordinal.h,, +Header,+,lib/libusb_stm32/inc/hid_usage_power.h,, +Header,+,lib/libusb_stm32/inc/hid_usage_simulation.h,, +Header,+,lib/libusb_stm32/inc/hid_usage_sport.h,, +Header,+,lib/libusb_stm32/inc/hid_usage_telephony.h,, +Header,+,lib/libusb_stm32/inc/hid_usage_vr.h,, +Header,+,lib/libusb_stm32/inc/usb.h,, +Header,+,lib/libusb_stm32/inc/usb_cdc.h,, +Header,+,lib/libusb_stm32/inc/usb_cdca.h,, +Header,+,lib/libusb_stm32/inc/usb_cdce.h,, +Header,+,lib/libusb_stm32/inc/usb_cdci.h,, +Header,+,lib/libusb_stm32/inc/usb_cdcp.h,, +Header,+,lib/libusb_stm32/inc/usb_cdcw.h,, +Header,+,lib/libusb_stm32/inc/usb_dfu.h,, +Header,+,lib/libusb_stm32/inc/usb_hid.h,, +Header,+,lib/libusb_stm32/inc/usb_std.h,, +Header,+,lib/libusb_stm32/inc/usb_tmc.h,, +Header,+,lib/libusb_stm32/inc/usbd_core.h,, +Header,+,lib/mbedtls/include/mbedtls/des.h,, +Header,+,lib/mbedtls/include/mbedtls/sha1.h,, Header,+,lib/micro-ecc/uECC.h,, Header,+,lib/one_wire/ibutton/ibutton_worker.h,, Header,+,lib/one_wire/maxim_crc.h,, @@ -132,6 +163,7 @@ Header,+,lib/subghz/blocks/math.h,, Header,+,lib/subghz/environment.h,, Header,+,lib/subghz/protocols/raw.h,, Header,+,lib/subghz/receiver.h,, +Header,+,lib/subghz/registry.h,, Header,+,lib/subghz/subghz_setting.h,, Header,+,lib/subghz/subghz_tx_rx_worker.h,, Header,+,lib/subghz/subghz_worker.h,, @@ -407,6 +439,7 @@ Function,-,_system_r,int,"_reent*, const char*" Function,-,_tempnam_r,char*,"_reent*, const char*, const char*" Function,-,_tmpfile_r,FILE*,_reent* Function,-,_tmpnam_r,char*,"_reent*, char*" +Function,-,_tzset_r,void,_reent* Function,-,_ungetc_r,int,"_reent*, int, FILE*" Function,-,_unsetenv_r,int,"_reent*, const char*" Function,-,_vasiprintf_r,int,"_reent*, char**, const char*, __gnuc_va_list" @@ -454,6 +487,8 @@ Function,+,args_read_hex_bytes,_Bool,"FuriString*, uint8_t*, size_t" Function,+,args_read_int_and_trim,_Bool,"FuriString*, int*" Function,+,args_read_probably_quoted_string_and_trim,_Bool,"FuriString*, FuriString*" Function,+,args_read_string_and_trim,_Bool,"FuriString*, FuriString*" +Function,-,asctime,char*,const tm* +Function,-,asctime_r,char*,"const tm*, char*" Function,-,asin,double,double Function,-,asinf,float,float Function,-,asinh,double,double @@ -621,6 +656,7 @@ Function,+,cli_read_timeout,size_t,"Cli*, uint8_t*, size_t, uint32_t" Function,+,cli_session_close,void,Cli* Function,+,cli_session_open,void,"Cli*, void*" Function,+,cli_write,void,"Cli*, const uint8_t*, size_t" +Function,-,clock,clock_t, Function,-,copysign,double,"double, double" Function,-,copysignf,float,"float, float" Function,-,copysignl,long double,"long double, long double" @@ -633,6 +669,8 @@ Function,-,cosl,long double,long double Function,+,crc32_calc_buffer,uint32_t,"uint32_t, const void*, size_t" Function,+,crc32_calc_file,uint32_t,"File*, const FileCrcProgressCb, void*" Function,-,ctermid,char*,char* +Function,-,ctime,char*,const time_t* +Function,-,ctime_r,char*,"const time_t*, char*" Function,-,cuserid,char*,char* Function,+,delete_mutex,_Bool,ValueMutex* Function,+,dialog_ex_alloc,DialogEx*, @@ -659,6 +697,7 @@ Function,+,dialog_message_set_icon,void,"DialogMessage*, const Icon*, uint8_t, u Function,+,dialog_message_set_text,void,"DialogMessage*, const char*, uint8_t, uint8_t, Align, Align" Function,+,dialog_message_show,DialogMessageButton,"DialogsApp*, const DialogMessage*" Function,+,dialog_message_show_storage_error,void,"DialogsApp*, const char*" +Function,-,difftime,double,"time_t, time_t" Function,-,digital_signal_alloc,DigitalSignal*,uint32_t Function,-,digital_signal_append,_Bool,"DigitalSignal*, DigitalSignal*" Function,-,digital_signal_free,void,DigitalSignal* @@ -1475,6 +1514,8 @@ Function,-,getenv,char*,const char* Function,-,gets,char*,char* Function,-,getsubopt,int,"char**, char**, char**" Function,-,getw,int,FILE* +Function,-,gmtime,tm*,const time_t* +Function,-,gmtime_r,tm*,"const time_t*, tm*" Function,+,gui_add_framebuffer_callback,void,"Gui*, GuiCanvasCommitCallback, void*" Function,+,gui_add_view_port,void,"Gui*, ViewPort*, GuiLayer" Function,+,gui_get_framebuffer_size,size_t,Gui* @@ -1535,6 +1576,42 @@ Function,-,ilogbl,int,long double Function,-,index,char*,"const char*, int" Function,-,infinity,double, Function,-,infinityf,float, +Function,+,infrared_alloc_decoder,InfraredDecoderHandler*, +Function,+,infrared_alloc_encoder,InfraredEncoderHandler*, +Function,+,infrared_check_decoder_ready,const InfraredMessage*,InfraredDecoderHandler* +Function,+,infrared_decode,const InfraredMessage*,"InfraredDecoderHandler*, _Bool, uint32_t" +Function,+,infrared_encode,InfraredStatus,"InfraredEncoderHandler*, uint32_t*, _Bool*" +Function,+,infrared_free_decoder,void,InfraredDecoderHandler* +Function,+,infrared_free_encoder,void,InfraredEncoderHandler* +Function,+,infrared_get_protocol_address_length,uint8_t,InfraredProtocol +Function,+,infrared_get_protocol_by_name,InfraredProtocol,const char* +Function,+,infrared_get_protocol_command_length,uint8_t,InfraredProtocol +Function,+,infrared_get_protocol_duty_cycle,float,InfraredProtocol +Function,+,infrared_get_protocol_frequency,uint32_t,InfraredProtocol +Function,+,infrared_get_protocol_name,const char*,InfraredProtocol +Function,+,infrared_is_protocol_valid,_Bool,InfraredProtocol +Function,+,infrared_reset_decoder,void,InfraredDecoderHandler* +Function,+,infrared_reset_encoder,void,"InfraredEncoderHandler*, const InfraredMessage*" +Function,+,infrared_send,void,"const InfraredMessage*, int" +Function,+,infrared_send_raw,void,"const uint32_t[], uint32_t, _Bool" +Function,+,infrared_send_raw_ext,void,"const uint32_t[], uint32_t, _Bool, uint32_t, float" +Function,+,infrared_worker_alloc,InfraredWorker*, +Function,+,infrared_worker_free,void,InfraredWorker* +Function,+,infrared_worker_get_decoded_signal,const InfraredMessage*,const InfraredWorkerSignal* +Function,+,infrared_worker_get_raw_signal,void,"const InfraredWorkerSignal*, const uint32_t**, size_t*" +Function,+,infrared_worker_rx_enable_blink_on_receiving,void,"InfraredWorker*, _Bool" +Function,+,infrared_worker_rx_enable_signal_decoding,void,"InfraredWorker*, _Bool" +Function,+,infrared_worker_rx_set_received_signal_callback,void,"InfraredWorker*, InfraredWorkerReceivedSignalCallback, void*" +Function,+,infrared_worker_rx_start,void,InfraredWorker* +Function,+,infrared_worker_rx_stop,void,InfraredWorker* +Function,+,infrared_worker_set_decoded_signal,void,"InfraredWorker*, const InfraredMessage*" +Function,+,infrared_worker_set_raw_signal,void,"InfraredWorker*, const uint32_t*, size_t" +Function,+,infrared_worker_signal_is_decoded,_Bool,const InfraredWorkerSignal* +Function,+,infrared_worker_tx_get_signal_steady_callback,InfraredWorkerGetSignalResponse,"void*, InfraredWorker*" +Function,+,infrared_worker_tx_set_get_signal_callback,void,"InfraredWorker*, InfraredWorkerGetSignalCallback, void*" +Function,+,infrared_worker_tx_set_signal_sent_callback,void,"InfraredWorker*, InfraredWorkerMessageSentCallback, void*" +Function,+,infrared_worker_tx_start,void,InfraredWorker* +Function,+,infrared_worker_tx_stop,void,InfraredWorker* Function,+,init_mutex,_Bool,"ValueMutex*, void*, size_t" Function,-,initstate,char*,"unsigned, char*, size_t" Function,+,input_get_key_name,const char*,InputKey @@ -1634,6 +1711,8 @@ Function,+,loader_update_menu,void, Function,+,loading_alloc,Loading*, Function,+,loading_free,void,Loading* Function,+,loading_get_view,View*,Loading* +Function,-,localtime,tm*,const time_t* +Function,-,localtime_r,tm*,"const time_t*, tm*" Function,-,log,double,double Function,-,log10,double,double Function,-,log10f,float,float @@ -1662,6 +1741,36 @@ Function,+,manchester_encoder_advance,_Bool,"ManchesterEncoderState*, const _Boo Function,+,manchester_encoder_finish,ManchesterEncoderResult,ManchesterEncoderState* Function,+,manchester_encoder_reset,void,ManchesterEncoderState* Function,+,maxim_crc8,uint8_t,"const uint8_t*, const uint8_t, const uint8_t" +Function,-,mbedtls_des3_crypt_cbc,int,"mbedtls_des3_context*, int, size_t, unsigned char[8], const unsigned char*, unsigned char*" +Function,-,mbedtls_des3_crypt_ecb,int,"mbedtls_des3_context*, const unsigned char[8], unsigned char[8]" +Function,-,mbedtls_des3_free,void,mbedtls_des3_context* +Function,-,mbedtls_des3_init,void,mbedtls_des3_context* +Function,-,mbedtls_des3_set2key_dec,int,"mbedtls_des3_context*, const unsigned char[8 * 2]" +Function,-,mbedtls_des3_set2key_enc,int,"mbedtls_des3_context*, const unsigned char[8 * 2]" +Function,-,mbedtls_des3_set3key_dec,int,"mbedtls_des3_context*, const unsigned char[8 * 3]" +Function,-,mbedtls_des3_set3key_enc,int,"mbedtls_des3_context*, const unsigned char[8 * 3]" +Function,-,mbedtls_des_crypt_cbc,int,"mbedtls_des_context*, int, size_t, unsigned char[8], const unsigned char*, unsigned char*" +Function,-,mbedtls_des_crypt_ecb,int,"mbedtls_des_context*, const unsigned char[8], unsigned char[8]" +Function,-,mbedtls_des_free,void,mbedtls_des_context* +Function,-,mbedtls_des_init,void,mbedtls_des_context* +Function,-,mbedtls_des_key_check_key_parity,int,const unsigned char[8] +Function,-,mbedtls_des_key_check_weak,int,const unsigned char[8] +Function,-,mbedtls_des_key_set_parity,void,unsigned char[8] +Function,-,mbedtls_des_self_test,int,int +Function,-,mbedtls_des_setkey,void,"uint32_t[32], const unsigned char[8]" +Function,-,mbedtls_des_setkey_dec,int,"mbedtls_des_context*, const unsigned char[8]" +Function,-,mbedtls_des_setkey_enc,int,"mbedtls_des_context*, const unsigned char[8]" +Function,-,mbedtls_internal_sha1_process,int,"mbedtls_sha1_context*, const unsigned char[64]" +Function,-,mbedtls_platform_gmtime_r,tm*,"const mbedtls_time_t*, tm*" +Function,-,mbedtls_platform_zeroize,void,"void*, size_t" +Function,-,mbedtls_sha1,int,"const unsigned char*, size_t, unsigned char[20]" +Function,-,mbedtls_sha1_clone,void,"mbedtls_sha1_context*, const mbedtls_sha1_context*" +Function,-,mbedtls_sha1_finish,int,"mbedtls_sha1_context*, unsigned char[20]" +Function,-,mbedtls_sha1_free,void,mbedtls_sha1_context* +Function,-,mbedtls_sha1_init,void,mbedtls_sha1_context* +Function,-,mbedtls_sha1_self_test,int,int +Function,-,mbedtls_sha1_starts,int,mbedtls_sha1_context* +Function,-,mbedtls_sha1_update,int,"mbedtls_sha1_context*, const unsigned char*, size_t" Function,-,mblen,int,"const char*, size_t" Function,-,mbstowcs,size_t,"wchar_t*, const char*, size_t" Function,-,mbtowc,int,"wchar_t*, const char*, size_t" @@ -1702,6 +1811,7 @@ Function,-,mkostemps,int,"char*, int, int" Function,-,mkstemp,int,char* Function,-,mkstemps,int,"char*, int" Function,-,mktemp,char*,char* +Function,-,mktime,time_t,tm* Function,-,modf,double,"double, double*" Function,-,modff,float,"float, float*" Function,-,modfl,long double,"long double, long double*" @@ -2210,6 +2320,8 @@ Function,+,stream_write_vaformat,size_t,"Stream*, const char*, va_list" Function,-,strerror,char*,int Function,-,strerror_l,char*,"int, locale_t" Function,-,strerror_r,char*,"int, char*, size_t" +Function,-,strftime,size_t,"char*, size_t, const char*, const tm*" +Function,-,strftime_l,size_t,"char*, size_t, const char*, const tm*, locale_t" Function,+,string_stream_alloc,Stream*, Function,-,strlcat,size_t,"char*, const char*, size_t" Function,+,strlcpy,size_t,"char*, const char*, size_t" @@ -2224,6 +2336,8 @@ Function,-,strndup,char*,"const char*, size_t" Function,-,strnlen,size_t,"const char*, size_t" Function,-,strnstr,char*,"const char*, const char*, size_t" Function,-,strpbrk,char*,"const char*, const char*" +Function,-,strptime,char*,"const char*, const char*, tm*" +Function,-,strptime_l,char*,"const char*, const char*, tm*, locale_t" Function,+,strrchr,char*,"const char*, int" Function,-,strsep,char*,"char**, const char*" Function,-,strsignal,char*,int @@ -2313,6 +2427,9 @@ Function,+,subghz_protocol_raw_get_sample_write,size_t,SubGhzProtocolDecoderRAW* Function,+,subghz_protocol_raw_save_to_file_init,_Bool,"SubGhzProtocolDecoderRAW*, const char*, SubGhzRadioPreset*" Function,+,subghz_protocol_raw_save_to_file_pause,void,"SubGhzProtocolDecoderRAW*, _Bool" Function,+,subghz_protocol_raw_save_to_file_stop,void,SubGhzProtocolDecoderRAW* +Function,+,subghz_protocol_registry_count,size_t,const SubGhzProtocolRegistry* +Function,+,subghz_protocol_registry_get_by_index,const SubGhzProtocol*,"const SubGhzProtocolRegistry*, size_t" +Function,+,subghz_protocol_registry_get_by_name,const SubGhzProtocol*,"const SubGhzProtocolRegistry*, const char*" Function,+,subghz_receiver_alloc_init,SubGhzReceiver*,SubGhzEnvironment* Function,+,subghz_receiver_decode,void,"SubGhzReceiver*, _Bool, uint32_t" Function,+,subghz_receiver_free,void,SubGhzReceiver* @@ -2411,6 +2528,7 @@ Function,+,text_input_set_validator,void,"TextInput*, TextInputValidatorCallback Function,-,tgamma,double,double Function,-,tgammaf,float,float Function,-,tgammal,long double,long double +Function,-,time,time_t,time_t* Function,+,timerCalculateTimer,uint32_t,uint16_t Function,-,timerDelay,void,uint16_t Function,+,timerIsExpired,_Bool,uint32_t @@ -2429,6 +2547,7 @@ Function,-,toupper_l,int,"int, locale_t" Function,-,trunc,double,double Function,-,truncf,float,float Function,-,truncl,long double,long double +Function,-,tzset,void, Function,-,uECC_compress,void,"const uint8_t*, uint8_t*, uECC_Curve" Function,+,uECC_compute_public_key,int,"const uint8_t*, uint8_t*, uECC_Curve" Function,-,uECC_curve_private_key_size,int,uECC_Curve @@ -2666,10 +2785,13 @@ Variable,-,MSIRangeTable,const uint32_t[16], Variable,-,SmpsPrescalerTable,const uint32_t[4][6], Variable,+,SystemCoreClock,uint32_t, Variable,+,_ctype_,const char[], +Variable,-,_daylight,int, Variable,+,_global_impure_ptr,_reent*, Variable,+,_impure_ptr,_reent*, Variable,-,_sys_errlist,const char*[], Variable,-,_sys_nerr,int, +Variable,-,_timezone,long, +Variable,-,_tzname,char*[2], Variable,+,cli_vcp,CliSession, Variable,+,furi_hal_i2c_bus_external,FuriHalI2cBus, Variable,+,furi_hal_i2c_bus_power,FuriHalI2cBus, diff --git a/lib/SConscript b/lib/SConscript index 2822684bc..60ffabfa9 100644 --- a/lib/SConscript +++ b/lib/SConscript @@ -17,12 +17,12 @@ env.Append( "lib/print", ], SDK_HEADERS=[ - File("#/lib/one_wire/one_wire_host_timing.h"), - File("#/lib/one_wire/one_wire_host.h"), - File("#/lib/one_wire/one_wire_slave.h"), - File("#/lib/one_wire/one_wire_device.h"), - File("#/lib/one_wire/ibutton/ibutton_worker.h"), - File("#/lib/one_wire/maxim_crc.h"), + File("one_wire/one_wire_host_timing.h"), + File("one_wire/one_wire_host.h"), + File("one_wire/one_wire_slave.h"), + File("one_wire/one_wire_device.h"), + File("one_wire/ibutton/ibutton_worker.h"), + File("one_wire/maxim_crc.h"), ], ) diff --git a/lib/STM32CubeWB.scons b/lib/STM32CubeWB.scons index e8350ea99..b0e55f82e 100644 --- a/lib/STM32CubeWB.scons +++ b/lib/STM32CubeWB.scons @@ -15,7 +15,7 @@ env.Append( ], SDK_HEADERS=env.GlobRecursive( "*_ll_*.h", - "#/lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/", + Dir("STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/"), exclude="*usb.h", ), ) diff --git a/lib/flipper_application/SConscript b/lib/flipper_application/SConscript index 3a5e7f4db..9fbbf95d1 100644 --- a/lib/flipper_application/SConscript +++ b/lib/flipper_application/SConscript @@ -5,7 +5,7 @@ env.Append( "#/lib/flipper_application", ], SDK_HEADERS=[ - File("#/lib/flipper_application/flipper_application.h"), + File("flipper_application.h"), ], ) diff --git a/lib/flipper_format/SConscript b/lib/flipper_format/SConscript index 5e185678b..353da8035 100644 --- a/lib/flipper_format/SConscript +++ b/lib/flipper_format/SConscript @@ -5,8 +5,8 @@ env.Append( "#/lib/flipper_format", ], SDK_HEADERS=[ - File("#/lib/flipper_format/flipper_format.h"), - File("#/lib/flipper_format/flipper_format_i.h"), + File("flipper_format.h"), + File("flipper_format_i.h"), ], ) diff --git a/lib/infrared/SConscript b/lib/infrared/SConscript index 35db75f87..9a1543f00 100644 --- a/lib/infrared/SConscript +++ b/lib/infrared/SConscript @@ -5,6 +5,11 @@ env.Append( "#/lib/infrared/encoder_decoder", "#/lib/infrared/worker", ], + SDK_HEADERS=[ + File("encoder_decoder/infrared.h"), + File("worker/infrared_worker.h"), + File("worker/infrared_transmit.h"), + ], ) diff --git a/lib/lfrfid/SConscript b/lib/lfrfid/SConscript index 6177a9a50..69ea9d3c1 100644 --- a/lib/lfrfid/SConscript +++ b/lib/lfrfid/SConscript @@ -8,12 +8,12 @@ env.Append( "#/lib/lfrfid", ], SDK_HEADERS=[ - File("#/lib/lfrfid/lfrfid_worker.h"), - File("#/lib/lfrfid/lfrfid_raw_worker.h"), - File("#/lib/lfrfid/lfrfid_raw_file.h"), - File("#/lib/lfrfid/lfrfid_dict_file.h"), - File("#/lib/lfrfid/tools/bit_lib.h"), - File("#/lib/lfrfid/protocols/lfrfid_protocols.h"), + File("lfrfid_worker.h"), + File("lfrfid_raw_worker.h"), + File("lfrfid_raw_file.h"), + File("lfrfid_dict_file.h"), + File("tools/bit_lib.h"), + File("protocols/lfrfid_protocols.h"), ], ) diff --git a/lib/libusb_stm32.scons b/lib/libusb_stm32.scons index cb867fdbc..4838b7c50 100644 --- a/lib/libusb_stm32.scons +++ b/lib/libusb_stm32.scons @@ -7,6 +7,10 @@ env.Append( CPPDEFINES=[ ("USB_PMASIZE", "0x400"), ], + SDK_HEADERS=env.GlobRecursive( + "*.h", + Dir("libusb_stm32/inc"), + ), ) diff --git a/lib/mbedtls.scons b/lib/mbedtls.scons index b57221a49..79a4a2520 100644 --- a/lib/mbedtls.scons +++ b/lib/mbedtls.scons @@ -5,6 +5,10 @@ env.Append( "#/lib/mbedtls", "#/lib/mbedtls/include", ], + SDK_HEADERS=[ + File("mbedtls/include/mbedtls/des.h"), + File("mbedtls/include/mbedtls/sha1.h"), + ], ) diff --git a/lib/misc.scons b/lib/misc.scons index b7d8554b5..91ad276a0 100644 --- a/lib/misc.scons +++ b/lib/misc.scons @@ -13,7 +13,7 @@ env.Append( "PB_ENABLE_MALLOC", ], SDK_HEADERS=[ - File("#/lib/micro-ecc/uECC.h"), + File("micro-ecc/uECC.h"), ], ) diff --git a/lib/print/SConscript b/lib/print/SConscript index d4a55ab84..f34c8152f 100644 --- a/lib/print/SConscript +++ b/lib/print/SConscript @@ -98,7 +98,7 @@ for wrapped_fn in wrapped_fn_list: env.Append( SDK_HEADERS=[ - File("#/lib/print/wrappers.h"), + File("wrappers.h"), ], ) diff --git a/lib/subghz/SConscript b/lib/subghz/SConscript index e25d122c8..6d9c0cd06 100644 --- a/lib/subghz/SConscript +++ b/lib/subghz/SConscript @@ -5,18 +5,19 @@ env.Append( "#/lib/subghz", ], SDK_HEADERS=[ - File("#/lib/subghz/environment.h"), - File("#/lib/subghz/receiver.h"), - File("#/lib/subghz/subghz_worker.h"), - File("#/lib/subghz/subghz_tx_rx_worker.h"), - File("#/lib/subghz/transmitter.h"), - File("#/lib/subghz/protocols/raw.h"), - File("#/lib/subghz/blocks/const.h"), - File("#/lib/subghz/blocks/decoder.h"), - File("#/lib/subghz/blocks/encoder.h"), - File("#/lib/subghz/blocks/generic.h"), - File("#/lib/subghz/blocks/math.h"), - File("#/lib/subghz/subghz_setting.h"), + File("environment.h"), + File("receiver.h"), + File("registry.h"), + File("subghz_worker.h"), + File("subghz_tx_rx_worker.h"), + File("transmitter.h"), + File("protocols/raw.h"), + File("blocks/const.h"), + File("blocks/decoder.h"), + File("blocks/encoder.h"), + File("blocks/generic.h"), + File("blocks/math.h"), + File("subghz_setting.h"), ], ) diff --git a/lib/subghz/registry.h b/lib/subghz/registry.h index 062cdf68f..91027807e 100644 --- a/lib/subghz/registry.h +++ b/lib/subghz/registry.h @@ -2,6 +2,10 @@ #include "types.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef struct SubGhzEnvironment SubGhzEnvironment; typedef struct SubGhzProtocolRegistry SubGhzProtocolRegistry; @@ -37,3 +41,7 @@ const SubGhzProtocol* subghz_protocol_registry_get_by_index( * @return Number of protocols */ size_t subghz_protocol_registry_count(const SubGhzProtocolRegistry* protocol_registry); + +#ifdef __cplusplus +} +#endif diff --git a/lib/toolbox/SConscript b/lib/toolbox/SConscript index d631431ee..015a8ed18 100644 --- a/lib/toolbox/SConscript +++ b/lib/toolbox/SConscript @@ -8,23 +8,23 @@ env.Append( "#/lib/toolbox", ], SDK_HEADERS=[ - File("#/lib/toolbox/manchester_decoder.h"), - File("#/lib/toolbox/manchester_encoder.h"), - File("#/lib/toolbox/path.h"), - File("#/lib/toolbox/random_name.h"), - File("#/lib/toolbox/hmac_sha256.h"), - File("#/lib/toolbox/crc32_calc.h"), - File("#/lib/toolbox/dir_walk.h"), - File("#/lib/toolbox/md5.h"), - File("#/lib/toolbox/args.h"), - File("#/lib/toolbox/saved_struct.h"), - File("#/lib/toolbox/version.h"), - File("#/lib/toolbox/tar/tar_archive.h"), - File("#/lib/toolbox/stream/stream.h"), - File("#/lib/toolbox/stream/file_stream.h"), - File("#/lib/toolbox/stream/string_stream.h"), - File("#/lib/toolbox/stream/buffered_file_stream.h"), - File("#/lib/toolbox/protocols/protocol_dict.h"), + File("manchester_decoder.h"), + File("manchester_encoder.h"), + File("path.h"), + File("random_name.h"), + File("hmac_sha256.h"), + File("crc32_calc.h"), + File("dir_walk.h"), + File("md5.h"), + File("args.h"), + File("saved_struct.h"), + File("version.h"), + File("tar/tar_archive.h"), + File("stream/stream.h"), + File("stream/file_stream.h"), + File("stream/string_stream.h"), + File("stream/buffered_file_stream.h"), + File("protocols/protocol_dict.h"), ], ) diff --git a/scripts/fbt/util.py b/scripts/fbt/util.py index baa4ddfee..f5404458e 100644 --- a/scripts/fbt/util.py +++ b/scripts/fbt/util.py @@ -1,11 +1,11 @@ import SCons from SCons.Subst import quote_spaces from SCons.Errors import StopError +from SCons.Node.FS import _my_normcase import re import os -import random -import string + WINPATHSEP_RE = re.compile(r"\\([^\"'\\]|$)") @@ -41,3 +41,14 @@ def link_dir(target_path, source_path, is_windows): def single_quote(arg_list): return " ".join(f"'{arg}'" if " " in arg else str(arg) for arg in arg_list) + + +def extract_abs_dir_path(node): + if isinstance(node, SCons.Node.FS.EntryProxy): + node = node.get() + + for repo_dir in node.get_all_rdirs(): + if os.path.exists(repo_dir.abspath): + return repo_dir.abspath + + raise StopError(f"Can't find absolute path for {node.name}") diff --git a/scripts/fbt_tools/crosscc.py b/scripts/fbt_tools/crosscc.py index aacda58c6..dd5cd5319 100644 --- a/scripts/fbt_tools/crosscc.py +++ b/scripts/fbt_tools/crosscc.py @@ -37,6 +37,21 @@ def _get_tool_version(env, tool): def generate(env, **kw): + if not env.get("VERBOSE", False): + env.SetDefault( + CCCOMSTR="\tCC\t${SOURCE}", + CXXCOMSTR="\tCPP\t${SOURCE}", + ASCOMSTR="\tASM\t${SOURCE}", + ARCOMSTR="\tAR\t${TARGET}", + RANLIBCOMSTR="\tRANLIB\t${TARGET}", + LINKCOMSTR="\tLINK\t${TARGET}", + INSTALLSTR="\tINSTALL\t${TARGET}", + APPSCOMSTR="\tAPPS\t${TARGET}", + VERSIONCOMSTR="\tVERSION\t${TARGET}", + STRIPCOMSTR="\tSTRIP\t${TARGET}", + OBJDUMPCOMSTR="\tOBJDUMP\t${TARGET}", + ) + for orig_tool in (asm, gcc, gxx, ar, gnulink, strip, gdb, objdump): orig_tool.generate(env) env.SetDefault( diff --git a/scripts/fbt_tools/fbt_apps.py b/scripts/fbt_tools/fbt_apps.py index ef5e9b9d9..55e282017 100644 --- a/scripts/fbt_tools/fbt_apps.py +++ b/scripts/fbt_tools/fbt_apps.py @@ -2,7 +2,7 @@ from SCons.Builder import Builder from SCons.Action import Action from SCons.Warnings import warn, WarningOnByDefault import SCons -import os.path +from ansi.color import fg from fbt.appmanifest import ( FlipperAppType, @@ -16,21 +16,20 @@ from fbt.appmanifest import ( # AppBuildset env["APPBUILD"] - contains subset of apps, filtered for current config -def LoadApplicationManifests(env): - appmgr = env["APPMGR"] = AppManager() - for app_dir, _ in env["APPDIRS"]: - app_dir_node = env.Dir("#").Dir(app_dir) +def LoadAppManifest(env, entry): + try: + APP_MANIFEST_NAME = "application.fam" + manifest_glob = entry.glob(APP_MANIFEST_NAME) + if len(manifest_glob) == 0: + raise FlipperManifestException( + f"Folder {entry}: manifest {APP_MANIFEST_NAME} is missing" + ) - for entry in app_dir_node.glob("*", ondisk=True, source=True): - if isinstance(entry, SCons.Node.FS.Dir) and not str(entry).startswith("."): - try: - app_manifest_file_path = os.path.join( - entry.abspath, "application.fam" - ) - appmgr.load_manifest(app_manifest_file_path, entry) - env.Append(PY_LINT_SOURCES=[app_manifest_file_path]) - except FlipperManifestException as e: - warn(WarningOnByDefault, str(e)) + app_manifest_file_path = manifest_glob[0].rfile().abspath + env["APPMGR"].load_manifest(app_manifest_file_path, entry) + env.Append(PY_LINT_SOURCES=[app_manifest_file_path]) + except FlipperManifestException as e: + warn(WarningOnByDefault, str(e)) def PrepareApplicationsBuild(env): @@ -46,12 +45,12 @@ def PrepareApplicationsBuild(env): def DumpApplicationConfig(target, source, env): print(f"Loaded {len(env['APPMGR'].known_apps)} app definitions.") - print("Firmware modules configuration:") + print(fg.boldgreen("Firmware modules configuration:")) for apptype in FlipperAppType: app_sublist = env["APPBUILD"].get_apps_of_type(apptype) if app_sublist: print( - f"{apptype.value}:\n\t", + fg.green(f"{apptype.value}:\n\t"), ", ".join(app.appid for app in app_sublist), ) @@ -65,8 +64,11 @@ def build_apps_c(target, source, env): def generate(env): - env.AddMethod(LoadApplicationManifests) + env.AddMethod(LoadAppManifest) env.AddMethod(PrepareApplicationsBuild) + env.SetDefault( + APPMGR=AppManager(), + ) env.Append( BUILDERS={ diff --git a/scripts/fbt_tools/fbt_assets.py b/scripts/fbt_tools/fbt_assets.py index 4fa5353d0..521c37e90 100644 --- a/scripts/fbt_tools/fbt_assets.py +++ b/scripts/fbt_tools/fbt_assets.py @@ -1,11 +1,10 @@ -import SCons - from SCons.Builder import Builder from SCons.Action import Action -from SCons.Node.FS import File +from SCons.Errors import SConsEnvironmentError import os import subprocess +from ansi.color import fg def icons_emitter(target, source, env): @@ -13,7 +12,6 @@ def icons_emitter(target, source, env): target[0].File(env.subst("${ICON_FILE_NAME}.c")), target[0].File(env.subst("${ICON_FILE_NAME}.h")), ] - source = env.GlobRecursive("*.*", env["ICON_SRC_DIR"]) return target, source @@ -86,7 +84,7 @@ def proto_ver_generator(target, source, env): ) except (subprocess.CalledProcessError, EnvironmentError) as e: # Not great, not terrible - print("Git: fetch failed") + print(fg.boldred("Git: fetch failed")) try: git_describe = _invoke_git( @@ -94,10 +92,8 @@ def proto_ver_generator(target, source, env): source_dir=src_dir, ) except (subprocess.CalledProcessError, EnvironmentError) as e: - print("Git: describe failed") - Exit("git error") + raise SConsEnvironmentError("Git: describe failed") - # print("describe=", git_describe) git_major, git_minor = git_describe.split(".") version_file_data = ( "#pragma once", @@ -116,7 +112,7 @@ def CompileIcons(env, target_dir, source_dir, *, icon_bundle_name="assets_icons" icons = env.IconBuilder( target_dir, - ICON_SRC_DIR=source_dir, + source_dir, ICON_FILE_NAME=icon_bundle_name, ) env.Depends(icons, icons_src) @@ -125,8 +121,8 @@ def CompileIcons(env, target_dir, source_dir, *, icon_bundle_name="assets_icons" def generate(env): env.SetDefault( - ASSETS_COMPILER="${ROOT_DIR.abspath}/scripts/assets.py", - NANOPB_COMPILER="${ROOT_DIR.abspath}/lib/nanopb/generator/nanopb_generator.py", + ASSETS_COMPILER="${FBT_SCRIPT_DIR}/assets.py", + NANOPB_COMPILER="${ROOT_DIR}/lib/nanopb/generator/nanopb_generator.py", ) env.AddMethod(CompileIcons) @@ -143,7 +139,7 @@ def generate(env): BUILDERS={ "IconBuilder": Builder( action=Action( - '${PYTHON3} "${ASSETS_COMPILER}" icons ${ICON_SRC_DIR} ${TARGET.dir} --filename ${ICON_FILE_NAME}', + '${PYTHON3} "${ASSETS_COMPILER}" icons ${ABSPATHGETTERFUNC(SOURCE)} ${TARGET.dir} --filename ${ICON_FILE_NAME}', "${ICONSCOMSTR}", ), emitter=icons_emitter, diff --git a/scripts/fbt_tools/fbt_dist.py b/scripts/fbt_tools/fbt_dist.py index 853013e9f..fb59e5b95 100644 --- a/scripts/fbt_tools/fbt_dist.py +++ b/scripts/fbt_tools/fbt_dist.py @@ -103,7 +103,7 @@ def DistCommand(env, name, source, **kw): command = env.Command( target, source, - '@${PYTHON3} "${ROOT_DIR.abspath}/scripts/sconsdist.py" copy -p ${DIST_PROJECTS} -s "${DIST_SUFFIX}" ${DIST_EXTRA}', + '@${PYTHON3} "${DIST_SCRIPT}" copy -p ${DIST_PROJECTS} -s "${DIST_SUFFIX}" ${DIST_EXTRA}', **kw, ) env.Pseudo(target) @@ -121,6 +121,9 @@ def generate(env): env.SetDefault( COPRO_MCU_FAMILY="STM32WB5x", + SELFUPDATE_SCRIPT="${FBT_SCRIPT_DIR}/selfupdate.py", + DIST_SCRIPT="${FBT_SCRIPT_DIR}/sconsdist.py", + COPRO_ASSETS_SCRIPT="${FBT_SCRIPT_DIR}/assets.py", ) env.Append( @@ -128,7 +131,7 @@ def generate(env): "UsbInstall": Builder( action=[ Action( - '${PYTHON3} "${ROOT_DIR.abspath}/scripts/selfupdate.py" dist/${DIST_DIR}/f${TARGET_HW}-update-${DIST_SUFFIX}/update.fuf' + '${PYTHON3} "${SELFUPDATE_SCRIPT}" dist/${DIST_DIR}/f${TARGET_HW}-update-${DIST_SUFFIX}/update.fuf' ), Touch("${TARGET}"), ] @@ -136,7 +139,7 @@ def generate(env): "CoproBuilder": Builder( action=Action( [ - '${PYTHON3} "${ROOT_DIR.abspath}/scripts/assets.py" ' + '${PYTHON3} "${COPRO_ASSETS_SCRIPT}" ' "copro ${COPRO_CUBE_DIR} " "${TARGET} ${COPRO_MCU_FAMILY} " "--cube_ver=${COPRO_CUBE_VERSION} " diff --git a/scripts/fbt_tools/fbt_extapps.py b/scripts/fbt_tools/fbt_extapps.py index 38c943cc5..fb4dc2f16 100644 --- a/scripts/fbt_tools/fbt_extapps.py +++ b/scripts/fbt_tools/fbt_extapps.py @@ -1,15 +1,18 @@ -import shutil from SCons.Builder import Builder from SCons.Action import Action from SCons.Errors import UserError import SCons.Warnings -import os -import pathlib from fbt.elfmanifest import assemble_manifest_data from fbt.appmanifest import FlipperApplication, FlipperManifestException from fbt.sdk.cache import SdkCache +from fbt.util import extract_abs_dir_path + +import os +import pathlib import itertools +import shutil + from ansi.color import fg @@ -62,7 +65,7 @@ def BuildAppElf(env, app): lib_src_root_path = os.path.join(app_work_dir, "lib", lib_def.name) app_env.AppendUnique( CPPPATH=list( - app_env.Dir(lib_src_root_path).Dir(incpath).srcnode() + app_env.Dir(lib_src_root_path).Dir(incpath).srcnode().rfile().abspath for incpath in lib_def.fap_include_paths ), ) @@ -82,7 +85,12 @@ def BuildAppElf(env, app): *lib_def.cflags, ], CPPDEFINES=lib_def.cdefines, - CPPPATH=list(map(app._appdir.Dir, lib_def.cincludes)), + CPPPATH=list( + map( + lambda cpath: extract_abs_dir_path(app._appdir.Dir(cpath)), + lib_def.cincludes, + ) + ), ) lib = private_lib_env.StaticLibrary( @@ -157,7 +165,6 @@ def prepare_app_metadata(target, source, env): app = env["APP"] meta_file_name = source[0].path + ".meta" with open(meta_file_name, "wb") as f: - # f.write(f"hello this is {app}") f.write( assemble_manifest_data( app_manifest=app, @@ -236,7 +243,10 @@ def fap_dist_action(target, source, env): def generate(env, **kw): - env.SetDefault(EXT_APPS_WORK_DIR=kw.get("EXT_APPS_WORK_DIR")) + env.SetDefault( + EXT_APPS_WORK_DIR=kw.get("EXT_APPS_WORK_DIR"), + APP_RUN_SCRIPT="${FBT_SCRIPT_DIR}/runfap.py", + ) if not env["VERBOSE"]: env.SetDefault( diff --git a/scripts/fbt_tools/fbt_sdk.py b/scripts/fbt_tools/fbt_sdk.py index f1f55bdb8..c46346b65 100644 --- a/scripts/fbt_tools/fbt_sdk.py +++ b/scripts/fbt_tools/fbt_sdk.py @@ -46,7 +46,9 @@ def prebuild_sdk_emitter(target, source, env): def prebuild_sdk_create_origin_file(target, source, env): mega_file = env.subst("${TARGET}.c", target=target[0]) with open(mega_file, "wt") as sdk_c: - sdk_c.write("\n".join(f"#include <{h.path}>" for h in env["SDK_HEADERS"])) + sdk_c.write( + "\n".join(f"#include <{h.srcnode().path}>" for h in env["SDK_HEADERS"]) + ) class SdkMeta: @@ -62,18 +64,25 @@ class SdkMeta: "cc_args": self._wrap_scons_vars("$CCFLAGS $_CCCOMCOM"), "cpp_args": self._wrap_scons_vars("$CXXFLAGS $CCFLAGS $_CCCOMCOM"), "linker_args": self._wrap_scons_vars("$LINKFLAGS"), - "linker_script": self.env.subst("${LINKER_SCRIPT_PATH}"), + "linker_libs": self.env.subst("${LIBS}"), + "app_ep_subst": self.env.subst("${APP_ENTRY}"), + "sdk_path_subst": self.env.subst("${SDK_DIR_SUBST}"), + "hardware": self.env.subst("${TARGET_HW}"), } with open(json_manifest_path, "wt") as f: json.dump(meta_contents, f, indent=4) def _wrap_scons_vars(self, vars: str): - expanded_vars = self.env.subst(vars, target=Entry("dummy")) + expanded_vars = self.env.subst( + vars, + target=Entry("dummy"), + ) return expanded_vars.replace("\\", "/") class SdkTreeBuilder: SDK_DIR_SUBST = "SDK_ROOT_DIR" + SDK_APP_EP_SUBST = "SDK_APP_EP_SUBST" def __init__(self, env, target, source) -> None: self.env = env @@ -87,6 +96,11 @@ class SdkTreeBuilder: self.sdk_root_dir = target[0].Dir(".") self.sdk_deploy_dir = self.sdk_root_dir.Dir(self.target_sdk_dir_name) + self.sdk_env = self.env.Clone( + APP_ENTRY=self.SDK_APP_EP_SUBST, + SDK_DIR_SUBST=self.SDK_DIR_SUBST, + ) + def _parse_sdk_depends(self): deps_file = self.source[0] with open(deps_file.path, "rt") as deps_f: @@ -95,38 +109,36 @@ class SdkTreeBuilder: self.header_depends = list( filter(lambda fname: fname.endswith(".h"), depends.split()), ) - self.header_depends.append(self.env.subst("${LINKER_SCRIPT_PATH}")) - self.header_depends.append(self.env.subst("${SDK_DEFINITION}")) + self.header_depends.append(self.sdk_env.subst("${LINKER_SCRIPT_PATH}")) + self.header_depends.append(self.sdk_env.subst("${SDK_DEFINITION}")) self.header_dirs = sorted( set(map(os.path.normpath, map(os.path.dirname, self.header_depends))) ) def _generate_sdk_meta(self): - filtered_paths = [self.target_sdk_dir_name] + filtered_paths = ["."] full_fw_paths = list( map( os.path.normpath, - (self.env.Dir(inc_dir).relpath for inc_dir in self.env["CPPPATH"]), + ( + self.sdk_env.Dir(inc_dir).relpath + for inc_dir in self.sdk_env["CPPPATH"] + ), ) ) sdk_dirs = ", ".join(f"'{dir}'" for dir in self.header_dirs) filtered_paths.extend( - map( - self.build_sdk_file_path, - filter(lambda path: path in sdk_dirs, full_fw_paths), - ) + filter(lambda path: path in sdk_dirs, full_fw_paths), ) + filtered_paths = list(map(self.build_sdk_file_path, filtered_paths)) - sdk_env = self.env.Clone() - sdk_env.Replace( + self.sdk_env.Replace( CPPPATH=filtered_paths, - LINKER_SCRIPT=self.env.subst("${APP_LINKER_SCRIPT}"), ORIG_LINKER_SCRIPT_PATH=self.env["LINKER_SCRIPT_PATH"], LINKER_SCRIPT_PATH=self.build_sdk_file_path("${ORIG_LINKER_SCRIPT_PATH}"), ) - - meta = SdkMeta(sdk_env, self) + meta = SdkMeta(self.sdk_env, self) meta.save_to(self.target[0].path) def build_sdk_file_path(self, orig_path: str) -> str: @@ -211,7 +223,7 @@ def validate_sdk_cache(source, target, env): current_sdk = SdkCollector() current_sdk.process_source_file_for_sdk(source[0].path) for h in env["SDK_HEADERS"]: - current_sdk.add_header_to_sdk(pathlib.Path(h.path).as_posix()) + current_sdk.add_header_to_sdk(pathlib.Path(h.srcnode().path).as_posix()) sdk_cache = SdkCache(target[0].path) sdk_cache.validate_api(current_sdk.get_api()) diff --git a/scripts/fbt_tools/fbt_version.py b/scripts/fbt_tools/fbt_version.py index 909eea4f3..87497ca5f 100644 --- a/scripts/fbt_tools/fbt_version.py +++ b/scripts/fbt_tools/fbt_version.py @@ -12,11 +12,14 @@ def version_emitter(target, source, env): def generate(env): + env.SetDefault( + VERSION_SCRIPT="${FBT_SCRIPT_DIR}/version.py", + ) env.Append( BUILDERS={ "VersionBuilder": Builder( action=Action( - '${PYTHON3} "${ROOT_DIR.abspath}/scripts/version.py" generate -t ${TARGET_HW} -o ${TARGET.dir.posix} --dir "${ROOT_DIR}"', + '${PYTHON3} "${VERSION_SCRIPT}" generate -t ${TARGET_HW} -o ${TARGET.dir.posix} --dir "${ROOT_DIR}"', "${VERSIONCOMSTR}", ), emitter=version_emitter, diff --git a/scripts/fbt_tools/fwbin.py b/scripts/fbt_tools/fwbin.py index 67e0d6450..f510c2a60 100644 --- a/scripts/fbt_tools/fwbin.py +++ b/scripts/fbt_tools/fwbin.py @@ -8,7 +8,8 @@ __NM_ARM_BIN = "arm-none-eabi-nm" def generate(env): env.SetDefault( - BIN2DFU="${ROOT_DIR.abspath}/scripts/bin2dfu.py", + BIN2DFU="${FBT_SCRIPT_DIR}/bin2dfu.py", + BIN_SIZE_SCRIPT="${FBT_SCRIPT_DIR}/fwsize.py", OBJCOPY=__OBJCOPY_ARM_BIN, # FIXME NM=__NM_ARM_BIN, # FIXME ) diff --git a/scripts/flipper/app.py b/scripts/flipper/app.py index 958356021..30630a5f9 100644 --- a/scripts/flipper/app.py +++ b/scripts/flipper/app.py @@ -1,6 +1,7 @@ import logging import argparse import sys +import colorlog class App: @@ -10,7 +11,7 @@ class App: self.parser = argparse.ArgumentParser() self.parser.add_argument("-d", "--debug", action="store_true", help="Debug") # Logging - self.logger = logging.getLogger() + self.logger = colorlog.getLogger() # Application specific initialization self.init() @@ -21,10 +22,17 @@ class App: self.log_level = logging.DEBUG if self.args.debug else logging.INFO self.logger.setLevel(self.log_level) if not self.logger.hasHandlers(): - self.handler = logging.StreamHandler(sys.stdout) + self.handler = colorlog.StreamHandler(sys.stdout) self.handler.setLevel(self.log_level) - self.formatter = logging.Formatter( - "%(asctime)s [%(levelname)s] %(message)s" + self.formatter = colorlog.ColoredFormatter( + "%(log_color)s%(asctime)s [%(levelname)s] %(message)s", + log_colors={ + "DEBUG": "cyan", + # "INFO": "white", + "WARNING": "yellow", + "ERROR": "red", + "CRITICAL": "red,bg_white", + }, ) self.handler.setFormatter(self.formatter) self.logger.addHandler(self.handler) diff --git a/scripts/sconsdist.py b/scripts/sconsdist.py index 7636c87bb..b8f1d72b2 100644 --- a/scripts/sconsdist.py +++ b/scripts/sconsdist.py @@ -131,7 +131,9 @@ class Main(App): self.copy_single_project(project) self.logger.info( - fg.green(f"Firmware binaries can be found at:\n\t{self.output_dir_path}") + fg.boldgreen( + f"Firmware binaries can be found at:\n\t{self.output_dir_path}" + ) ) if self.args.version: @@ -167,7 +169,7 @@ class Main(App): if (bundle_result := UpdateMain(no_exit=True)(bundle_args)) == 0: self.logger.info( - fg.green( + fg.boldgreen( f"Use this directory to self-update your Flipper:\n\t{bundle_dir}" ) ) diff --git a/scripts/testing/await_flipper.py b/scripts/testing/await_flipper.py old mode 100644 new mode 100755 diff --git a/scripts/testing/units.py b/scripts/testing/units.py old mode 100644 new mode 100755 diff --git a/scripts/toolchain/fbtenv.cmd b/scripts/toolchain/fbtenv.cmd index a11a3ccd5..6e87bf95a 100644 --- a/scripts/toolchain/fbtenv.cmd +++ b/scripts/toolchain/fbtenv.cmd @@ -13,19 +13,22 @@ if not [%FBT_NOENV%] == [] ( exit /b 0 ) -set "FLIPPER_TOOLCHAIN_VERSION=16" -set "FBT_TOOLCHAIN_ROOT=%FBT_ROOT%\toolchain\x86_64-windows" +set "FLIPPER_TOOLCHAIN_VERSION=17" +if [%FBT_TOOLCHAIN_ROOT%] == [] ( + set "FBT_TOOLCHAIN_ROOT=%FBT_ROOT%\toolchain\x86_64-windows" +) if not exist "%FBT_TOOLCHAIN_ROOT%" ( - powershell -ExecutionPolicy Bypass -File "%FBT_ROOT%\scripts\toolchain\windows-toolchain-download.ps1" "%flipper_toolchain_version%" + powershell -ExecutionPolicy Bypass -File "%FBT_ROOT%\scripts\toolchain\windows-toolchain-download.ps1" "%flipper_toolchain_version%" "%FBT_TOOLCHAIN_ROOT%" ) if not exist "%FBT_TOOLCHAIN_ROOT%\VERSION" ( - powershell -ExecutionPolicy Bypass -File "%FBT_ROOT%\scripts\toolchain\windows-toolchain-download.ps1" "%flipper_toolchain_version%" + powershell -ExecutionPolicy Bypass -File "%FBT_ROOT%\scripts\toolchain\windows-toolchain-download.ps1" "%flipper_toolchain_version%" "%FBT_TOOLCHAIN_ROOT%" ) + set /p REAL_TOOLCHAIN_VERSION=<"%FBT_TOOLCHAIN_ROOT%\VERSION" if not "%REAL_TOOLCHAIN_VERSION%" == "%FLIPPER_TOOLCHAIN_VERSION%" ( - powershell -ExecutionPolicy Bypass -File "%FBT_ROOT%\scripts\toolchain\windows-toolchain-download.ps1" "%flipper_toolchain_version%" + powershell -ExecutionPolicy Bypass -File "%FBT_ROOT%\scripts\toolchain\windows-toolchain-download.ps1" "%flipper_toolchain_version%" "%FBT_TOOLCHAIN_ROOT%" ) diff --git a/scripts/toolchain/fbtenv.sh b/scripts/toolchain/fbtenv.sh index 15f29e4dc..d3fdb8cea 100755 --- a/scripts/toolchain/fbtenv.sh +++ b/scripts/toolchain/fbtenv.sh @@ -5,7 +5,7 @@ # public variables DEFAULT_SCRIPT_PATH="$(pwd -P)"; SCRIPT_PATH="${SCRIPT_PATH:-$DEFAULT_SCRIPT_PATH}"; -FBT_TOOLCHAIN_VERSION="${FBT_TOOLCHAIN_VERSION:-"16"}"; +FBT_TOOLCHAIN_VERSION="${FBT_TOOLCHAIN_VERSION:-"17"}"; FBT_TOOLCHAIN_PATH="${FBT_TOOLCHAIN_PATH:-$SCRIPT_PATH}"; fbtenv_show_usage() @@ -62,7 +62,7 @@ fbtenv_check_sourced() fbtenv_show_usage; return 1; fi - case ${0##*/} in dash|-dash|bash|-bash|ksh|-ksh|sh|-sh|*.sh|fbt) + case ${0##*/} in dash|-dash|bash|-bash|ksh|-ksh|sh|-sh|*.sh|fbt|ufbt) return 0;; esac fbtenv_show_usage; @@ -76,8 +76,8 @@ fbtenv_chck_many_source() return 0; fi fi - echo "Warning! FBT environment script sourced more than once!"; - echo "This may signal that you are making mistakes, please open a new shell!"; + echo "Warning! FBT environment script was sourced more than once!"; + echo "You might be doing things wrong, please open a new shell!"; return 1; } @@ -93,8 +93,8 @@ fbtenv_set_shell_prompt() fbtenv_check_script_path() { - if [ ! -x "$SCRIPT_PATH/fbt" ]; then - echo "Please source this script being into flipperzero-firmware root directory, or specify 'SCRIPT_PATH' manually"; + if [ ! -x "$SCRIPT_PATH/fbt" ] && [ ! -x "$SCRIPT_PATH/ufbt" ] ; then + echo "Please source this script from [u]fbt root directory, or specify 'SCRIPT_PATH' variable manually"; echo "Example:"; printf "\tSCRIPT_PATH=lang/c/flipperzero-firmware source lang/c/flipperzero-firmware/scripts/fbtenv.sh\n"; echo "If current directory is right, type 'unset SCRIPT_PATH' and try again" @@ -108,7 +108,7 @@ fbtenv_get_kernel_type() SYS_TYPE="$(uname -s)"; ARCH_TYPE="$(uname -m)"; if [ "$ARCH_TYPE" != "x86_64" ] && [ "$SYS_TYPE" != "Darwin" ]; then - echo "Now we provide toolchain only for x86_64 arhitecture, sorry.."; + echo "We only provide toolchain for x86_64 CPUs, sorry.."; return 1; fi if [ "$SYS_TYPE" = "Darwin" ]; then @@ -119,10 +119,10 @@ fbtenv_get_kernel_type() TOOLCHAIN_ARCH_DIR="$FBT_TOOLCHAIN_PATH/toolchain/x86_64-linux"; TOOLCHAIN_URL="https://update.flipperzero.one/builds/toolchain/gcc-arm-none-eabi-10.3-x86_64-linux-flipper-$FBT_TOOLCHAIN_VERSION.tar.gz"; elif echo "$SYS_TYPE" | grep -q "MINGW"; then - echo "In MinGW shell use \"fbt.cmd\" instead of \"fbt\""; + echo "In MinGW shell use \"[u]fbt.cmd\" instead of \"[u]fbt\""; return 1; else - echo "Your system is not recognized. Sorry.. Please report us your configuration."; + echo "Your system configuration is not supported. Sorry.. Please report us your configuration."; return 1; fi return 0; @@ -142,7 +142,7 @@ fbtenv_check_rosetta() fbtenv_check_tar() { - printf "Checking tar.."; + printf "Checking for tar.."; if ! tar --version > /dev/null 2>&1; then echo "no"; return 1; @@ -153,7 +153,7 @@ fbtenv_check_tar() fbtenv_check_downloaded_toolchain() { - printf "Checking downloaded toolchain tgz.."; + printf "Checking if downloaded toolchain tgz exists.."; if [ ! -f "$FBT_TOOLCHAIN_PATH/toolchain/$TOOLCHAIN_TAR" ]; then echo "no"; return 1; @@ -204,7 +204,7 @@ fbtenv_unpack_toolchain() fbtenv_clearing() { - printf "Clearing.."; + printf "Cleaning up.."; if [ -n "${FBT_TOOLCHAIN_PATH:-""}" ]; then rm -rf "${FBT_TOOLCHAIN_PATH:?}/toolchain/"*.tar.gz; rm -rf "${FBT_TOOLCHAIN_PATH:?}/toolchain/"*.part; diff --git a/scripts/toolchain/windows-toolchain-download.ps1 b/scripts/toolchain/windows-toolchain-download.ps1 index aaed89856..c96bb119c 100644 --- a/scripts/toolchain/windows-toolchain-download.ps1 +++ b/scripts/toolchain/windows-toolchain-download.ps1 @@ -1,34 +1,46 @@ Set-StrictMode -Version 2.0 $ErrorActionPreference = "Stop" [Net.ServicePointManager]::SecurityProtocol = "tls12, tls11, tls" -$repo_root = (Get-Item "$PSScriptRoot\..\..").FullName +# TODO: fix +$download_dir = (Get-Item "$PSScriptRoot\..\..").FullName $toolchain_version = $args[0] -$toolchain_url = "https://update.flipperzero.one/builds/toolchain/gcc-arm-none-eabi-10.3-x86_64-windows-flipper-$toolchain_version.zip" -$toolchain_zip = "gcc-arm-none-eabi-10.3-x86_64-windows-flipper-$toolchain_version.zip" -$toolchain_dir = "gcc-arm-none-eabi-10.3-x86_64-windows-flipper" +$toolchain_target_path = $args[1] -if (Test-Path -LiteralPath "$repo_root\toolchain\x86_64-windows") { +$toolchain_url = "https://update.flipperzero.one/builds/toolchain/gcc-arm-none-eabi-10.3-x86_64-windows-flipper-$toolchain_version.zip" +$toolchain_dist_folder = "gcc-arm-none-eabi-10.3-x86_64-windows-flipper" +$toolchain_zip = "$toolchain_dist_folder-$toolchain_version.zip" + +$toolchain_zip_temp_path = "$download_dir\$toolchain_zip" +$toolchain_dist_temp_path = "$download_dir\$toolchain_dist_folder" + +if (Test-Path -LiteralPath "$toolchain_target_path") { Write-Host -NoNewline "Removing old Windows toolchain.." - Remove-Item -LiteralPath "$repo_root\toolchain\x86_64-windows" -Force -Recurse + Remove-Item -LiteralPath "$toolchain_target_path" -Force -Recurse Write-Host "done!" } -if (!(Test-Path -Path "$repo_root\$toolchain_zip" -PathType Leaf)) { +if (!(Test-Path -Path "$toolchain_zip_temp_path" -PathType Leaf)) { Write-Host -NoNewline "Downloading Windows toolchain.." $wc = New-Object net.webclient - $wc.Downloadfile("$toolchain_url", "$repo_root\$toolchain_zip") + $wc.Downloadfile("$toolchain_url", "$toolchain_zip_temp_path") Write-Host "done!" } -if (!(Test-Path -LiteralPath "$repo_root\toolchain")) { - New-Item "$repo_root\toolchain" -ItemType Directory +if (!(Test-Path -LiteralPath "$toolchain_target_path\..")) { + New-Item "$toolchain_target_path\.." -ItemType Directory -Force } Write-Host -NoNewline "Extracting Windows toolchain.." +# This is faster than Expand-Archive Add-Type -Assembly "System.IO.Compression.Filesystem" -[System.IO.Compression.ZipFile]::ExtractToDirectory("$repo_root\$toolchain_zip", "$repo_root\") -Move-Item -Path "$repo_root\$toolchain_dir" -Destination "$repo_root\toolchain\x86_64-windows" +[System.IO.Compression.ZipFile]::ExtractToDirectory("$toolchain_zip_temp_path", "$download_dir") +# Expand-Archive -LiteralPath "$toolchain_zip_temp_path" -DestinationPath "$download_dir" + +Write-Host -NoNewline "moving.." +Move-Item -LiteralPath "$toolchain_dist_temp_path" -Destination "$toolchain_target_path" Write-Host "done!" Write-Host -NoNewline "Cleaning up temporary files.." -Remove-Item -LiteralPath "$repo_root\$toolchain_zip" -Force +Remove-Item -LiteralPath "$toolchain_zip_temp_path" -Force Write-Host "done!" + +# dasdasd \ No newline at end of file diff --git a/site_scons/cc.scons b/site_scons/cc.scons index c923b3872..1eb6a3376 100644 --- a/site_scons/cc.scons +++ b/site_scons/cc.scons @@ -30,10 +30,9 @@ ENV.AppendUnique( "-ffunction-sections", "-fsingle-precision-constant", "-fno-math-errno", - "-fstack-usage", + # Generates .su files with stack usage information + # "-fstack-usage", "-g", - # "-Wno-stringop-overread", - # "-Wno-stringop-overflow", ], CPPDEFINES=[ "_GNU_SOURCE", diff --git a/site_scons/environ.scons b/site_scons/environ.scons index 94705dada..96424caad 100644 --- a/site_scons/environ.scons +++ b/site_scons/environ.scons @@ -1,5 +1,10 @@ from SCons.Platform import TempFileMunge -from fbt.util import tempfile_arg_esc_func, single_quote, wrap_tempfile +from fbt.util import ( + tempfile_arg_esc_func, + single_quote, + wrap_tempfile, + extract_abs_dir_path, +) import os import multiprocessing @@ -52,6 +57,12 @@ coreenv = VAR_ENV.Clone( MAXLINELENGTH=2048, PROGSUFFIX=".elf", ENV=forward_os_env, + SINGLEQUOTEFUNC=single_quote, + ABSPATHGETTERFUNC=extract_abs_dir_path, + # Setting up temp file parameters - to overcome command line length limits + TEMPFILEARGESCFUNC=tempfile_arg_esc_func, + FBT_SCRIPT_DIR=Dir("#/scripts"), + ROOT_DIR=Dir("#"), ) # If DIST_SUFFIX is set in environment, is has precedence (set by CI) @@ -60,24 +71,6 @@ if os_suffix := os.environ.get("DIST_SUFFIX", None): DIST_SUFFIX=os_suffix, ) -# print(coreenv.Dump()) -if not coreenv["VERBOSE"]: - coreenv.SetDefault( - CCCOMSTR="\tCC\t${SOURCE}", - CXXCOMSTR="\tCPP\t${SOURCE}", - ASCOMSTR="\tASM\t${SOURCE}", - ARCOMSTR="\tAR\t${TARGET}", - RANLIBCOMSTR="\tRANLIB\t${TARGET}", - LINKCOMSTR="\tLINK\t${TARGET}", - INSTALLSTR="\tINSTALL\t${TARGET}", - APPSCOMSTR="\tAPPS\t${TARGET}", - VERSIONCOMSTR="\tVERSION\t${TARGET}", - STRIPCOMSTR="\tSTRIP\t${TARGET}", - OBJDUMPCOMSTR="\tOBJDUMP\t${TARGET}", - # GDBCOMSTR="\tGDB\t${SOURCE}", - # GDBPYCOMSTR="\tGDB-PY\t${SOURCE}", - ) - # Default value for commandline options SetOption("num_jobs", multiprocessing.cpu_count()) @@ -90,12 +83,7 @@ SetOption("max_drift", 1) # Random task queue - to discover isses with build logic faster # SetOption("random", 1) - -# Setting up temp file parameters - to overcome command line length limits -coreenv["TEMPFILEARGESCFUNC"] = tempfile_arg_esc_func wrap_tempfile(coreenv, "LINKCOM") wrap_tempfile(coreenv, "ARCOM") -coreenv["SINGLEQUOTEFUNC"] = single_quote - Return("coreenv") diff --git a/site_scons/extapps.scons b/site_scons/extapps.scons index 90d228e58..bb1d65ffc 100644 --- a/site_scons/extapps.scons +++ b/site_scons/extapps.scons @@ -3,10 +3,9 @@ from SCons.Errors import UserError Import("ENV") - from fbt.appmanifest import FlipperAppType -appenv = ENV.Clone( +appenv = ENV["APPENV"] = ENV.Clone( tools=[ ( "fbt_extapps", @@ -17,6 +16,7 @@ appenv = ENV.Clone( }, ), "fbt_assets", + "fbt_sdk", ] ) @@ -66,6 +66,7 @@ extapps = appenv["_extapps"] = { "validators": {}, "dist": {}, "resources_dist": None, + "sdk_tree": None, } @@ -115,10 +116,41 @@ if appsrc := appenv.subst("$APPSRC"): app_manifest, fap_file, app_validator = appenv.GetExtAppFromPath(appsrc) appenv.PhonyTarget( "launch_app", - '${PYTHON3} scripts/runfap.py ${SOURCE} --fap_dst_dir "/ext/apps/${FAP_CATEGORY}"', + '${PYTHON3} "${APP_RUN_SCRIPT}" ${SOURCE} --fap_dst_dir "/ext/apps/${FAP_CATEGORY}"', source=fap_file, FAP_CATEGORY=app_manifest.fap_category, ) appenv.Alias("launch_app", app_validator) +# SDK management + +sdk_origin_path = "${BUILD_DIR}/sdk_origin" +sdk_source = appenv.SDKPrebuilder( + sdk_origin_path, + # Deps on root SDK headers and generated files + (appenv["SDK_HEADERS"], appenv["FW_ASSETS_HEADERS"]), +) +# Extra deps on headers included in deeper levels +Depends(sdk_source, appenv.ProcessSdkDepends(f"{sdk_origin_path}.d")) + +appenv["SDK_DIR"] = appenv.Dir("${BUILD_DIR}/sdk") +sdk_tree = extapps["sdk_tree"] = appenv.SDKTree(appenv["SDK_DIR"], sdk_origin_path) +# AlwaysBuild(sdk_tree) +Alias("sdk_tree", sdk_tree) + +sdk_apicheck = appenv.SDKSymUpdater(appenv["SDK_DEFINITION"], sdk_origin_path) +Precious(sdk_apicheck) +NoClean(sdk_apicheck) +AlwaysBuild(sdk_apicheck) +Alias("sdk_check", sdk_apicheck) + +sdk_apisyms = appenv.SDKSymGenerator( + "${BUILD_DIR}/assets/compiled/symbols.h", appenv["SDK_DEFINITION"] +) +Alias("api_syms", sdk_apisyms) + +if appenv["FORCE"]: + appenv.AlwaysBuild(sdk_source, sdk_tree, sdk_apicheck, sdk_apisyms) + + Return("extapps") From a09d0a8bd42d727fe4b686b761cb8012dc99703a Mon Sep 17 00:00:00 2001 From: Konstantin Volkov <72250702+doomwastaken@users.noreply.github.com> Date: Wed, 2 Nov 2022 18:21:43 +0300 Subject: [PATCH 09/23] fixed job name, renamed compile step id (#1952) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: あく --- .github/workflows/unit_tests.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml index a7671f0f9..1ca4a9c03 100644 --- a/.github/workflows/unit_tests.yml +++ b/.github/workflows/unit_tests.yml @@ -8,7 +8,7 @@ env: DEFAULT_TARGET: f7 jobs: - main: + run_units_on_test_bench: runs-on: [self-hosted, FlipperZeroTest] steps: - name: Checkout code @@ -22,14 +22,14 @@ jobs: run: | echo "flipper=/dev/ttyACM0" >> $GITHUB_OUTPUT - - name: 'Compile unit tests firmware' - id: compile + - name: 'Flash unit tests firmware' + id: flashing run: | FBT_TOOLCHAIN_PATH=/opt ./fbt flash OPENOCD_ADAPTER_SERIAL=2A0906016415303030303032 FIRMWARE_APP_SET=unit_tests FORCE=1 - name: 'Wait for flipper to finish updating' id: connect - if: steps.compile.outcome == 'success' + if: steps.flashing.outcome == 'success' run: | . scripts/toolchain/fbtenv.sh ./scripts/testing/await_flipper.py ${{steps.device.outputs.flipper}} From c417d467f72b63b25f7dce0eee6b3554fd2d8d0d Mon Sep 17 00:00:00 2001 From: Georgii Surkov <37121527+gsurkov@users.noreply.github.com> Date: Wed, 2 Nov 2022 19:13:06 +0300 Subject: [PATCH 10/23] Handle storage full error (#1958) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: あく --- applications/services/rpc/rpc_storage.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/applications/services/rpc/rpc_storage.c b/applications/services/rpc/rpc_storage.c index 1b545b414..e28998e13 100644 --- a/applications/services/rpc/rpc_storage.c +++ b/applications/services/rpc/rpc_storage.c @@ -405,6 +405,10 @@ static void rpc_system_storage_write_process(const PB_Main* request, void* conte if(!fs_operation_success) { send_response = true; command_status = rpc_system_storage_get_file_error(file); + if(command_status == PB_CommandStatus_OK) { + // Report errors not handled by underlying APIs + command_status = PB_CommandStatus_ERROR_STORAGE_INTERNAL; + } } if(send_response) { From 0652830c51cee5fced1d4651c538d24160599dfa Mon Sep 17 00:00:00 2001 From: Skorpionm <85568270+Skorpionm@users.noreply.github.com> Date: Wed, 2 Nov 2022 20:24:07 +0400 Subject: [PATCH 11/23] [FL-2940] WS: add protocol Ambient_Weather (#1960) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * WS: add protocol Ambient_Weather * WS: fix link * WS: removing unused code Co-authored-by: あく --- .../helpers/weather_station_types.h | 2 +- .../protocols/acurite_592txr.c | 2 +- .../protocols/ambient_weather.c | 278 ++++++++++++++++++ .../protocols/ambient_weather.h | 79 +++++ .../weather_station/protocols/gt_wt_03.c | 2 +- .../protocols/lacrosse_tx141thbv2.c | 2 +- .../weather_station/protocols/nexus_th.c | 2 +- .../protocols/protocol_items.c | 1 + .../protocols/protocol_items.h | 1 + 9 files changed, 364 insertions(+), 5 deletions(-) create mode 100644 applications/plugins/weather_station/protocols/ambient_weather.c create mode 100644 applications/plugins/weather_station/protocols/ambient_weather.h diff --git a/applications/plugins/weather_station/helpers/weather_station_types.h b/applications/plugins/weather_station/helpers/weather_station_types.h index 2976cbce8..5a66dd0ce 100644 --- a/applications/plugins/weather_station/helpers/weather_station_types.h +++ b/applications/plugins/weather_station/helpers/weather_station_types.h @@ -3,7 +3,7 @@ #include #include -#define WS_VERSION_APP "0.3.1" +#define WS_VERSION_APP "0.4" #define WS_DEVELOPED "SkorP" #define WS_GITHUB "https://github.com/flipperdevices/flipperzero-firmware" diff --git a/applications/plugins/weather_station/protocols/acurite_592txr.c b/applications/plugins/weather_station/protocols/acurite_592txr.c index db05af095..4d7f59544 100644 --- a/applications/plugins/weather_station/protocols/acurite_592txr.c +++ b/applications/plugins/weather_station/protocols/acurite_592txr.c @@ -4,7 +4,7 @@ /* * Help - * https://github.com/merbanan/rtl_433/blob/5bef4e43133ac4c0e2d18d36f87c52b4f9458453/src/devices/acurite.c + * https://github.com/merbanan/rtl_433/blob/master/src/devices/acurite.c * * Acurite 592TXR Temperature Humidity sensor decoder * Message Type 0x04, 7 bytes diff --git a/applications/plugins/weather_station/protocols/ambient_weather.c b/applications/plugins/weather_station/protocols/ambient_weather.c new file mode 100644 index 000000000..07f5330fc --- /dev/null +++ b/applications/plugins/weather_station/protocols/ambient_weather.c @@ -0,0 +1,278 @@ +#include "ambient_weather.h" +#include + +#define TAG "WSProtocolAmbient_Weather" + +/* + * Help + * https://github.com/merbanan/rtl_433/blob/master/src/devices/ambient_weather.c + * + * Decode Ambient Weather F007TH, F012TH, TF 30.3208.02, SwitchDoc F016TH. + * Devices supported: + * - Ambient Weather F007TH Thermo-Hygrometer. + * - Ambient Weather F012TH Indoor/Display Thermo-Hygrometer. + * - TFA senders 30.3208.02 from the TFA "Klima-Monitor" 30.3054, + * - SwitchDoc Labs F016TH. + * This decoder handles the 433mhz/868mhz thermo-hygrometers. + * The 915mhz (WH*) family of devices use different modulation/encoding. + * Byte 0 Byte 1 Byte 2 Byte 3 Byte 4 Byte 5 + * xxxxMMMM IIIIIIII BCCCTTTT TTTTTTTT HHHHHHHH MMMMMMMM + * - x: Unknown 0x04 on F007TH/F012TH + * - M: Model Number?, 0x05 on F007TH/F012TH/SwitchDocLabs F016TH + * - I: ID byte (8 bits), volatie, changes at power up, + * - B: Battery Low + * - C: Channel (3 bits 1-8) - F007TH set by Dip switch, F012TH soft setting + * - T: Temperature 12 bits - Fahrenheit * 10 + 400 + * - H: Humidity (8 bits) + * - M: Message integrity check LFSR Digest-8, gen 0x98, key 0x3e, init 0x64 + * + * three repeats without gap + * full preamble is 0x00145 (the last bits might not be fixed, e.g. 0x00146) + * and on decoding also 0xffd45 + */ + +#define AMBIENT_WEATHER_PACKET_HEADER_1 0xFFD440000000000 //0xffd45 .. 0xffd46 +#define AMBIENT_WEATHER_PACKET_HEADER_2 0x001440000000000 //0x00145 .. 0x00146 +#define AMBIENT_WEATHER_PACKET_HEADER_MASK 0xFFFFC0000000000 + +static const SubGhzBlockConst ws_protocol_ambient_weather_const = { + .te_short = 500, + .te_long = 1000, + .te_delta = 120, + .min_count_bit_for_found = 48, +}; + +struct WSProtocolDecoderAmbient_Weather { + SubGhzProtocolDecoderBase base; + + SubGhzBlockDecoder decoder; + WSBlockGeneric generic; + ManchesterState manchester_saved_state; + uint16_t header_count; +}; + +struct WSProtocolEncoderAmbient_Weather { + SubGhzProtocolEncoderBase base; + + SubGhzProtocolBlockEncoder encoder; + WSBlockGeneric generic; +}; + +const SubGhzProtocolDecoder ws_protocol_ambient_weather_decoder = { + .alloc = ws_protocol_decoder_ambient_weather_alloc, + .free = ws_protocol_decoder_ambient_weather_free, + + .feed = ws_protocol_decoder_ambient_weather_feed, + .reset = ws_protocol_decoder_ambient_weather_reset, + + .get_hash_data = ws_protocol_decoder_ambient_weather_get_hash_data, + .serialize = ws_protocol_decoder_ambient_weather_serialize, + .deserialize = ws_protocol_decoder_ambient_weather_deserialize, + .get_string = ws_protocol_decoder_ambient_weather_get_string, +}; + +const SubGhzProtocolEncoder ws_protocol_ambient_weather_encoder = { + .alloc = NULL, + .free = NULL, + + .deserialize = NULL, + .stop = NULL, + .yield = NULL, +}; + +const SubGhzProtocol ws_protocol_ambient_weather = { + .name = WS_PROTOCOL_AMBIENT_WEATHER_NAME, + .type = SubGhzProtocolWeatherStation, + .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 | + SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable, + + .decoder = &ws_protocol_ambient_weather_decoder, + .encoder = &ws_protocol_ambient_weather_encoder, +}; + +void* ws_protocol_decoder_ambient_weather_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); + WSProtocolDecoderAmbient_Weather* instance = malloc(sizeof(WSProtocolDecoderAmbient_Weather)); + instance->base.protocol = &ws_protocol_ambient_weather; + instance->generic.protocol_name = instance->base.protocol->name; + return instance; +} + +void ws_protocol_decoder_ambient_weather_free(void* context) { + furi_assert(context); + WSProtocolDecoderAmbient_Weather* instance = context; + free(instance); +} + +void ws_protocol_decoder_ambient_weather_reset(void* context) { + furi_assert(context); + WSProtocolDecoderAmbient_Weather* instance = context; + manchester_advance( + instance->manchester_saved_state, + ManchesterEventReset, + &instance->manchester_saved_state, + NULL); +} + +static bool ws_protocol_ambient_weather_check_crc(WSProtocolDecoderAmbient_Weather* instance) { + uint8_t msg[] = { + instance->decoder.decode_data >> 40, + instance->decoder.decode_data >> 32, + instance->decoder.decode_data >> 24, + instance->decoder.decode_data >> 16, + instance->decoder.decode_data >> 8}; + + uint8_t crc = subghz_protocol_blocks_lfsr_digest8(msg, 5, 0x98, 0x3e) ^ 0x64; + return (crc == (uint8_t)(instance->decoder.decode_data & 0xFF)); +} + +/** + * Analysis of received data + * @param instance Pointer to a WSBlockGeneric* instance + */ +static void ws_protocol_ambient_weather_remote_controller(WSBlockGeneric* instance) { + instance->id = (instance->data >> 32) & 0xFF; + instance->battery_low = (instance->data >> 31) & 1; + instance->channel = ((instance->data >> 28) & 0x07) + 1; + instance->temp = ws_block_generic_fahrenheit_to_celsius( + ((float)((instance->data >> 16) & 0x0FFF) - 400.0f) / 10.0f); + instance->humidity = (instance->data >> 8) & 0xFF; + instance->btn = WS_NO_BTN; + + // ToDo maybe it won't be needed + /* + Sanity checks to reduce false positives and other bad data + Packets with Bad data often pass the MIC check. + - humidity > 100 (such as 255) and + - temperatures > 140 F (such as 369.5 F and 348.8 F + Specs in the F007TH and F012TH manuals state the range is: + - Temperature: -40 to 140 F + - Humidity: 10 to 99% + @todo - sanity check b[0] "model number" + - 0x45 - F007TH and F012TH + - 0x?5 - SwitchDocLabs F016TH temperature sensor (based on comment b[0] & 0x0f == 5) + - ? - TFA 30.3208.02 + if (instance->humidity < 0 || instance->humidity > 100) { + ERROR; + } + + if (instance->temp < -40.0 || instance->temp > 140.0) { + ERROR; + } + */ +} + +void ws_protocol_decoder_ambient_weather_feed(void* context, bool level, uint32_t duration) { + furi_assert(context); + WSProtocolDecoderAmbient_Weather* instance = context; + + ManchesterEvent event = ManchesterEventReset; + if(!level) { + if(DURATION_DIFF(duration, ws_protocol_ambient_weather_const.te_short) < + ws_protocol_ambient_weather_const.te_delta) { + event = ManchesterEventShortLow; + } else if( + DURATION_DIFF(duration, ws_protocol_ambient_weather_const.te_long) < + ws_protocol_ambient_weather_const.te_delta * 2) { + event = ManchesterEventLongLow; + } + } else { + if(DURATION_DIFF(duration, ws_protocol_ambient_weather_const.te_short) < + ws_protocol_ambient_weather_const.te_delta) { + event = ManchesterEventShortHigh; + } else if( + DURATION_DIFF(duration, ws_protocol_ambient_weather_const.te_long) < + ws_protocol_ambient_weather_const.te_delta * 2) { + event = ManchesterEventLongHigh; + } + } + if(event != ManchesterEventReset) { + bool data; + bool data_ok = manchester_advance( + instance->manchester_saved_state, event, &instance->manchester_saved_state, &data); + + if(data_ok) { + instance->decoder.decode_data = (instance->decoder.decode_data << 1) | !data; + } + + if(((instance->decoder.decode_data & AMBIENT_WEATHER_PACKET_HEADER_MASK) == + AMBIENT_WEATHER_PACKET_HEADER_1) || + ((instance->decoder.decode_data & AMBIENT_WEATHER_PACKET_HEADER_MASK) == + AMBIENT_WEATHER_PACKET_HEADER_2)) { + if(ws_protocol_ambient_weather_check_crc(instance)) { + instance->decoder.decode_data = instance->decoder.decode_data; + instance->generic.data = instance->decoder.decode_data; + instance->generic.data_count_bit = + ws_protocol_ambient_weather_const.min_count_bit_for_found; + ws_protocol_ambient_weather_remote_controller(&instance->generic); + if(instance->base.callback) + instance->base.callback(&instance->base, instance->base.context); + instance->decoder.decode_data = 0; + instance->decoder.decode_count_bit = 0; + } + } + } else { + instance->decoder.decode_data = 0; + instance->decoder.decode_count_bit = 0; + manchester_advance( + instance->manchester_saved_state, + ManchesterEventReset, + &instance->manchester_saved_state, + NULL); + } +} + +uint8_t ws_protocol_decoder_ambient_weather_get_hash_data(void* context) { + furi_assert(context); + WSProtocolDecoderAmbient_Weather* instance = context; + return subghz_protocol_blocks_get_hash_data( + &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); +} + +bool ws_protocol_decoder_ambient_weather_serialize( + void* context, + FlipperFormat* flipper_format, + SubGhzRadioPreset* preset) { + furi_assert(context); + WSProtocolDecoderAmbient_Weather* instance = context; + return ws_block_generic_serialize(&instance->generic, flipper_format, preset); +} + +bool ws_protocol_decoder_ambient_weather_deserialize(void* context, FlipperFormat* flipper_format) { + furi_assert(context); + WSProtocolDecoderAmbient_Weather* instance = context; + bool ret = false; + do { + if(!ws_block_generic_deserialize(&instance->generic, flipper_format)) { + break; + } + if(instance->generic.data_count_bit != + ws_protocol_ambient_weather_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } + ret = true; + } while(false); + return ret; +} + +void ws_protocol_decoder_ambient_weather_get_string(void* context, FuriString* output) { + furi_assert(context); + WSProtocolDecoderAmbient_Weather* instance = context; + furi_string_printf( + output, + "%s %dbit\r\n" + "Key:0x%lX%08lX\r\n" + "Sn:0x%lX Ch:%d Bat:%d\r\n" + "Temp:%d.%d C Hum:%d%%", + instance->generic.protocol_name, + instance->generic.data_count_bit, + (uint32_t)(instance->generic.data >> 32), + (uint32_t)(instance->generic.data), + instance->generic.id, + instance->generic.channel, + instance->generic.battery_low, + (int16_t)instance->generic.temp, + abs(((int16_t)(instance->generic.temp * 10) - (((int16_t)instance->generic.temp) * 10))), + instance->generic.humidity); +} diff --git a/applications/plugins/weather_station/protocols/ambient_weather.h b/applications/plugins/weather_station/protocols/ambient_weather.h new file mode 100644 index 000000000..04cc5819c --- /dev/null +++ b/applications/plugins/weather_station/protocols/ambient_weather.h @@ -0,0 +1,79 @@ +#pragma once + +#include + +#include +#include +#include +#include "ws_generic.h" +#include + +#define WS_PROTOCOL_AMBIENT_WEATHER_NAME "Ambient_Weather" + +typedef struct WSProtocolDecoderAmbient_Weather WSProtocolDecoderAmbient_Weather; +typedef struct WSProtocolEncoderAmbient_Weather WSProtocolEncoderAmbient_Weather; + +extern const SubGhzProtocolDecoder ws_protocol_ambient_weather_decoder; +extern const SubGhzProtocolEncoder ws_protocol_ambient_weather_encoder; +extern const SubGhzProtocol ws_protocol_ambient_weather; + +/** + * Allocate WSProtocolDecoderAmbient_Weather. + * @param environment Pointer to a SubGhzEnvironment instance + * @return WSProtocolDecoderAmbient_Weather* pointer to a WSProtocolDecoderAmbient_Weather instance + */ +void* ws_protocol_decoder_ambient_weather_alloc(SubGhzEnvironment* environment); + +/** + * Free WSProtocolDecoderAmbient_Weather. + * @param context Pointer to a WSProtocolDecoderAmbient_Weather instance + */ +void ws_protocol_decoder_ambient_weather_free(void* context); + +/** + * Reset decoder WSProtocolDecoderAmbient_Weather. + * @param context Pointer to a WSProtocolDecoderAmbient_Weather instance + */ +void ws_protocol_decoder_ambient_weather_reset(void* context); + +/** + * Parse a raw sequence of levels and durations received from the air. + * @param context Pointer to a WSProtocolDecoderAmbient_Weather instance + * @param level Signal level true-high false-low + * @param duration Duration of this level in, us + */ +void ws_protocol_decoder_ambient_weather_feed(void* context, bool level, uint32_t duration); + +/** + * Getting the hash sum of the last randomly received parcel. + * @param context Pointer to a WSProtocolDecoderAmbient_Weather instance + * @return hash Hash sum + */ +uint8_t ws_protocol_decoder_ambient_weather_get_hash_data(void* context); + +/** + * Serialize data WSProtocolDecoderAmbient_Weather. + * @param context Pointer to a WSProtocolDecoderAmbient_Weather instance + * @param flipper_format Pointer to a FlipperFormat instance + * @param preset The modulation on which the signal was received, SubGhzRadioPreset + * @return true On success + */ +bool ws_protocol_decoder_ambient_weather_serialize( + void* context, + FlipperFormat* flipper_format, + SubGhzRadioPreset* preset); + +/** + * Deserialize data WSProtocolDecoderAmbient_Weather. + * @param context Pointer to a WSProtocolDecoderAmbient_Weather instance + * @param flipper_format Pointer to a FlipperFormat instance + * @return true On success + */ +bool ws_protocol_decoder_ambient_weather_deserialize(void* context, FlipperFormat* flipper_format); + +/** + * Getting a textual representation of the received data. + * @param context Pointer to a WSProtocolDecoderAmbient_Weather instance + * @param output Resulting text + */ +void ws_protocol_decoder_ambient_weather_get_string(void* context, FuriString* output); diff --git a/applications/plugins/weather_station/protocols/gt_wt_03.c b/applications/plugins/weather_station/protocols/gt_wt_03.c index 1492374c9..04bca9ac1 100644 --- a/applications/plugins/weather_station/protocols/gt_wt_03.c +++ b/applications/plugins/weather_station/protocols/gt_wt_03.c @@ -4,7 +4,7 @@ /* * Help - * https://github.com/merbanan/rtl_433/blob/5f0ff6db624270a4598958ab9dd79bb385ced3ef/src/devices/gt_wt_03.c + * https://github.com/merbanan/rtl_433/blob/master/src/devices/gt_wt_03.c * * * Globaltronics GT-WT-03 sensor on 433.92MHz. diff --git a/applications/plugins/weather_station/protocols/lacrosse_tx141thbv2.c b/applications/plugins/weather_station/protocols/lacrosse_tx141thbv2.c index 828d49be7..d4b89be87 100644 --- a/applications/plugins/weather_station/protocols/lacrosse_tx141thbv2.c +++ b/applications/plugins/weather_station/protocols/lacrosse_tx141thbv2.c @@ -4,7 +4,7 @@ /* * Help - * https://github.com/merbanan/rtl_433/blob/7e83cfd27d14247b6c3c81732bfe4a4f9a974d30/src/devices/lacrosse_tx141x.c + * https://github.com/merbanan/rtl_433/blob/master/src/devices/lacrosse_tx141x.c * * iiii iiii | bkcc tttt | tttt tttt | hhhh hhhh | cccc cccc | u * - i: identification; changes on battery switch diff --git a/applications/plugins/weather_station/protocols/nexus_th.c b/applications/plugins/weather_station/protocols/nexus_th.c index a2ab0f412..c3d823eda 100644 --- a/applications/plugins/weather_station/protocols/nexus_th.c +++ b/applications/plugins/weather_station/protocols/nexus_th.c @@ -4,7 +4,7 @@ /* * Help - * https://github.com/merbanan/rtl_433/blob/ef2d37cf51e3264d11cde9149ef87de2f0a4d37a/src/devices/nexus.c + * https://github.com/merbanan/rtl_433/blob/master/src/devices/nexus.c * * Nexus sensor protocol with ID, temperature and optional humidity * also FreeTec (Pearl) NC-7345 sensors for FreeTec Weatherstation NC-7344, diff --git a/applications/plugins/weather_station/protocols/protocol_items.c b/applications/plugins/weather_station/protocols/protocol_items.c index 3ec9e995a..d7f6458ab 100644 --- a/applications/plugins/weather_station/protocols/protocol_items.c +++ b/applications/plugins/weather_station/protocols/protocol_items.c @@ -9,6 +9,7 @@ const SubGhzProtocol* weather_station_protocol_registry_items[] = { &ws_protocol_lacrosse_tx141thbv2, &ws_protocol_oregon2, &ws_protocol_acurite_592txr, + &ws_protocol_ambient_weather, }; const SubGhzProtocolRegistry weather_station_protocol_registry = { diff --git a/applications/plugins/weather_station/protocols/protocol_items.h b/applications/plugins/weather_station/protocols/protocol_items.h index 8f3eb53d7..76c085ab4 100644 --- a/applications/plugins/weather_station/protocols/protocol_items.h +++ b/applications/plugins/weather_station/protocols/protocol_items.h @@ -9,5 +9,6 @@ #include "lacrosse_tx141thbv2.h" #include "oregon2.h" #include "acurite_592txr.h" +#include "ambient_weather.h" extern const SubGhzProtocolRegistry weather_station_protocol_registry; From 9c4612e571db42f5e6123a3f159e01337453a6af Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Wed, 2 Nov 2022 22:18:08 +0300 Subject: [PATCH 12/23] Plugins: New AM2320 Sensor plugin --- .../am2320_temp_sensor/application.fam | 14 + .../am2320_temp_sensor/temperature_sensor.c | 336 ++++++++++++++++++ .../temperature_sensor.png | Bin .../Readme.md | 0 .../application.fam | 2 +- .../docs/App.png | Bin .../docs/Connection.png | Bin .../docs/Flipper.png | Bin .../temperature_sensor.c | 0 .../htu21d_temp_sensor/temperature_sensor.png | Bin 0 -> 181 bytes 10 files changed, 351 insertions(+), 1 deletion(-) create mode 100644 applications/plugins/am2320_temp_sensor/application.fam create mode 100644 applications/plugins/am2320_temp_sensor/temperature_sensor.c rename applications/plugins/{temperature_sensor => am2320_temp_sensor}/temperature_sensor.png (100%) rename applications/plugins/{temperature_sensor => htu21d_temp_sensor}/Readme.md (100%) rename applications/plugins/{temperature_sensor => htu21d_temp_sensor}/application.fam (89%) rename applications/plugins/{temperature_sensor => htu21d_temp_sensor}/docs/App.png (100%) rename applications/plugins/{temperature_sensor => htu21d_temp_sensor}/docs/Connection.png (100%) rename applications/plugins/{temperature_sensor => htu21d_temp_sensor}/docs/Flipper.png (100%) rename applications/plugins/{temperature_sensor => htu21d_temp_sensor}/temperature_sensor.c (100%) create mode 100644 applications/plugins/htu21d_temp_sensor/temperature_sensor.png diff --git a/applications/plugins/am2320_temp_sensor/application.fam b/applications/plugins/am2320_temp_sensor/application.fam new file mode 100644 index 000000000..cd4afdc4a --- /dev/null +++ b/applications/plugins/am2320_temp_sensor/application.fam @@ -0,0 +1,14 @@ +App( + appid="am2320_temp_sensor", + name="[AM2320] Temp. Sensor", + apptype=FlipperAppType.EXTERNAL, + entry_point="temperature_sensor_app", + cdefines=["APP_TEMPERATURE_SENSOR"], + requires=[ + "gui", + ], + stack_size=2 * 1024, + order=90, + fap_icon="temperature_sensor.png", + fap_category="GPIO", +) diff --git a/applications/plugins/am2320_temp_sensor/temperature_sensor.c b/applications/plugins/am2320_temp_sensor/temperature_sensor.c new file mode 100644 index 000000000..236c5e2d2 --- /dev/null +++ b/applications/plugins/am2320_temp_sensor/temperature_sensor.c @@ -0,0 +1,336 @@ +/* Flipper Plugin to read the values from a AM2320/AM2321 Sensor */ +/* Created by @xMasterX, original app (was used as template) by Mywk - https://github.com/Mywk */ +/* Lib used as reference: https://github.com/Gozem/am2320/blob/master/am2321.c*/ +#include +#include +#include +#include + +#include +#include + +#include + +#include + +#define TS_DEFAULT_VALUE 0xFFFF + +#define AM2320_ADDRESS (0x5C << 1) + +#define DATA_BUFFER_SIZE 8 + +// External I2C BUS +#define I2C_BUS &furi_hal_i2c_handle_external + +typedef enum { + TSSInitializing, + TSSNoSensor, + TSSPendingUpdate, +} TSStatus; + +typedef enum { + TSEventTypeTick, + TSEventTypeInput, +} TSEventType; + +typedef struct { + TSEventType type; + InputEvent input; +} TSEvent; + +extern const NotificationSequence sequence_blink_red_100; +extern const NotificationSequence sequence_blink_blue_100; + +static TSStatus temperature_sensor_current_status = TSSInitializing; + +// Temperature and Humidity data buffers, ready to print +char ts_data_buffer_temperature_c[DATA_BUFFER_SIZE]; +char ts_data_buffer_temperature_f[DATA_BUFFER_SIZE]; +char ts_data_buffer_relative_humidity[DATA_BUFFER_SIZE]; +char ts_data_buffer_absolute_humidity[DATA_BUFFER_SIZE]; + +// CRC16 calculation +static uint16_t get_crc16(const uint8_t* buf, size_t len) { + uint16_t crc = 0xFFFF; + + while(len--) { + crc ^= (uint16_t)*buf++; + for(unsigned i = 0; i < 8; i++) { + if(crc & 0x0001) { + crc >>= 1; + crc ^= 0xA001; + } else { + crc >>= 1; + } + } + } + + return crc; +} +// Combine bytes +static uint16_t combine_bytes(uint8_t msb, uint8_t lsb) { + return ((uint16_t)msb << 8) | (uint16_t)lsb; +} + +// Executes an I2C wake up, sends command and reads result +// true if fetch was successful, false otherwise +static bool temperature_sensor_get_data(uint8_t* buffer, uint8_t size) { + uint32_t timeout = furi_ms_to_ticks(100); + uint8_t cmdbuffer[3] = {0, 0, 0}; + bool ret = false; + + // Aquire I2C bus + furi_hal_i2c_acquire(I2C_BUS); + + // Wake UP AM2320 (sensor goes to sleep to not warm up and affect the humidity sensor) + furi_hal_i2c_is_device_ready(I2C_BUS, (uint8_t)AM2320_ADDRESS, timeout); + // Check if device woken up then we do next stuff + if(furi_hal_i2c_is_device_ready(I2C_BUS, (uint8_t)AM2320_ADDRESS, timeout)) { + // Wait a bit + furi_delay_us(1000); + + // Prepare command: Addr 0x03, start register = 0x00, number of registers to read = 0x04 + cmdbuffer[0] = 0x03; + cmdbuffer[1] = 0x00; + cmdbuffer[2] = 0x04; + + // Transmit command to read registers + ret = furi_hal_i2c_tx(I2C_BUS, (uint8_t)AM2320_ADDRESS, cmdbuffer, 3, timeout); + + // Wait a bit + furi_delay_us(1600); + if(ret) { + /* + * Read out 8 bytes of data + * Byte 0: Should be Modbus function code 0x03 + * Byte 1: Should be number of registers to read (0x04) + * Byte 2: Humidity msb + * Byte 3: Humidity lsb + * Byte 4: Temperature msb + * Byte 5: Temperature lsb + * Byte 6: CRC lsb byte + * Byte 7: CRC msb byte + */ + ret = furi_hal_i2c_rx(I2C_BUS, (uint8_t)AM2320_ADDRESS, buffer, size, timeout); + } + } + // Release i2c bus + furi_hal_i2c_release(I2C_BUS); + + return ret; +} + +// Fetches temperature and humidity from sensor +// Temperature and humidity must be preallocated +// true if fetch was successful, false otherwise +static bool temperature_sensor_fetch_info(double* temperature, double* humidity) { + *humidity = (float)0; + bool ret = false; + + uint8_t buffer[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + + // Fetch data from sensor + ret = temperature_sensor_get_data(buffer, 8); + + // If we got no result + if(!ret) return false; + + if(buffer[0] != 0x03) return false; // must be 0x03 modbus reply + if(buffer[1] != 0x04) return false; // must be 0x04 number of registers reply + + // Check CRC16 sum, if not correct - return false + uint16_t crcdata = get_crc16(buffer, 6); + uint16_t crcread = combine_bytes(buffer[7], buffer[6]); + if(crcdata != crcread) return false; + + // Combine bytes for temp and humidity + uint16_t temp16 = combine_bytes(buffer[4], buffer[5]); + uint16_t humi16 = combine_bytes(buffer[2], buffer[3]); + + /* Temperature resolution is 16Bit, + * temperature highest bit (Bit15) is equal to 1 indicates a + * negative temperature, the temperature highest bit (Bit15) + * is equal to 0 indicates a positive temperature; + * temperature in addition to the most significant bit (Bit14 ~ Bit0) + * indicates the temperature sensor string value. + * Temperature sensor value is a string of 10 times the + * actual temperature value. + */ + if(temp16 & 0x8000) { + temp16 = -(temp16 & 0x7FFF); + } + + // Prepare output data + *temperature = (float)temp16 / 10.0; + *humidity = (float)humi16 / 10.0; + + return true; +} + +// Draw callback + +static void temperature_sensor_draw_callback(Canvas* canvas, void* ctx) { + UNUSED(ctx); + + canvas_clear(canvas); + canvas_set_font(canvas, FontPrimary); + canvas_draw_str(canvas, 2, 10, "AM2320/AM2321 Sensor"); + + canvas_set_font(canvas, FontSecondary); + canvas_draw_str(canvas, 2, 62, "Press back to exit."); + + switch(temperature_sensor_current_status) { + case TSSInitializing: + canvas_draw_str(canvas, 2, 30, "Initializing.."); + break; + case TSSNoSensor: + canvas_draw_str(canvas, 2, 30, "No sensor found!"); + break; + case TSSPendingUpdate: { + canvas_draw_str(canvas, 3, 24, "Temperature"); + canvas_draw_str(canvas, 68, 24, "Humidity"); + + // Draw vertical lines + canvas_draw_line(canvas, 61, 16, 61, 50); + canvas_draw_line(canvas, 62, 16, 62, 50); + + // Draw horizontal line + canvas_draw_line(canvas, 2, 27, 122, 27); + + // Draw temperature and humidity values + canvas_draw_str(canvas, 8, 38, ts_data_buffer_temperature_c); + canvas_draw_str(canvas, 42, 38, "C"); + canvas_draw_str(canvas, 8, 48, ts_data_buffer_temperature_f); + canvas_draw_str(canvas, 42, 48, "F"); + canvas_draw_str(canvas, 68, 38, ts_data_buffer_relative_humidity); + canvas_draw_str(canvas, 100, 38, "%"); + canvas_draw_str(canvas, 68, 48, ts_data_buffer_absolute_humidity); + canvas_draw_str(canvas, 100, 48, "g/m3"); + + } break; + default: + break; + } +} + +// Input callback + +static void temperature_sensor_input_callback(InputEvent* input_event, void* ctx) { + furi_assert(ctx); + FuriMessageQueue* event_queue = ctx; + + TSEvent event = {.type = TSEventTypeInput, .input = *input_event}; + furi_message_queue_put(event_queue, &event, FuriWaitForever); +} + +// Timer callback + +static void temperature_sensor_timer_callback(FuriMessageQueue* event_queue) { + furi_assert(event_queue); + + TSEvent event = {.type = TSEventTypeTick}; + furi_message_queue_put(event_queue, &event, 0); +} + +// App entry point + +int32_t temperature_sensor_app(void* p) { + UNUSED(p); + + furi_hal_power_suppress_charge_enter(); + // Declare our variables and assign variables a default value + TSEvent tsEvent; + bool sensorFound = false; + double celsius, fahrenheit, rel_humidity, abs_humidity = TS_DEFAULT_VALUE; + + // Used for absolute humidity calculation + double vapour_pressure = 0; + + FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(TSEvent)); + + // Register callbacks + ViewPort* view_port = view_port_alloc(); + view_port_draw_callback_set(view_port, temperature_sensor_draw_callback, NULL); + view_port_input_callback_set(view_port, temperature_sensor_input_callback, event_queue); + + // Create timer and register its callback + FuriTimer* timer = + furi_timer_alloc(temperature_sensor_timer_callback, FuriTimerTypePeriodic, event_queue); + furi_timer_start(timer, furi_kernel_get_tick_frequency()); + + // Register viewport + Gui* gui = furi_record_open(RECORD_GUI); + gui_add_view_port(gui, view_port, GuiLayerFullscreen); + + // Used to notify the user by blinking red (error) or blue (fetch successful) + NotificationApp* notifications = furi_record_open(RECORD_NOTIFICATION); + + while(1) { + furi_check(furi_message_queue_get(event_queue, &tsEvent, FuriWaitForever) == FuriStatusOk); + + // Handle events + if(tsEvent.type == TSEventTypeInput) { + // Exit on back key + if(tsEvent.input.key == + InputKeyBack) // We dont check for type here, we can check the type of keypress like: (event.input.type == InputTypeShort) + break; + + } else if(tsEvent.type == TSEventTypeTick) { + // Update sensor data + // Fetch data and set the sensor current status accordingly + sensorFound = temperature_sensor_fetch_info(&celsius, &rel_humidity); + temperature_sensor_current_status = (sensorFound ? TSSPendingUpdate : TSSNoSensor); + + if(sensorFound) { + // Blink blue + notification_message(notifications, &sequence_blink_blue_100); + + if(celsius != TS_DEFAULT_VALUE && rel_humidity != TS_DEFAULT_VALUE) { + // Convert celsius to fahrenheit + fahrenheit = (celsius * 9 / 5) + 32; + + // Calculate absolute humidity - For more info refer to https://github.com/Mywk/FlipperTemperatureSensor/issues/1 + // Calculate saturation vapour pressure first + vapour_pressure = + (double)6.11 * + pow(10, (double)(((double)7.5 * celsius) / ((double)237.3 + celsius))); + // Then the vapour pressure in Pa + vapour_pressure = vapour_pressure * rel_humidity; + // Calculate absolute humidity + abs_humidity = + (double)2.16679 * (double)(vapour_pressure / ((double)273.15 + celsius)); + + // Fill our buffers here, not on the canvas draw callback + snprintf(ts_data_buffer_temperature_c, DATA_BUFFER_SIZE, "%.2f", celsius); + snprintf(ts_data_buffer_temperature_f, DATA_BUFFER_SIZE, "%.2f", fahrenheit); + snprintf( + ts_data_buffer_relative_humidity, DATA_BUFFER_SIZE, "%.2f", rel_humidity); + snprintf( + ts_data_buffer_absolute_humidity, DATA_BUFFER_SIZE, "%.2f", abs_humidity); + } + + } else { + // Reset our variables to their default values + celsius = fahrenheit = rel_humidity = abs_humidity = TS_DEFAULT_VALUE; + + // Blink red + notification_message(notifications, &sequence_blink_red_100); + } + } + + uint32_t wait_ticks = furi_ms_to_ticks(!sensorFound ? 100 : 500); + furi_delay_tick(wait_ticks); + } + + furi_hal_power_suppress_charge_exit(); + // Dobby is freee (free our variables, Flipper will crash if we don't do this!) + furi_timer_free(timer); + gui_remove_view_port(gui, view_port); + view_port_free(view_port); + furi_message_queue_free(event_queue); + + furi_record_close(RECORD_NOTIFICATION); + furi_record_close(RECORD_GUI); + + return 0; +} diff --git a/applications/plugins/temperature_sensor/temperature_sensor.png b/applications/plugins/am2320_temp_sensor/temperature_sensor.png similarity index 100% rename from applications/plugins/temperature_sensor/temperature_sensor.png rename to applications/plugins/am2320_temp_sensor/temperature_sensor.png diff --git a/applications/plugins/temperature_sensor/Readme.md b/applications/plugins/htu21d_temp_sensor/Readme.md similarity index 100% rename from applications/plugins/temperature_sensor/Readme.md rename to applications/plugins/htu21d_temp_sensor/Readme.md diff --git a/applications/plugins/temperature_sensor/application.fam b/applications/plugins/htu21d_temp_sensor/application.fam similarity index 89% rename from applications/plugins/temperature_sensor/application.fam rename to applications/plugins/htu21d_temp_sensor/application.fam index f465c5c93..b3101f42e 100644 --- a/applications/plugins/temperature_sensor/application.fam +++ b/applications/plugins/htu21d_temp_sensor/application.fam @@ -1,6 +1,6 @@ App( appid="temperature_sensor", - name="[HTU21D] Temp Sensor", + name="[HTU21D] Temp. Sensor", apptype=FlipperAppType.EXTERNAL, entry_point="temperature_sensor_app", cdefines=["APP_TEMPERATURE_SENSOR"], diff --git a/applications/plugins/temperature_sensor/docs/App.png b/applications/plugins/htu21d_temp_sensor/docs/App.png similarity index 100% rename from applications/plugins/temperature_sensor/docs/App.png rename to applications/plugins/htu21d_temp_sensor/docs/App.png diff --git a/applications/plugins/temperature_sensor/docs/Connection.png b/applications/plugins/htu21d_temp_sensor/docs/Connection.png similarity index 100% rename from applications/plugins/temperature_sensor/docs/Connection.png rename to applications/plugins/htu21d_temp_sensor/docs/Connection.png diff --git a/applications/plugins/temperature_sensor/docs/Flipper.png b/applications/plugins/htu21d_temp_sensor/docs/Flipper.png similarity index 100% rename from applications/plugins/temperature_sensor/docs/Flipper.png rename to applications/plugins/htu21d_temp_sensor/docs/Flipper.png diff --git a/applications/plugins/temperature_sensor/temperature_sensor.c b/applications/plugins/htu21d_temp_sensor/temperature_sensor.c similarity index 100% rename from applications/plugins/temperature_sensor/temperature_sensor.c rename to applications/plugins/htu21d_temp_sensor/temperature_sensor.c diff --git a/applications/plugins/htu21d_temp_sensor/temperature_sensor.png b/applications/plugins/htu21d_temp_sensor/temperature_sensor.png new file mode 100644 index 0000000000000000000000000000000000000000..b6fe6d7feb1fa91f43ea3ce545bf3056f0f8a4b8 GIT binary patch literal 181 zcmeAS@N?(olHy`uVBq!ia0vp^AT}2V8<6ZZI=>f4F%}28J29*~C-V}>VM%xNb!1@J z*w6hZkrl}2EbxddW?X?_wfUrhf?l33jv*SsQ~MdY7!){|xBmaXbJmiR8&)uH zEaAIqH<2lH>YXg@Xy%9c9e?=GOkB=*{m{gR2NzH1OsFVdQ&MBb@0O^W43IG5A literal 0 HcmV?d00001 From e1f5999095d176334b7a3625da811670dac5182b Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Wed, 2 Nov 2022 22:54:44 +0300 Subject: [PATCH 13/23] update lib paths --- lib/SConscript | 2 +- lib/STM32CubeWB.scons | 4 ++-- lib/drivers/SConscript | 2 +- lib/subghz/SConscript | 28 ++++++++++++++-------------- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/lib/SConscript b/lib/SConscript index f0d672053..57cfb3f3a 100644 --- a/lib/SConscript +++ b/lib/SConscript @@ -23,7 +23,7 @@ env.Append( File("one_wire/one_wire_device.h"), File("one_wire/ibutton/ibutton_worker.h"), File("one_wire/maxim_crc.h"), - File("#/lib/u8g2/u8g2.h"), + File("u8g2/u8g2.h"), ], ) diff --git a/lib/STM32CubeWB.scons b/lib/STM32CubeWB.scons index a00b07d98..cbdde9814 100644 --- a/lib/STM32CubeWB.scons +++ b/lib/STM32CubeWB.scons @@ -15,8 +15,8 @@ env.Append( ], SDK_HEADERS=[ *env.GlobRecursive("*_ll_*.h", "#/lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/", exclude="*usb.h"), - File("#/lib/STM32CubeWB/Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h"), - File("#/lib/STM32CubeWB/Middlewares/Third_Party/FreeRTOS/Source/include/stream_buffer.h"), + File("STM32CubeWB/Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h"), + File("STM32CubeWB/Middlewares/Third_Party/FreeRTOS/Source/include/stream_buffer.h"), ], ) diff --git a/lib/drivers/SConscript b/lib/drivers/SConscript index 1ca613289..18b96a0ed 100644 --- a/lib/drivers/SConscript +++ b/lib/drivers/SConscript @@ -5,7 +5,7 @@ env.Append( "#/lib/drivers", ], SDK_HEADERS=[ - File("#/lib/drivers/nrf24.h"), + File("drivers/nrf24.h"), ], ) diff --git a/lib/subghz/SConscript b/lib/subghz/SConscript index 39c04969b..d0a663a50 100644 --- a/lib/subghz/SConscript +++ b/lib/subghz/SConscript @@ -5,20 +5,20 @@ env.Append( "#/lib/subghz", ], SDK_HEADERS=[ - File("#/lib/subghz/environment.h"), - File("#/lib/subghz/receiver.h"), - File("#/lib/subghz/subghz_worker.h"), - File("#/lib/subghz/subghz_tx_rx_worker.h"), - File("#/lib/subghz/transmitter.h"), - File("#/lib/subghz/registry.h"), - File("#/lib/subghz/protocols/protocol_items.h"), - File("#/lib/subghz/protocols/raw.h"), - File("#/lib/subghz/blocks/const.h"), - File("#/lib/subghz/blocks/decoder.h"), - File("#/lib/subghz/blocks/encoder.h"), - File("#/lib/subghz/blocks/generic.h"), - File("#/lib/subghz/blocks/math.h"), - File("#/lib/subghz/subghz_setting.h"), + File("subghz/environment.h"), + File("subghz/receiver.h"), + File("subghz/subghz_worker.h"), + File("subghz/subghz_tx_rx_worker.h"), + File("subghz/transmitter.h"), + File("subghz/registry.h"), + File("subghz/protocols/protocol_items.h"), + File("subghz/protocols/raw.h"), + File("subghz/blocks/const.h"), + File("subghz/blocks/decoder.h"), + File("subghz/blocks/encoder.h"), + File("subghz/blocks/generic.h"), + File("subghz/blocks/math.h"), + File("subghz/subghz_setting.h"), ], ) From c8bc9e26e0522e93737aa94f2df324fc0da306b2 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Wed, 2 Nov 2022 23:07:00 +0300 Subject: [PATCH 14/23] Fix part 1 --- applications/main/clock_app/clock_app.c | 2 ++ applications/main/unirfremix/unirfremix_app.c | 4 +++ .../plugins/dht_temp_sensor/quenon_dht_mon.c | 2 ++ .../scene/flipfrid_scene_entrypoint.c | 2 ++ .../scene/flipfrid_scene_load_custom_uids.c | 2 ++ .../flipfrid/scene/flipfrid_scene_load_file.c | 2 ++ .../scene/flipfrid_scene_run_attack.c | 2 ++ .../scene/flipfrid_scene_select_field.c | 2 ++ applications/plugins/hc_sr04/hc_sr04.c | 2 ++ applications/plugins/metronome/metronome.c | 6 ++++ .../spectrum_analyzer/spectrum_analyzer.c | 2 ++ .../plugins/tetris_game/tetris_game.c | 2 ++ lib/drivers/SConscript | 2 +- lib/subghz/SConscript | 28 +++++++++---------- 14 files changed, 45 insertions(+), 15 deletions(-) diff --git a/applications/main/clock_app/clock_app.c b/applications/main/clock_app/clock_app.c index 1bd92d9ec..c5b4dd9e8 100644 --- a/applications/main/clock_app/clock_app.c +++ b/applications/main/clock_app/clock_app.c @@ -216,6 +216,8 @@ int32_t clock_app(void* p) { // Exit the plugin processing = false; break; + default: + break; } } } /*else if(event.type == EventTypeTick) { diff --git a/applications/main/unirfremix/unirfremix_app.c b/applications/main/unirfremix/unirfremix_app.c index 0ed42da7b..af231a80a 100644 --- a/applications/main/unirfremix/unirfremix_app.c +++ b/applications/main/unirfremix/unirfremix_app.c @@ -1044,6 +1044,8 @@ int32_t unirfremix_app(void* p) { unirfremix_tx_stop(app); exit_loop = true; break; + default: + break; } if(app->processing == 0) { @@ -1115,6 +1117,8 @@ int32_t unirfremix_app(void* p) { case InputKeyBack: exit_loop = true; break; + default: + break; } if(exit_loop == true) { diff --git a/applications/plugins/dht_temp_sensor/quenon_dht_mon.c b/applications/plugins/dht_temp_sensor/quenon_dht_mon.c index bbb91ec3d..4084a351c 100644 --- a/applications/plugins/dht_temp_sensor/quenon_dht_mon.c +++ b/applications/plugins/dht_temp_sensor/quenon_dht_mon.c @@ -442,6 +442,8 @@ int32_t quenon_dht_mon_app() { case InputKeyBack: processing = false; break; + default: + break; } } } diff --git a/applications/plugins/flipfrid/scene/flipfrid_scene_entrypoint.c b/applications/plugins/flipfrid/scene/flipfrid_scene_entrypoint.c index 3a1ce4951..1ac91625f 100644 --- a/applications/plugins/flipfrid/scene/flipfrid_scene_entrypoint.c +++ b/applications/plugins/flipfrid/scene/flipfrid_scene_entrypoint.c @@ -134,6 +134,8 @@ void flipfrid_scene_entrypoint_on_event(FlipFridEvent event, FlipFridState* cont case InputKeyBack: context->is_running = false; break; + default: + break; } } } diff --git a/applications/plugins/flipfrid/scene/flipfrid_scene_load_custom_uids.c b/applications/plugins/flipfrid/scene/flipfrid_scene_load_custom_uids.c index cc9e9871d..9130b2d92 100644 --- a/applications/plugins/flipfrid/scene/flipfrid_scene_load_custom_uids.c +++ b/applications/plugins/flipfrid/scene/flipfrid_scene_load_custom_uids.c @@ -71,6 +71,8 @@ void flipfrid_scene_load_custom_uids_on_event(FlipFridEvent event, FlipFridState case InputKeyBack: context->current_scene = SceneEntryPoint; break; + default: + break; } } } diff --git a/applications/plugins/flipfrid/scene/flipfrid_scene_load_file.c b/applications/plugins/flipfrid/scene/flipfrid_scene_load_file.c index 76864018b..b2e27fc9a 100644 --- a/applications/plugins/flipfrid/scene/flipfrid_scene_load_file.c +++ b/applications/plugins/flipfrid/scene/flipfrid_scene_load_file.c @@ -158,6 +158,8 @@ void flipfrid_scene_load_file_on_event(FlipFridEvent event, FlipFridState* conte case InputKeyBack: context->current_scene = SceneEntryPoint; break; + default: + break; } } } diff --git a/applications/plugins/flipfrid/scene/flipfrid_scene_run_attack.c b/applications/plugins/flipfrid/scene/flipfrid_scene_run_attack.c index 3baa4ea49..c2f1a77ca 100644 --- a/applications/plugins/flipfrid/scene/flipfrid_scene_run_attack.c +++ b/applications/plugins/flipfrid/scene/flipfrid_scene_run_attack.c @@ -546,6 +546,8 @@ void flipfrid_scene_run_attack_on_event(FlipFridEvent event, FlipFridState* cont notification_message(context->notify, &sequence_blink_stop); context->current_scene = SceneEntryPoint; break; + default: + break; } } } diff --git a/applications/plugins/flipfrid/scene/flipfrid_scene_select_field.c b/applications/plugins/flipfrid/scene/flipfrid_scene_select_field.c index 79416d616..ccb49e910 100644 --- a/applications/plugins/flipfrid/scene/flipfrid_scene_select_field.c +++ b/applications/plugins/flipfrid/scene/flipfrid_scene_select_field.c @@ -129,6 +129,8 @@ void flipfrid_scene_select_field_on_event(FlipFridEvent event, FlipFridState* co furi_string_reset(context->notification_msg); context->current_scene = SceneSelectFile; break; + default: + break; } FURI_LOG_D(TAG, "Position: %d/%d", context->key_index, nb_bytes); } diff --git a/applications/plugins/hc_sr04/hc_sr04.c b/applications/plugins/hc_sr04/hc_sr04.c index 911e92dc6..dbbf4f3ec 100644 --- a/applications/plugins/hc_sr04/hc_sr04.c +++ b/applications/plugins/hc_sr04/hc_sr04.c @@ -230,6 +230,8 @@ int32_t hc_sr04_app() { case InputKeyBack: processing = false; break; + default: + break; } } } diff --git a/applications/plugins/metronome/metronome.c b/applications/plugins/metronome/metronome.c index e0770f2f8..0afa15a36 100644 --- a/applications/plugins/metronome/metronome.c +++ b/applications/plugins/metronome/metronome.c @@ -318,6 +318,8 @@ int32_t metronome_app() { case InputKeyBack: processing = false; break; + default: + break; } } else if(event.input.type == InputTypeLong) { // hold events @@ -338,6 +340,8 @@ int32_t metronome_app() { case InputKeyBack: processing = false; break; + default: + break; } } else if(event.input.type == InputTypeRepeat) { // repeat events @@ -357,6 +361,8 @@ int32_t metronome_app() { case InputKeyBack: processing = false; break; + default: + break; } } } diff --git a/applications/plugins/spectrum_analyzer/spectrum_analyzer.c b/applications/plugins/spectrum_analyzer/spectrum_analyzer.c index d94739bc1..8d68c5a1a 100644 --- a/applications/plugins/spectrum_analyzer/spectrum_analyzer.c +++ b/applications/plugins/spectrum_analyzer/spectrum_analyzer.c @@ -496,6 +496,8 @@ int32_t spectrum_analyzer_app(void* p) { case InputKeyBack: exit_loop = true; break; + default: + break; } furi_mutex_release(spectrum_analyzer->model_mutex); diff --git a/applications/plugins/tetris_game/tetris_game.c b/applications/plugins/tetris_game/tetris_game.c index 29b61cd2a..949c29896 100644 --- a/applications/plugins/tetris_game/tetris_game.c +++ b/applications/plugins/tetris_game/tetris_game.c @@ -437,6 +437,8 @@ int32_t tetris_game_app() { case InputKeyBack: processing = false; break; + default: + break; } } } else if(event.type == EventTypeTick) { diff --git a/lib/drivers/SConscript b/lib/drivers/SConscript index 18b96a0ed..d82f09f1d 100644 --- a/lib/drivers/SConscript +++ b/lib/drivers/SConscript @@ -5,7 +5,7 @@ env.Append( "#/lib/drivers", ], SDK_HEADERS=[ - File("drivers/nrf24.h"), + File("nrf24.h"), ], ) diff --git a/lib/subghz/SConscript b/lib/subghz/SConscript index d0a663a50..8fbec94ad 100644 --- a/lib/subghz/SConscript +++ b/lib/subghz/SConscript @@ -5,20 +5,20 @@ env.Append( "#/lib/subghz", ], SDK_HEADERS=[ - File("subghz/environment.h"), - File("subghz/receiver.h"), - File("subghz/subghz_worker.h"), - File("subghz/subghz_tx_rx_worker.h"), - File("subghz/transmitter.h"), - File("subghz/registry.h"), - File("subghz/protocols/protocol_items.h"), - File("subghz/protocols/raw.h"), - File("subghz/blocks/const.h"), - File("subghz/blocks/decoder.h"), - File("subghz/blocks/encoder.h"), - File("subghz/blocks/generic.h"), - File("subghz/blocks/math.h"), - File("subghz/subghz_setting.h"), + File("environment.h"), + File("receiver.h"), + File("subghz_worker.h"), + File("subghz_tx_rx_worker.h"), + File("transmitter.h"), + File("registry.h"), + File("protocols/protocol_items.h"), + File("protocols/raw.h"), + File("blocks/const.h"), + File("blocks/decoder.h"), + File("blocks/encoder.h"), + File("blocks/generic.h"), + File("blocks/math.h"), + File("subghz_setting.h"), ], ) From adab2b9e03f9d095af52fa2b48efef482415ae4a Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Wed, 2 Nov 2022 23:10:14 +0300 Subject: [PATCH 15/23] Update and fix TOTP fix - added this in every button event switch: default: break; --- .../totp/images/totp_arrow_left_8x9.png | Bin 0 -> 149 bytes .../totp/images/totp_arrow_right_8x9.png | Bin 0 -> 149 bytes .../scenes/add_new_token/totp_input_text.c | 18 +- .../scenes/add_new_token/totp_input_text.h | 2 +- .../add_new_token/totp_scene_add_new_token.c | 293 +++++++++--------- .../add_new_token/totp_scene_add_new_token.h | 6 +- .../scenes/app_settings/totp_app_settings.c | 151 ++++----- .../scenes/app_settings/totp_app_settings.h | 10 +- .../authenticate/totp_scene_authenticate.c | 148 ++++----- .../authenticate/totp_scene_authenticate.h | 6 +- .../totp_scene_generate_token.c | 121 ++++---- .../totp_scene_generate_token.h | 10 +- .../plugins/totp/scenes/scene_director.c | 2 +- .../plugins/totp/scenes/scene_director.h | 2 +- .../scenes/token_menu/totp_scene_token_menu.c | 213 ++++++------- .../scenes/token_menu/totp_scene_token_menu.h | 8 +- applications/plugins/totp/services/cli/cli.c | 2 +- .../plugins/totp/services/cli/cli_helpers.c | 3 +- .../plugins/totp/services/cli/cli_helpers.h | 28 +- .../totp/services/cli/commands/add/add.c | 117 +++---- .../plugins/totp/services/config/config.c | 36 +-- .../plugins/totp/services/config/config.h | 4 +- .../plugins/totp/services/crypto/crypto.c | 19 +- .../plugins/totp/services/crypto/crypto.h | 10 +- .../plugins/totp/services/crypto/memset_s.c | 22 ++ .../plugins/totp/services/crypto/memset_s.h | 16 + .../plugins/totp/services/list/list.c | 5 +- .../plugins/totp/services/list/list.h | 11 +- .../plugins/totp/services/nullable/nullable.h | 17 + .../totp/services/roll_value/roll_value.c | 28 ++ .../totp/services/roll_value/roll_value.h | 17 + .../plugins/totp/services/totp/totp.c | 18 +- .../plugins/totp/services/totp/totp.h | 6 +- applications/plugins/totp/services/ui/icons.h | 13 - .../plugins/totp/services/ui/ui_controls.c | 30 +- .../plugins/totp/services/ui/ui_controls.h | 10 +- applications/plugins/totp/totp_app.c | 52 ++-- .../plugins/totp/types/plugin_state.h | 4 +- applications/plugins/totp/types/token_info.c | 11 +- applications/plugins/totp/types/token_info.h | 8 +- 40 files changed, 810 insertions(+), 667 deletions(-) create mode 100644 applications/plugins/totp/images/totp_arrow_left_8x9.png create mode 100644 applications/plugins/totp/images/totp_arrow_right_8x9.png create mode 100644 applications/plugins/totp/services/crypto/memset_s.c create mode 100644 applications/plugins/totp/services/crypto/memset_s.h create mode 100644 applications/plugins/totp/services/nullable/nullable.h create mode 100644 applications/plugins/totp/services/roll_value/roll_value.c create mode 100644 applications/plugins/totp/services/roll_value/roll_value.h delete mode 100644 applications/plugins/totp/services/ui/icons.h diff --git a/applications/plugins/totp/images/totp_arrow_left_8x9.png b/applications/plugins/totp/images/totp_arrow_left_8x9.png new file mode 100644 index 0000000000000000000000000000000000000000..3bf9121c0b3eb1d3a7e05bc069f9b23827adb381 GIT binary patch literal 149 zcmeAS@N?(olHy`uVBq!ia0vp^96-#;$P6S+=l;(HQjEnx?oJHr&dIz4a#+$GeH|GX zHuiJ>Nn{1`*#dk*T>t<74`hZOx?BgOI14-?iy0XB4ude`@%$AjKtTyl7sn8Z%gG5T o3F#BkSET>oKk|v^4Nnh)$W|twRlcWOfod2$UHx3vIVCg!0A-gcZvX%Q literal 0 HcmV?d00001 diff --git a/applications/plugins/totp/images/totp_arrow_right_8x9.png b/applications/plugins/totp/images/totp_arrow_right_8x9.png new file mode 100644 index 0000000000000000000000000000000000000000..8c6a8bfeb91385715c668ae573f6e609cf43ad72 GIT binary patch literal 149 zcmeAS@N?(olHy`uVBq!ia0vp^96-#;$P6S+=l;(HQjEnx?oJHr&dIz4a#+$GeH|GX zHuiJ>Nn{1`*#dk*T!Hle|NocXoPQU{;w #include "../../types/common.h" +size_t strnlen(const char* s, size_t maxlen) { + size_t len; + + for(len = 0; len < maxlen; len++, s++) { + if(!*s) break; + } + + return len; +} + void view_draw(View* view, Canvas* canvas) { furi_assert(view); if(view->draw_callback) { @@ -32,10 +42,14 @@ static void commit_text_input_callback(void* context) { InputTextSceneState* text_input_state = (InputTextSceneState*)context; if(text_input_state->callback != 0) { InputTextSceneCallbackResult* result = malloc(sizeof(InputTextSceneCallbackResult)); - result->user_input_length = strlen(text_input_state->text_input_buffer); + result->user_input_length = + strnlen(text_input_state->text_input_buffer, INPUT_BUFFER_SIZE); result->user_input = malloc(result->user_input_length + 1); result->callback_data = text_input_state->callback_data; - strcpy(result->user_input, text_input_state->text_input_buffer); + strlcpy( + result->user_input, + text_input_state->text_input_buffer, + result->user_input_length + 1); text_input_state->callback(result); } } diff --git a/applications/plugins/totp/scenes/add_new_token/totp_input_text.h b/applications/plugins/totp/scenes/add_new_token/totp_input_text.h index a73a227b5..dda0dc301 100644 --- a/applications/plugins/totp/scenes/add_new_token/totp_input_text.h +++ b/applications/plugins/totp/scenes/add_new_token/totp_input_text.h @@ -10,7 +10,7 @@ typedef struct { char* user_input; - uint8_t user_input_length; + size_t user_input_length; void* callback_data; } InputTextSceneCallbackResult; diff --git a/applications/plugins/totp/scenes/add_new_token/totp_scene_add_new_token.c b/applications/plugins/totp/scenes/add_new_token/totp_scene_add_new_token.c index fc39b66cd..ff8cc5f38 100644 --- a/applications/plugins/totp/scenes/add_new_token/totp_scene_add_new_token.c +++ b/applications/plugins/totp/scenes/add_new_token/totp_scene_add_new_token.c @@ -8,6 +8,8 @@ #include "../../services/base32/base32.h" #include "../../services/config/config.h" #include "../../services/ui/ui_controls.h" +#include "../../services/roll_value/roll_value.h" +#include "../../services/nullable/nullable.h" #include "../generate_token/totp_scene_generate_token.h" #define TOKEN_ALGO_LIST_LENGTH 3 @@ -25,22 +27,22 @@ typedef enum { typedef struct { char* token_name; - uint8_t token_name_length; + size_t token_name_length; char* token_secret; - uint8_t token_secret_length; + size_t token_secret_length; bool saved; Control selected_control; InputTextSceneContext* token_name_input_context; InputTextSceneContext* token_secret_input_context; InputTextSceneState* input_state; uint32_t input_started_at; - int16_t current_token_index; - int32_t screen_y_offset; + TotpNullable_uint16_t current_token_index; + int16_t screen_y_offset; TokenHashAlgo algo; TokenDigitsCount digits_count; } SceneState; -void totp_scene_add_new_token_init(PluginState* plugin_state) { +void totp_scene_add_new_token_init(const PluginState* plugin_state) { UNUSED(plugin_state); } @@ -87,9 +89,9 @@ void totp_scene_add_new_token_activate( scene_state->input_state = NULL; if(context == NULL) { - scene_state->current_token_index = -1; + TOTP_NULLABLE_NULL(scene_state->current_token_index); } else { - scene_state->current_token_index = context->current_token_index; + TOTP_NULLABLE_VALUE(scene_state->current_token_index, context->current_token_index); } } @@ -150,141 +152,148 @@ void update_screen_y_offset(SceneState* scene_state) { } bool totp_scene_add_new_token_handle_event(PluginEvent* const event, PluginState* plugin_state) { - if(event->type == EventTypeKey) { - SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; - if(scene_state->input_started_at > 0 && - furi_get_tick() - scene_state->input_started_at > 300) { - return totp_input_text_handle_event(event, scene_state->input_state); - } - - if(event->input.type == InputTypeLong && event->input.key == InputKeyBack) { - return false; - } else if(event->input.type == InputTypePress) { - switch(event->input.key) { - case InputKeyUp: - if(scene_state->selected_control > TokenNameTextBox) { - scene_state->selected_control--; - update_screen_y_offset(scene_state); - } - break; - case InputKeyDown: - if(scene_state->selected_control < ConfirmButton) { - scene_state->selected_control++; - update_screen_y_offset(scene_state); - } - break; - case InputKeyRight: - if(scene_state->selected_control == TokenAlgoSelect) { - if(scene_state->algo < SHA512) { - scene_state->algo++; - } else { - scene_state->algo = SHA1; - } - } else if(scene_state->selected_control == TokenLengthSelect) { - if(scene_state->digits_count < TOTP_8_DIGITS) { - scene_state->digits_count++; - } else { - scene_state->digits_count = TOTP_6_DIGITS; - } - } - break; - case InputKeyLeft: - if(scene_state->selected_control == TokenAlgoSelect) { - if(scene_state->algo > SHA1) { - scene_state->algo--; - } else { - scene_state->algo = SHA512; - } - } else if(scene_state->selected_control == TokenLengthSelect) { - if(scene_state->digits_count > TOTP_6_DIGITS) { - scene_state->digits_count--; - } else { - scene_state->digits_count = TOTP_8_DIGITS; - } - } - break; - case InputKeyOk: - switch(scene_state->selected_control) { - case TokenNameTextBox: - if(scene_state->input_state != NULL) { - totp_input_text_free(scene_state->input_state); - } - scene_state->input_state = - totp_input_text_activate(scene_state->token_name_input_context); - scene_state->input_started_at = furi_get_tick(); - break; - case TokenSecretTextBox: - if(scene_state->input_state != NULL) { - totp_input_text_free(scene_state->input_state); - } - scene_state->input_state = - totp_input_text_activate(scene_state->token_secret_input_context); - scene_state->input_started_at = furi_get_tick(); - break; - case TokenAlgoSelect: - break; - case TokenLengthSelect: - break; - case ConfirmButton: { - TokenInfo* tokenInfo = token_info_alloc(); - bool token_secret_set = token_info_set_secret( - tokenInfo, - scene_state->token_secret, - scene_state->token_secret_length, - &plugin_state->iv[0]); - - if(token_secret_set) { - tokenInfo->name = malloc(scene_state->token_name_length + 1); - strcpy(tokenInfo->name, scene_state->token_name); - tokenInfo->algo = scene_state->algo; - tokenInfo->digits = scene_state->digits_count; - - if(plugin_state->tokens_list == NULL) { - plugin_state->tokens_list = list_init_head(tokenInfo); - } else { - list_add(plugin_state->tokens_list, tokenInfo); - } - plugin_state->tokens_count++; - - totp_config_file_save_new_token(tokenInfo); - - GenerateTokenSceneContext generate_scene_context = { - .current_token_index = plugin_state->tokens_count - 1}; - totp_scene_director_activate_scene( - plugin_state, TotpSceneGenerateToken, &generate_scene_context); - } else { - token_info_free(tokenInfo); - DialogMessage* message = dialog_message_alloc(); - dialog_message_set_buttons(message, "Back", NULL, NULL); - dialog_message_set_text( - message, - "Token secret is invalid", - SCREEN_WIDTH_CENTER, - SCREEN_HEIGHT_CENTER, - AlignCenter, - AlignCenter); - dialog_message_show(plugin_state->dialogs, message); - dialog_message_free(message); - scene_state->selected_control = TokenSecretTextBox; - update_screen_y_offset(scene_state); - } - break; - } - } - break; - case InputKeyBack: - if(scene_state->current_token_index >= 0) { - GenerateTokenSceneContext generate_scene_context = { - .current_token_index = scene_state->current_token_index}; - totp_scene_director_activate_scene( - plugin_state, TotpSceneGenerateToken, &generate_scene_context); - } else { - totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL); - } - break; - } - } + if(event->type != EventTypeKey) { + return true; } + + SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; + if(scene_state->input_started_at > 0 && + furi_get_tick() - scene_state->input_started_at > 300) { + return totp_input_text_handle_event(event, scene_state->input_state); + } + + if(event->input.type == InputTypeLong && event->input.key == InputKeyBack) { + return false; + } + + if(event->input.type != InputTypePress) { + return true; + } + + switch(event->input.key) { + case InputKeyUp: + totp_roll_value_uint8_t( + &scene_state->selected_control, + -1, + TokenNameTextBox, + ConfirmButton, + RollOverflowBehaviorStop); + update_screen_y_offset(scene_state); + break; + case InputKeyDown: + totp_roll_value_uint8_t( + &scene_state->selected_control, + 1, + TokenNameTextBox, + ConfirmButton, + RollOverflowBehaviorStop); + update_screen_y_offset(scene_state); + break; + case InputKeyRight: + if(scene_state->selected_control == TokenAlgoSelect) { + totp_roll_value_uint8_t(&scene_state->algo, 1, SHA1, SHA512, RollOverflowBehaviorRoll); + } else if(scene_state->selected_control == TokenLengthSelect) { + totp_roll_value_uint8_t( + &scene_state->digits_count, + 1, + TOTP_6_DIGITS, + TOTP_8_DIGITS, + RollOverflowBehaviorRoll); + } + break; + case InputKeyLeft: + if(scene_state->selected_control == TokenAlgoSelect) { + totp_roll_value_uint8_t( + &scene_state->algo, -1, SHA1, SHA512, RollOverflowBehaviorRoll); + } else if(scene_state->selected_control == TokenLengthSelect) { + totp_roll_value_uint8_t( + &scene_state->digits_count, + -1, + TOTP_6_DIGITS, + TOTP_8_DIGITS, + RollOverflowBehaviorRoll); + } + break; + case InputKeyOk: + switch(scene_state->selected_control) { + case TokenNameTextBox: + if(scene_state->input_state != NULL) { + totp_input_text_free(scene_state->input_state); + } + scene_state->input_state = + totp_input_text_activate(scene_state->token_name_input_context); + scene_state->input_started_at = furi_get_tick(); + break; + case TokenSecretTextBox: + if(scene_state->input_state != NULL) { + totp_input_text_free(scene_state->input_state); + } + scene_state->input_state = + totp_input_text_activate(scene_state->token_secret_input_context); + scene_state->input_started_at = furi_get_tick(); + break; + case TokenAlgoSelect: + break; + case TokenLengthSelect: + break; + case ConfirmButton: { + TokenInfo* tokenInfo = token_info_alloc(); + bool token_secret_set = token_info_set_secret( + tokenInfo, + scene_state->token_secret, + scene_state->token_secret_length, + &plugin_state->iv[0]); + + if(token_secret_set) { + tokenInfo->name = malloc(scene_state->token_name_length + 1); + strlcpy( + tokenInfo->name, scene_state->token_name, scene_state->token_name_length + 1); + tokenInfo->algo = scene_state->algo; + tokenInfo->digits = scene_state->digits_count; + + TOTP_LIST_INIT_OR_ADD(plugin_state->tokens_list, tokenInfo); + plugin_state->tokens_count++; + + totp_config_file_save_new_token(tokenInfo); + + GenerateTokenSceneContext generate_scene_context = { + .current_token_index = plugin_state->tokens_count - 1}; + totp_scene_director_activate_scene( + plugin_state, TotpSceneGenerateToken, &generate_scene_context); + } else { + token_info_free(tokenInfo); + DialogMessage* message = dialog_message_alloc(); + dialog_message_set_buttons(message, "Back", NULL, NULL); + dialog_message_set_text( + message, + "Token secret is invalid", + SCREEN_WIDTH_CENTER, + SCREEN_HEIGHT_CENTER, + AlignCenter, + AlignCenter); + dialog_message_show(plugin_state->dialogs, message); + dialog_message_free(message); + scene_state->selected_control = TokenSecretTextBox; + update_screen_y_offset(scene_state); + } + break; + } + } + break; + case InputKeyBack: + if(!scene_state->current_token_index.is_null) { + GenerateTokenSceneContext generate_scene_context = { + .current_token_index = scene_state->current_token_index.value}; + totp_scene_director_activate_scene( + plugin_state, TotpSceneGenerateToken, &generate_scene_context); + } else { + totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL); + } + break; + default: + break; + } + return true; } @@ -308,6 +317,6 @@ void totp_scene_add_new_token_deactivate(PluginState* plugin_state) { plugin_state->current_scene_state = NULL; } -void totp_scene_add_new_token_free(PluginState* plugin_state) { +void totp_scene_add_new_token_free(const PluginState* plugin_state) { UNUSED(plugin_state); } diff --git a/applications/plugins/totp/scenes/add_new_token/totp_scene_add_new_token.h b/applications/plugins/totp/scenes/add_new_token/totp_scene_add_new_token.h index b65c567a2..9f53fe799 100644 --- a/applications/plugins/totp/scenes/add_new_token/totp_scene_add_new_token.h +++ b/applications/plugins/totp/scenes/add_new_token/totp_scene_add_new_token.h @@ -7,14 +7,14 @@ #include "../../types/plugin_event.h" typedef struct { - uint8_t current_token_index; + uint16_t current_token_index; } TokenAddEditSceneContext; -void totp_scene_add_new_token_init(PluginState* plugin_state); +void totp_scene_add_new_token_init(const PluginState* plugin_state); void totp_scene_add_new_token_activate( PluginState* plugin_state, const TokenAddEditSceneContext* context); void totp_scene_add_new_token_render(Canvas* const canvas, PluginState* plugin_state); bool totp_scene_add_new_token_handle_event(PluginEvent* const event, PluginState* plugin_state); void totp_scene_add_new_token_deactivate(PluginState* plugin_state); -void totp_scene_add_new_token_free(PluginState* plugin_state); +void totp_scene_add_new_token_free(const PluginState* plugin_state); diff --git a/applications/plugins/totp/scenes/app_settings/totp_app_settings.c b/applications/plugins/totp/scenes/app_settings/totp_app_settings.c index cdb775a8d..b5b75db71 100644 --- a/applications/plugins/totp/scenes/app_settings/totp_app_settings.c +++ b/applications/plugins/totp/scenes/app_settings/totp_app_settings.c @@ -4,6 +4,8 @@ #include "../token_menu/totp_scene_token_menu.h" #include "../../services/ui/constants.h" #include "../../services/config/config.h" +#include "../../services/roll_value/roll_value.h" +#include "../../services/nullable/nullable.h" #define DIGIT_TO_CHAR(digit) ((digit) + '0') @@ -12,11 +14,11 @@ typedef enum { HoursInput, MinutesInput, ConfirmButton } Control; typedef struct { int8_t tz_offset_hours; uint8_t tz_offset_minutes; - int16_t current_token_index; + TotpNullable_uint16_t current_token_index; Control selected_control; } SceneState; -void totp_scene_app_settings_init(PluginState* plugin_state) { +void totp_scene_app_settings_init(const PluginState* plugin_state) { UNUSED(plugin_state); } @@ -26,9 +28,9 @@ void totp_scene_app_settings_activate( SceneState* scene_state = malloc(sizeof(SceneState)); plugin_state->current_scene_state = scene_state; if(context != NULL) { - scene_state->current_token_index = context->current_token_index; + TOTP_NULLABLE_VALUE(scene_state->current_token_index, context->current_token_index); } else { - scene_state->current_token_index = -1; + TOTP_NULLABLE_NULL(scene_state->current_token_index); } float off_int; @@ -53,7 +55,7 @@ static void two_digit_to_str(int8_t num, char* str) { } void totp_scene_app_settings_render(Canvas* const canvas, PluginState* plugin_state) { - SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; + const SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; canvas_set_font(canvas, FontPrimary); canvas_draw_str_aligned(canvas, 0, 0, AlignLeft, AlignTop, "Timezone offset"); @@ -90,77 +92,80 @@ void totp_scene_app_settings_render(Canvas* const canvas, PluginState* plugin_st scene_state->selected_control == ConfirmButton); } -bool totp_scene_app_settings_handle_event(PluginEvent* const event, PluginState* plugin_state) { - if(event->type == EventTypeKey) { - SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; - if(event->input.type == InputTypePress) { - switch(event->input.key) { - case InputKeyUp: - if(scene_state->selected_control > HoursInput) { - scene_state->selected_control--; - } - break; - case InputKeyDown: - if(scene_state->selected_control < ConfirmButton) { - scene_state->selected_control++; - } - break; - case InputKeyRight: - if(scene_state->selected_control == HoursInput) { - if(scene_state->tz_offset_hours < 12) { - scene_state->tz_offset_hours++; - } - } else if(scene_state->selected_control == MinutesInput) { - if(scene_state->tz_offset_minutes < 45) { - scene_state->tz_offset_minutes += 15; - } else { - scene_state->tz_offset_minutes = 0; - } - } - break; - case InputKeyLeft: - if(scene_state->selected_control == HoursInput) { - if(scene_state->tz_offset_hours > -12) { - scene_state->tz_offset_hours--; - } - } else if(scene_state->selected_control == MinutesInput) { - if(scene_state->tz_offset_minutes >= 15) { - scene_state->tz_offset_minutes -= 15; - } else { - scene_state->tz_offset_minutes = 45; - } - } - break; - case InputKeyOk: - if(scene_state->selected_control == ConfirmButton) { - plugin_state->timezone_offset = (float)scene_state->tz_offset_hours + - (float)scene_state->tz_offset_minutes / 60.0f; - totp_config_file_update_timezone_offset(plugin_state->timezone_offset); +bool totp_scene_app_settings_handle_event( + const PluginEvent* const event, + PluginState* plugin_state) { + if(event->type != EventTypeKey) { + return true; + } - if(scene_state->current_token_index >= 0) { - TokenMenuSceneContext generate_scene_context = { - .current_token_index = scene_state->current_token_index}; - totp_scene_director_activate_scene( - plugin_state, TotpSceneTokenMenu, &generate_scene_context); - } else { - totp_scene_director_activate_scene(plugin_state, TotpSceneTokenMenu, NULL); - } - } - break; - case InputKeyBack: { - if(scene_state->current_token_index >= 0) { - TokenMenuSceneContext generate_scene_context = { - .current_token_index = scene_state->current_token_index}; - totp_scene_director_activate_scene( - plugin_state, TotpSceneTokenMenu, &generate_scene_context); - } else { - totp_scene_director_activate_scene(plugin_state, TotpSceneTokenMenu, NULL); - } - break; - } + SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; + if(event->input.type != InputTypePress) { + return true; + } + + switch(event->input.key) { + case InputKeyUp: + totp_roll_value_uint8_t( + &scene_state->selected_control, + -1, + HoursInput, + ConfirmButton, + RollOverflowBehaviorStop); + break; + case InputKeyDown: + totp_roll_value_uint8_t( + &scene_state->selected_control, 1, HoursInput, ConfirmButton, RollOverflowBehaviorStop); + break; + case InputKeyRight: + if(scene_state->selected_control == HoursInput) { + totp_roll_value_int8_t( + &scene_state->tz_offset_hours, 1, -12, 12, RollOverflowBehaviorStop); + } else if(scene_state->selected_control == MinutesInput) { + totp_roll_value_uint8_t( + &scene_state->tz_offset_minutes, 15, 0, 45, RollOverflowBehaviorRoll); + } + break; + case InputKeyLeft: + if(scene_state->selected_control == HoursInput) { + totp_roll_value_int8_t( + &scene_state->tz_offset_hours, -1, -12, 12, RollOverflowBehaviorStop); + } else if(scene_state->selected_control == MinutesInput) { + totp_roll_value_uint8_t( + &scene_state->tz_offset_minutes, -15, 0, 45, RollOverflowBehaviorRoll); + } + break; + case InputKeyOk: + if(scene_state->selected_control == ConfirmButton) { + plugin_state->timezone_offset = (float)scene_state->tz_offset_hours + + (float)scene_state->tz_offset_minutes / 60.0f; + totp_config_file_update_timezone_offset(plugin_state->timezone_offset); + + if(!scene_state->current_token_index.is_null) { + TokenMenuSceneContext generate_scene_context = { + .current_token_index = scene_state->current_token_index.value}; + totp_scene_director_activate_scene( + plugin_state, TotpSceneTokenMenu, &generate_scene_context); + } else { + totp_scene_director_activate_scene(plugin_state, TotpSceneTokenMenu, NULL); } } + break; + case InputKeyBack: { + if(!scene_state->current_token_index.is_null) { + TokenMenuSceneContext generate_scene_context = { + .current_token_index = scene_state->current_token_index.value}; + totp_scene_director_activate_scene( + plugin_state, TotpSceneTokenMenu, &generate_scene_context); + } else { + totp_scene_director_activate_scene(plugin_state, TotpSceneTokenMenu, NULL); + } + break; } + default: + break; + } + return true; } @@ -171,6 +176,6 @@ void totp_scene_app_settings_deactivate(PluginState* plugin_state) { plugin_state->current_scene_state = NULL; } -void totp_scene_app_settings_free(PluginState* plugin_state) { +void totp_scene_app_settings_free(const PluginState* plugin_state) { UNUSED(plugin_state); } \ No newline at end of file diff --git a/applications/plugins/totp/scenes/app_settings/totp_app_settings.h b/applications/plugins/totp/scenes/app_settings/totp_app_settings.h index b97de3390..bcf930839 100644 --- a/applications/plugins/totp/scenes/app_settings/totp_app_settings.h +++ b/applications/plugins/totp/scenes/app_settings/totp_app_settings.h @@ -7,14 +7,16 @@ #include "../../types/plugin_event.h" typedef struct { - uint8_t current_token_index; + uint16_t current_token_index; } AppSettingsSceneContext; -void totp_scene_app_settings_init(PluginState* plugin_state); +void totp_scene_app_settings_init(const PluginState* plugin_state); void totp_scene_app_settings_activate( PluginState* plugin_state, const AppSettingsSceneContext* context); void totp_scene_app_settings_render(Canvas* const canvas, PluginState* plugin_state); -bool totp_scene_app_settings_handle_event(PluginEvent* const event, PluginState* plugin_state); +bool totp_scene_app_settings_handle_event( + const PluginEvent* const event, + PluginState* plugin_state); void totp_scene_app_settings_deactivate(PluginState* plugin_state); -void totp_scene_app_settings_free(PluginState* plugin_state); \ No newline at end of file +void totp_scene_app_settings_free(const PluginState* plugin_state); \ No newline at end of file diff --git a/applications/plugins/totp/scenes/authenticate/totp_scene_authenticate.c b/applications/plugins/totp/scenes/authenticate/totp_scene_authenticate.c index 4ed79accd..8f44653ec 100644 --- a/applications/plugins/totp/scenes/authenticate/totp_scene_authenticate.c +++ b/applications/plugins/totp/scenes/authenticate/totp_scene_authenticate.c @@ -1,7 +1,7 @@ #include "totp_scene_authenticate.h" #include +#include #include "../../types/common.h" -#include "../../services/ui/icons.h" #include "../../services/ui/constants.h" #include "../../services/config/config.h" #include "../scene_director.h" @@ -9,6 +9,10 @@ #include "../../services/crypto/crypto.h" #define MAX_CODE_LENGTH TOTP_IV_SIZE +#define ARROW_UP_CODE 2 +#define ARROW_RIGHT_CODE 8 +#define ARROW_DOWN_CODE 11 +#define ARROW_LEFT_CODE 5 typedef struct { uint8_t code_input[MAX_CODE_LENGTH]; @@ -28,7 +32,7 @@ void totp_scene_authenticate_activate(PluginState* plugin_state) { } void totp_scene_authenticate_render(Canvas* const canvas, PluginState* plugin_state) { - SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; + const SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; int v_shift = 0; if(scene_state->code_length > 0) { @@ -73,78 +77,82 @@ void totp_scene_authenticate_render(Canvas* const canvas, PluginState* plugin_st } } -bool totp_scene_authenticate_handle_event(PluginEvent* const event, PluginState* plugin_state) { - if(event->type == EventTypeKey) { - if(event->input.type == InputTypeLong && event->input.key == InputKeyBack) { - return false; - } else if(event->input.type == InputTypePress) { - SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; +bool totp_scene_authenticate_handle_event( + const PluginEvent* const event, + PluginState* plugin_state) { + if(event->type != EventTypeKey) { + return true; + } - const uint8_t ARROW_UP_CODE = 2; - const uint8_t ARROW_RIGHT_CODE = 8; - const uint8_t ARROW_DOWN_CODE = 11; - const uint8_t ARROW_LEFT_CODE = 5; + if(event->input.type == InputTypeLong && event->input.key == InputKeyBack) { + return false; + } - switch(event->input.key) { - case InputKeyUp: - if(scene_state->code_length < MAX_CODE_LENGTH) { - scene_state->code_input[scene_state->code_length] = ARROW_UP_CODE; - scene_state->code_length++; - } - break; - case InputKeyDown: - if(scene_state->code_length < MAX_CODE_LENGTH) { - scene_state->code_input[scene_state->code_length] = ARROW_DOWN_CODE; - scene_state->code_length++; - } - break; - case InputKeyRight: - if(scene_state->code_length < MAX_CODE_LENGTH) { - scene_state->code_input[scene_state->code_length] = ARROW_RIGHT_CODE; - scene_state->code_length++; - } - break; - case InputKeyLeft: - if(scene_state->code_length < MAX_CODE_LENGTH) { - scene_state->code_input[scene_state->code_length] = ARROW_LEFT_CODE; - scene_state->code_length++; - } - break; - case InputKeyOk: - totp_crypto_seed_iv( - plugin_state, &scene_state->code_input[0], scene_state->code_length); + if(event->input.type != InputTypePress) { + return true; + } - if(totp_crypto_verify_key(plugin_state)) { - FURI_LOG_D(LOGGING_TAG, "PIN is valid"); - totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL); - } else { - FURI_LOG_D(LOGGING_TAG, "PIN is NOT valid"); - memset(&scene_state->code_input[0], 0, MAX_CODE_LENGTH); - memset(&plugin_state->iv[0], 0, TOTP_IV_SIZE); - scene_state->code_length = 0; + SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; - DialogMessage* message = dialog_message_alloc(); - dialog_message_set_buttons(message, "Try again", NULL, NULL); - dialog_message_set_header( - message, - "You entered\ninvalid PIN", - SCREEN_WIDTH_CENTER - 25, - SCREEN_HEIGHT_CENTER - 5, - AlignCenter, - AlignCenter); - dialog_message_set_icon(message, &I_DolphinCommon_56x48, 72, 17); - dialog_message_show(plugin_state->dialogs, message); - dialog_message_free(message); - } - break; - case InputKeyBack: - if(scene_state->code_length > 0) { - scene_state->code_input[scene_state->code_length - 1] = 0; - scene_state->code_length--; - } - break; - } + switch(event->input.key) { + case InputKeyUp: + if(scene_state->code_length < MAX_CODE_LENGTH) { + scene_state->code_input[scene_state->code_length] = ARROW_UP_CODE; + scene_state->code_length++; } + break; + case InputKeyDown: + if(scene_state->code_length < MAX_CODE_LENGTH) { + scene_state->code_input[scene_state->code_length] = ARROW_DOWN_CODE; + scene_state->code_length++; + } + break; + case InputKeyRight: + if(scene_state->code_length < MAX_CODE_LENGTH) { + scene_state->code_input[scene_state->code_length] = ARROW_RIGHT_CODE; + scene_state->code_length++; + } + break; + case InputKeyLeft: + if(scene_state->code_length < MAX_CODE_LENGTH) { + scene_state->code_input[scene_state->code_length] = ARROW_LEFT_CODE; + scene_state->code_length++; + } + break; + case InputKeyOk: + totp_crypto_seed_iv(plugin_state, &scene_state->code_input[0], scene_state->code_length); + + if(totp_crypto_verify_key(plugin_state)) { + FURI_LOG_D(LOGGING_TAG, "PIN is valid"); + totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL); + } else { + FURI_LOG_D(LOGGING_TAG, "PIN is NOT valid"); + memset(&scene_state->code_input[0], 0, MAX_CODE_LENGTH); + memset(&plugin_state->iv[0], 0, TOTP_IV_SIZE); + scene_state->code_length = 0; + + DialogMessage* message = dialog_message_alloc(); + dialog_message_set_buttons(message, "Try again", NULL, NULL); + dialog_message_set_header( + message, + "You entered\ninvalid PIN", + SCREEN_WIDTH_CENTER - 25, + SCREEN_HEIGHT_CENTER - 5, + AlignCenter, + AlignCenter); + dialog_message_set_icon(message, &I_DolphinCommon_56x48, 72, 17); + dialog_message_show(plugin_state->dialogs, message); + dialog_message_free(message); + } + break; + case InputKeyBack: + if(scene_state->code_length > 0) { + scene_state->code_input[scene_state->code_length - 1] = 0; + scene_state->code_length--; + } + break; + default: + break; } return true; @@ -156,6 +164,6 @@ void totp_scene_authenticate_deactivate(PluginState* plugin_state) { plugin_state->current_scene_state = NULL; } -void totp_scene_authenticate_free(PluginState* plugin_state) { +void totp_scene_authenticate_free(const PluginState* plugin_state) { UNUSED(plugin_state); } diff --git a/applications/plugins/totp/scenes/authenticate/totp_scene_authenticate.h b/applications/plugins/totp/scenes/authenticate/totp_scene_authenticate.h index f1199a425..c54152f62 100644 --- a/applications/plugins/totp/scenes/authenticate/totp_scene_authenticate.h +++ b/applications/plugins/totp/scenes/authenticate/totp_scene_authenticate.h @@ -9,6 +9,8 @@ void totp_scene_authenticate_init(PluginState* plugin_state); void totp_scene_authenticate_activate(PluginState* plugin_state); void totp_scene_authenticate_render(Canvas* const canvas, PluginState* plugin_state); -bool totp_scene_authenticate_handle_event(PluginEvent* const event, PluginState* plugin_state); +bool totp_scene_authenticate_handle_event( + const PluginEvent* const event, + PluginState* plugin_state); void totp_scene_authenticate_deactivate(PluginState* plugin_state); -void totp_scene_authenticate_free(PluginState* plugin_state); +void totp_scene_authenticate_free(const PluginState* plugin_state); diff --git a/applications/plugins/totp/scenes/generate_token/totp_scene_generate_token.c b/applications/plugins/totp/scenes/generate_token/totp_scene_generate_token.c index 674bcd41e..c95e2c4e7 100644 --- a/applications/plugins/totp/scenes/generate_token/totp_scene_generate_token.c +++ b/applications/plugins/totp/scenes/generate_token/totp_scene_generate_token.c @@ -1,14 +1,16 @@ #include #include #include +#include #include "totp_scene_generate_token.h" #include "../../types/token_info.h" #include "../../types/common.h" -#include "../../services/ui/icons.h" #include "../../services/ui/constants.h" #include "../../services/totp/totp.h" #include "../../services/config/config.h" #include "../../services/crypto/crypto.h" +#include "../../services/crypto/memset_s.h" +#include "../../services/roll_value/roll_value.h" #include "../scene_director.h" #include "../token_menu/totp_scene_token_menu.h" @@ -16,7 +18,7 @@ #define DIGIT_TO_CHAR(digit) ((digit) + '0') typedef struct { - uint8_t current_token_index; + uint16_t current_token_index; char last_code[9]; char* last_code_name; bool need_token_update; @@ -95,7 +97,7 @@ void update_totp_params(PluginState* const plugin_state) { } } -void totp_scene_generate_token_init(PluginState* plugin_state) { +void totp_scene_generate_token_init(const PluginState* plugin_state) { UNUSED(plugin_state); } @@ -180,7 +182,7 @@ void totp_scene_generate_token_render(Canvas* const canvas, PluginState* plugin_ ->data); if(tokenInfo->token != NULL && tokenInfo->token_length > 0) { - uint8_t key_length; + size_t key_length; uint8_t* key = totp_crypto_decrypt( tokenInfo->token, tokenInfo->token_length, &plugin_state->iv[0], &key_length); @@ -195,7 +197,7 @@ void totp_scene_generate_token_render(Canvas* const canvas, PluginState* plugin_ TOKEN_LIFETIME), scene_state->last_code, tokenInfo->digits); - memset(key, 0, key_length); + memset_s(key, sizeof(key), 0, key_length); free(key); } else { i_token_to_str(0, scene_state->last_code, tokenInfo->digits); @@ -248,63 +250,63 @@ void totp_scene_generate_token_render(Canvas* const canvas, PluginState* plugin_ canvas_draw_box(canvas, barX, SCREEN_HEIGHT - BAR_MARGIN - BAR_HEIGHT, barWidth, BAR_HEIGHT); if(plugin_state->tokens_count > 1) { - canvas_draw_xbm( - canvas, - 0, - SCREEN_HEIGHT_CENTER - 24, - ICON_ARROW_LEFT_8x9_WIDTH, - ICON_ARROW_LEFT_8x9_HEIGHT, - &ICON_ARROW_LEFT_8x9[0]); - canvas_draw_xbm( - canvas, - SCREEN_WIDTH - 9, - SCREEN_HEIGHT_CENTER - 24, - ICON_ARROW_RIGHT_8x9_WIDTH, - ICON_ARROW_RIGHT_8x9_HEIGHT, - &ICON_ARROW_RIGHT_8x9[0]); + canvas_draw_icon(canvas, 0, SCREEN_HEIGHT_CENTER - 24, &I_totp_arrow_left_8x9); + canvas_draw_icon( + canvas, SCREEN_WIDTH - 9, SCREEN_HEIGHT_CENTER - 24, &I_totp_arrow_right_8x9); } } -bool totp_scene_generate_token_handle_event(PluginEvent* const event, PluginState* plugin_state) { - if(event->type == EventTypeKey) { - if(event->input.type == InputTypeLong && event->input.key == InputKeyBack) { - return false; - } else if(event->input.type == InputTypePress) { - SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; - switch(event->input.key) { - case InputKeyUp: - break; - case InputKeyDown: - break; - case InputKeyRight: - if(scene_state->current_token_index < plugin_state->tokens_count - 1) { - scene_state->current_token_index++; - } else { - scene_state->current_token_index = 0; - } - update_totp_params(plugin_state); - break; - case InputKeyLeft: - if(scene_state->current_token_index > 0) { - scene_state->current_token_index--; - } else { - scene_state->current_token_index = plugin_state->tokens_count - 1; - } - update_totp_params(plugin_state); - break; - case InputKeyOk: - if(plugin_state->tokens_count == 0) { - totp_scene_director_activate_scene(plugin_state, TotpSceneTokenMenu, NULL); - } else { - TokenMenuSceneContext ctx = { - .current_token_index = scene_state->current_token_index}; - totp_scene_director_activate_scene(plugin_state, TotpSceneTokenMenu, &ctx); - } - break; - case InputKeyBack: - break; - } +bool totp_scene_generate_token_handle_event( + const PluginEvent* const event, + PluginState* plugin_state) { + if(event->type != EventTypeKey) { + return true; + } + + if(event->input.type == InputTypeLong && event->input.key == InputKeyBack) { + return false; + } + + if(event->input.type != InputTypePress) { + return true; + } + + SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; + switch(event->input.key) { + case InputKeyUp: + break; + case InputKeyDown: + break; + case InputKeyRight: + totp_roll_value_uint16_t( + &scene_state->current_token_index, + 1, + 0, + plugin_state->tokens_count - 1, + RollOverflowBehaviorRoll); + update_totp_params(plugin_state); + break; + case InputKeyLeft: + totp_roll_value_uint16_t( + &scene_state->current_token_index, + -1, + 0, + plugin_state->tokens_count - 1, + RollOverflowBehaviorRoll); + update_totp_params(plugin_state); + break; + case InputKeyOk: + if(plugin_state->tokens_count == 0) { + totp_scene_director_activate_scene(plugin_state, TotpSceneTokenMenu, NULL); + } else { + TokenMenuSceneContext ctx = {.current_token_index = scene_state->current_token_index}; + totp_scene_director_activate_scene(plugin_state, TotpSceneTokenMenu, &ctx); } + break; + case InputKeyBack: + break; + default: + break; } return true; @@ -314,11 +316,10 @@ void totp_scene_generate_token_deactivate(PluginState* plugin_state) { if(plugin_state->current_scene_state == NULL) return; SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; - free(scene_state->last_code); free(scene_state); plugin_state->current_scene_state = NULL; } -void totp_scene_generate_token_free(PluginState* plugin_state) { +void totp_scene_generate_token_free(const PluginState* plugin_state) { UNUSED(plugin_state); } diff --git a/applications/plugins/totp/scenes/generate_token/totp_scene_generate_token.h b/applications/plugins/totp/scenes/generate_token/totp_scene_generate_token.h index 1284c7b41..65f9b84e0 100644 --- a/applications/plugins/totp/scenes/generate_token/totp_scene_generate_token.h +++ b/applications/plugins/totp/scenes/generate_token/totp_scene_generate_token.h @@ -7,14 +7,16 @@ #include "../../types/plugin_event.h" typedef struct { - uint8_t current_token_index; + uint16_t current_token_index; } GenerateTokenSceneContext; -void totp_scene_generate_token_init(PluginState* plugin_state); +void totp_scene_generate_token_init(const PluginState* plugin_state); void totp_scene_generate_token_activate( PluginState* plugin_state, const GenerateTokenSceneContext* context); void totp_scene_generate_token_render(Canvas* const canvas, PluginState* plugin_state); -bool totp_scene_generate_token_handle_event(PluginEvent* const event, PluginState* plugin_state); +bool totp_scene_generate_token_handle_event( + const PluginEvent* const event, + PluginState* plugin_state); void totp_scene_generate_token_deactivate(PluginState* plugin_state); -void totp_scene_generate_token_free(PluginState* plugin_state); +void totp_scene_generate_token_free(const PluginState* plugin_state); diff --git a/applications/plugins/totp/scenes/scene_director.c b/applications/plugins/totp/scenes/scene_director.c index d4ddd1768..5265123f5 100644 --- a/applications/plugins/totp/scenes/scene_director.c +++ b/applications/plugins/totp/scenes/scene_director.c @@ -88,7 +88,7 @@ void totp_scene_director_render(Canvas* const canvas, PluginState* const plugin_ } } -void totp_scene_director_dispose(PluginState* const plugin_state) { +void totp_scene_director_dispose(const PluginState* const plugin_state) { totp_scene_generate_token_free(plugin_state); totp_scene_authenticate_free(plugin_state); totp_scene_add_new_token_free(plugin_state); diff --git a/applications/plugins/totp/scenes/scene_director.h b/applications/plugins/totp/scenes/scene_director.h index 3c25afff6..cc06029d3 100644 --- a/applications/plugins/totp/scenes/scene_director.h +++ b/applications/plugins/totp/scenes/scene_director.h @@ -12,5 +12,5 @@ void totp_scene_director_activate_scene( void totp_scene_director_deactivate_active_scene(PluginState* const plugin_state); void totp_scene_director_init_scenes(PluginState* const plugin_state); void totp_scene_director_render(Canvas* const canvas, PluginState* const plugin_state); -void totp_scene_director_dispose(PluginState* const plugin_state); +void totp_scene_director_dispose(const PluginState* const plugin_state); bool totp_scene_director_handle_event(PluginEvent* const event, PluginState* const plugin_state); diff --git a/applications/plugins/totp/scenes/token_menu/totp_scene_token_menu.c b/applications/plugins/totp/scenes/token_menu/totp_scene_token_menu.c index 22c37dc2c..fecf4f21e 100644 --- a/applications/plugins/totp/scenes/token_menu/totp_scene_token_menu.c +++ b/applications/plugins/totp/scenes/token_menu/totp_scene_token_menu.c @@ -10,6 +10,8 @@ #include "../generate_token/totp_scene_generate_token.h" #include "../add_new_token/totp_scene_add_new_token.h" #include "../app_settings/totp_app_settings.h" +#include "../../services/nullable/nullable.h" +#include "../../services/roll_value/roll_value.h" #define SCREEN_HEIGHT_THIRD (SCREEN_HEIGHT / 3) #define SCREEN_HEIGHT_THIRD_CENTER (SCREEN_HEIGHT_THIRD >> 1) @@ -18,10 +20,10 @@ typedef enum { AddNewToken, DeleteToken, AppSettings } Control; typedef struct { Control selected_control; - int16_t current_token_index; + TotpNullable_uint16_t current_token_index; } SceneState; -void totp_scene_token_menu_init(PluginState* plugin_state) { +void totp_scene_token_menu_init(const PluginState* plugin_state) { UNUSED(plugin_state); } @@ -31,15 +33,15 @@ void totp_scene_token_menu_activate( SceneState* scene_state = malloc(sizeof(SceneState)); plugin_state->current_scene_state = scene_state; if(context != NULL) { - scene_state->current_token_index = context->current_token_index; + TOTP_NULLABLE_VALUE(scene_state->current_token_index, context->current_token_index); } else { - scene_state->current_token_index = -1; + TOTP_NULLABLE_NULL(scene_state->current_token_index); } } void totp_scene_token_menu_render(Canvas* const canvas, PluginState* plugin_state) { - SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; - if(scene_state->current_token_index < 0) { + const SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; + if(scene_state->current_token_index.is_null) { ui_control_button_render( canvas, SCREEN_WIDTH_CENTER - 36, @@ -84,104 +86,107 @@ void totp_scene_token_menu_render(Canvas* const canvas, PluginState* plugin_stat } } -bool totp_scene_token_menu_handle_event(PluginEvent* const event, PluginState* plugin_state) { - if(event->type == EventTypeKey) { - SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; - if(event->input.type == InputTypePress) { - switch(event->input.key) { - case InputKeyUp: - if(scene_state->selected_control > AddNewToken) { - scene_state->selected_control--; - if(scene_state->selected_control == DeleteToken && - scene_state->current_token_index < 0) { - scene_state->selected_control--; - } - } else { - scene_state->selected_control = AppSettings; - } - break; - case InputKeyDown: - if(scene_state->selected_control < AppSettings) { - scene_state->selected_control++; - if(scene_state->selected_control == DeleteToken && - scene_state->current_token_index < 0) { - scene_state->selected_control++; - } - } else { - scene_state->selected_control = AddNewToken; - } - break; - case InputKeyRight: - break; - case InputKeyLeft: - break; - case InputKeyOk: - switch(scene_state->selected_control) { - case AddNewToken: { - TokenAddEditSceneContext add_new_token_scene_context = { - .current_token_index = scene_state->current_token_index}; - totp_scene_director_activate_scene( - plugin_state, TotpSceneAddNewToken, &add_new_token_scene_context); - break; - } - case DeleteToken: { - DialogMessage* message = dialog_message_alloc(); - dialog_message_set_buttons(message, "No", NULL, "Yes"); - dialog_message_set_header(message, "Confirmation", 0, 0, AlignLeft, AlignTop); - dialog_message_set_text( - message, - "Are you sure want to delete?", - SCREEN_WIDTH_CENTER, - SCREEN_HEIGHT_CENTER, - AlignCenter, - AlignCenter); - DialogMessageButton dialog_result = - dialog_message_show(plugin_state->dialogs, message); - dialog_message_free(message); - if(dialog_result == DialogMessageButtonRight) { - ListNode* list_node = list_element_at( - plugin_state->tokens_list, scene_state->current_token_index); - - TokenInfo* tokenInfo = list_node->data; - token_info_free(tokenInfo); - plugin_state->tokens_list = - list_remove(plugin_state->tokens_list, list_node); - plugin_state->tokens_count--; - - totp_full_save_config_file(plugin_state); - totp_scene_director_activate_scene( - plugin_state, TotpSceneGenerateToken, NULL); - } - break; - } - case AppSettings: { - if(scene_state->current_token_index >= 0) { - AppSettingsSceneContext app_settings_context = { - .current_token_index = scene_state->current_token_index}; - totp_scene_director_activate_scene( - plugin_state, TotpSceneAppSettings, &app_settings_context); - } else { - totp_scene_director_activate_scene( - plugin_state, TotpSceneAppSettings, NULL); - } - break; - } - } - break; - case InputKeyBack: { - if(scene_state->current_token_index >= 0) { - GenerateTokenSceneContext generate_scene_context = { - .current_token_index = scene_state->current_token_index}; - totp_scene_director_activate_scene( - plugin_state, TotpSceneGenerateToken, &generate_scene_context); - } else { - totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL); - } - break; - } - } - } +bool totp_scene_token_menu_handle_event(const PluginEvent* const event, PluginState* plugin_state) { + if(event->type != EventTypeKey) { + return true; } + + SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; + if(event->input.type != InputTypePress) { + return true; + } + + switch(event->input.key) { + case InputKeyUp: + totp_roll_value_uint8_t( + &scene_state->selected_control, -1, AddNewToken, AppSettings, RollOverflowBehaviorRoll); + if(scene_state->selected_control == DeleteToken && + scene_state->current_token_index.is_null) { + scene_state->selected_control--; + } + break; + case InputKeyDown: + totp_roll_value_uint8_t( + &scene_state->selected_control, 1, AddNewToken, AppSettings, RollOverflowBehaviorRoll); + if(scene_state->selected_control == DeleteToken && + scene_state->current_token_index.is_null) { + scene_state->selected_control++; + } + break; + case InputKeyRight: + break; + case InputKeyLeft: + break; + case InputKeyOk: + switch(scene_state->selected_control) { + case AddNewToken: { + if(scene_state->current_token_index.is_null) { + totp_scene_director_activate_scene(plugin_state, TotpSceneAddNewToken, NULL); + } else { + TokenAddEditSceneContext add_new_token_scene_context = { + .current_token_index = scene_state->current_token_index.value}; + totp_scene_director_activate_scene( + plugin_state, TotpSceneAddNewToken, &add_new_token_scene_context); + } + break; + } + case DeleteToken: { + DialogMessage* message = dialog_message_alloc(); + dialog_message_set_buttons(message, "No", NULL, "Yes"); + dialog_message_set_header(message, "Confirmation", 0, 0, AlignLeft, AlignTop); + dialog_message_set_text( + message, + "Are you sure want to delete?", + SCREEN_WIDTH_CENTER, + SCREEN_HEIGHT_CENTER, + AlignCenter, + AlignCenter); + DialogMessageButton dialog_result = + dialog_message_show(plugin_state->dialogs, message); + dialog_message_free(message); + if(dialog_result == DialogMessageButtonRight && + !scene_state->current_token_index.is_null) { + ListNode* list_node = list_element_at( + plugin_state->tokens_list, scene_state->current_token_index.value); + + TokenInfo* tokenInfo = list_node->data; + token_info_free(tokenInfo); + plugin_state->tokens_list = list_remove(plugin_state->tokens_list, list_node); + plugin_state->tokens_count--; + + totp_full_save_config_file(plugin_state); + totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL); + } + break; + } + case AppSettings: { + if(!scene_state->current_token_index.is_null) { + AppSettingsSceneContext app_settings_context = { + .current_token_index = scene_state->current_token_index.value}; + totp_scene_director_activate_scene( + plugin_state, TotpSceneAppSettings, &app_settings_context); + } else { + totp_scene_director_activate_scene(plugin_state, TotpSceneAppSettings, NULL); + } + break; + } + } + break; + case InputKeyBack: { + if(!scene_state->current_token_index.is_null) { + GenerateTokenSceneContext generate_scene_context = { + .current_token_index = scene_state->current_token_index.value}; + totp_scene_director_activate_scene( + plugin_state, TotpSceneGenerateToken, &generate_scene_context); + } else { + totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL); + } + break; + } + default: + break; + } + return true; } @@ -192,6 +197,6 @@ void totp_scene_token_menu_deactivate(PluginState* plugin_state) { plugin_state->current_scene_state = NULL; } -void totp_scene_token_menu_free(PluginState* plugin_state) { +void totp_scene_token_menu_free(const PluginState* plugin_state) { UNUSED(plugin_state); } diff --git a/applications/plugins/totp/scenes/token_menu/totp_scene_token_menu.h b/applications/plugins/totp/scenes/token_menu/totp_scene_token_menu.h index 0b117cb25..acb499be8 100644 --- a/applications/plugins/totp/scenes/token_menu/totp_scene_token_menu.h +++ b/applications/plugins/totp/scenes/token_menu/totp_scene_token_menu.h @@ -7,14 +7,14 @@ #include "../../types/plugin_event.h" typedef struct { - uint8_t current_token_index; + uint16_t current_token_index; } TokenMenuSceneContext; -void totp_scene_token_menu_init(PluginState* plugin_state); +void totp_scene_token_menu_init(const PluginState* plugin_state); void totp_scene_token_menu_activate( PluginState* plugin_state, const TokenMenuSceneContext* context); void totp_scene_token_menu_render(Canvas* const canvas, PluginState* plugin_state); -bool totp_scene_token_menu_handle_event(PluginEvent* const event, PluginState* plugin_state); +bool totp_scene_token_menu_handle_event(const PluginEvent* const event, PluginState* plugin_state); void totp_scene_token_menu_deactivate(PluginState* plugin_state); -void totp_scene_token_menu_free(PluginState* plugin_state); +void totp_scene_token_menu_free(const PluginState* plugin_state); diff --git a/applications/plugins/totp/services/cli/cli.c b/applications/plugins/totp/services/cli/cli.c index 3a7afdd96..76e58a02d 100644 --- a/applications/plugins/totp/services/cli/cli.c +++ b/applications/plugins/totp/services/cli/cli.c @@ -9,7 +9,7 @@ #include "commands/timezone/timezone.h" #include "commands/help/help.h" -static void totp_cli_print_unknown_command(FuriString* unknown_command) { +static void totp_cli_print_unknown_command(const FuriString* unknown_command) { TOTP_CLI_PRINTF( "Command \"%s\" is unknown. Use \"" TOTP_CLI_COMMAND_HELP "\" command to get list of available commands.", diff --git a/applications/plugins/totp/services/cli/cli_helpers.c b/applications/plugins/totp/services/cli/cli_helpers.c index 81a1e4b77..4a0b8b352 100644 --- a/applications/plugins/totp/services/cli/cli_helpers.c +++ b/applications/plugins/totp/services/cli/cli_helpers.c @@ -1,7 +1,7 @@ #include "cli_helpers.h" #include -bool totp_cli_ensure_authenticated(PluginState* plugin_state, Cli* cli) { +bool totp_cli_ensure_authenticated(const PluginState* plugin_state, Cli* cli) { if(plugin_state->current_scene == TotpSceneAuthentication) { TOTP_CLI_PRINTF("Pleases enter PIN on your flipper device\r\n"); @@ -11,7 +11,6 @@ bool totp_cli_ensure_authenticated(PluginState* plugin_state, Cli* cli) { } TOTP_CLI_DELETE_LAST_LINE(); - fflush(stdout); if(plugin_state->current_scene == TotpSceneAuthentication) { return false; diff --git a/applications/plugins/totp/services/cli/cli_helpers.h b/applications/plugins/totp/services/cli/cli_helpers.h index 216925e50..9b19f926b 100644 --- a/applications/plugins/totp/services/cli/cli_helpers.h +++ b/applications/plugins/totp/services/cli/cli_helpers.h @@ -13,16 +13,28 @@ #define DOCOPT_OPTIONS "[options]" #define DOCOPT_DEFAULT(val) "[default: " val "]" -#define TOTP_CLI_PRINTF(format, ...) \ - _Pragma(STRINGIFY(GCC diagnostic push)); \ - _Pragma(STRINGIFY(GCC diagnostic ignored "-Wdouble-promotion")); \ - printf(format, ##__VA_ARGS__); \ - _Pragma(STRINGIFY(GCC diagnostic pop)); +#define TOTP_CLI_PRINTF(format, ...) \ + do { \ + _Pragma(STRINGIFY(GCC diagnostic push)) \ + _Pragma(STRINGIFY(GCC diagnostic ignored "-Wdouble-promotion")) \ + printf(format, ##__VA_ARGS__); \ + _Pragma(STRINGIFY(GCC diagnostic pop)) \ + } while(false) + +#define TOTP_CLI_DELETE_LAST_LINE() \ + TOTP_CLI_PRINTF("\033[A\33[2K\r"); \ + fflush(stdout) + +#define TOTP_CLI_DELETE_CURRENT_LINE() \ + TOTP_CLI_PRINTF("\33[2K\r"); \ + fflush(stdout) + +#define TOTP_CLI_DELETE_LAST_CHAR() \ + TOTP_CLI_PRINTF("\b \b"); \ + fflush(stdout) -#define TOTP_CLI_DELETE_LAST_LINE() TOTP_CLI_PRINTF("\033[A\33[2K\r") -#define TOTP_CLI_DELETE_CURRENT_LINE() TOTP_CLI_PRINTF("\33[2K\r") #define TOTP_CLI_PRINT_INVALID_ARGUMENTS() \ TOTP_CLI_PRINTF( \ "Invalid command arguments. use \"help\" command to get list of available commands") -bool totp_cli_ensure_authenticated(PluginState* plugin_state, Cli* cli); +bool totp_cli_ensure_authenticated(const PluginState* plugin_state, Cli* cli); diff --git a/applications/plugins/totp/services/cli/commands/add/add.c b/applications/plugins/totp/services/cli/commands/add/add.c index 41ff5b860..31548c59e 100644 --- a/applications/plugins/totp/services/cli/commands/add/add.c +++ b/applications/plugins/totp/services/cli/commands/add/add.c @@ -14,7 +14,7 @@ #define TOTP_CLI_COMMAND_ADD_ARG_DIGITS_PREFIX "-d" #define TOTP_CLI_COMMAND_ADD_ARG_UNSECURE_PREFIX "-u" -static bool token_info_set_digits_from_str(TokenInfo* token_info, FuriString* str) { +static bool token_info_set_digits_from_str(TokenInfo* token_info, const FuriString* str) { switch(furi_string_get_char(str, 0)) { case '6': token_info->digits = TOTP_6_DIGITS; @@ -27,7 +27,7 @@ static bool token_info_set_digits_from_str(TokenInfo* token_info, FuriString* st return false; } -static bool token_info_set_algo_from_str(TokenInfo* token_info, FuriString* str) { +static bool token_info_set_algo_from_str(TokenInfo* token_info, const FuriString* str) { if(furi_string_cmpi_str(str, TOTP_CONFIG_TOKEN_ALGO_SHA1_NAME) == 0) { token_info->algo = SHA1; return true; @@ -79,10 +79,53 @@ void totp_cli_command_add_docopt_options() { TOTP_CLI_COMMAND_ADD_ARG_UNSECURE_PREFIX) " Show console user input as-is without masking\r\n"); } +static void furi_string_secure_free(FuriString* str) { + for(long i = furi_string_size(str) - 1; i >= 0; i--) { + furi_string_set_char(str, i, '\0'); + } + + furi_string_free(str); +} + +static bool totp_cli_read_secret(Cli* cli, FuriString* out_str, bool mask_user_input) { + uint8_t c; + while(cli_read(cli, &c, 1) == 1) { + if(c == CliSymbolAsciiEsc) { + // Some keys generating escape-sequences + // We need to ignore them as we case about alpha-numerics only + uint8_t c2; + cli_read_timeout(cli, &c2, 1, 0); + cli_read_timeout(cli, &c2, 1, 0); + } else if(c == CliSymbolAsciiETX) { + TOTP_CLI_DELETE_CURRENT_LINE(); + TOTP_CLI_PRINTF("Cancelled by user\r\n"); + return false; + } else if((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { + if(mask_user_input) { + putc('*', stdout); + } else { + putc(c, stdout); + } + fflush(stdout); + furi_string_push_back(out_str, c); + } else if(c == CliSymbolAsciiBackspace || c == CliSymbolAsciiDel) { + size_t out_str_size = furi_string_size(out_str); + if(out_str_size > 0) { + TOTP_CLI_DELETE_LAST_CHAR(); + furi_string_left(out_str, out_str_size - 1); + } + } else if(c == CliSymbolAsciiCR) { + cli_nl(); + break; + } + } + + TOTP_CLI_DELETE_LAST_LINE(); + return true; +} + void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args, Cli* cli) { FuriString* temp_str = furi_string_alloc(); - const char* temp_cstr; - TokenInfo* token_info = token_info_alloc(); // Reading token name @@ -93,9 +136,9 @@ void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args, Cl return; } - temp_cstr = furi_string_get_cstr(temp_str); - token_info->name = malloc(strlen(temp_cstr) + 1); - strcpy(token_info->name, temp_cstr); + size_t temp_cstr_len = furi_string_size(temp_str); + token_info->name = malloc(temp_cstr_len + 1); + strlcpy(token_info->name, furi_string_get_cstr(temp_str), temp_cstr_len + 1); // Read optional arguments bool mask_user_input = true; @@ -142,59 +185,25 @@ void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args, Cl // Reading token secret furi_string_reset(temp_str); TOTP_CLI_PRINTF("Enter token secret and confirm with [ENTER]\r\n"); - - uint8_t c; - while(cli_read(cli, &c, 1) == 1) { - if(c == CliSymbolAsciiEsc) { - uint8_t c2; - cli_read_timeout(cli, &c2, 1, 0); - cli_read_timeout(cli, &c2, 1, 0); - } else if(c == CliSymbolAsciiETX) { - TOTP_CLI_DELETE_CURRENT_LINE(); - TOTP_CLI_PRINTF("Cancelled by user"); - furi_string_free(temp_str); - token_info_free(token_info); - return; - } else if((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { - if(mask_user_input) { - putc('*', stdout); - } else { - putc(c, stdout); - } - fflush(stdout); - furi_string_push_back(temp_str, c); - } else if(c == CliSymbolAsciiBackspace || c == CliSymbolAsciiDel) { - size_t temp_str_size = furi_string_size(temp_str); - if(temp_str_size > 0) { - TOTP_CLI_PRINTF("\b \b"); - fflush(stdout); - furi_string_left(temp_str, temp_str_size - 1); - } - } else if(c == CliSymbolAsciiCR) { - cli_nl(); - break; - } - } - - temp_cstr = furi_string_get_cstr(temp_str); - - TOTP_CLI_DELETE_LAST_LINE(); - - if(!totp_cli_ensure_authenticated(plugin_state, cli)) { - furi_string_free(temp_str); + if(!totp_cli_read_secret(cli, temp_str, mask_user_input) || + !totp_cli_ensure_authenticated(plugin_state, cli)) { + furi_string_secure_free(temp_str); token_info_free(token_info); return; } - if(!token_info_set_secret(token_info, temp_cstr, strlen(temp_cstr), plugin_state->iv)) { + if(!token_info_set_secret( + token_info, + furi_string_get_cstr(temp_str), + furi_string_size(temp_str), + plugin_state->iv)) { TOTP_CLI_PRINTF("Token secret seems to be invalid and can not be parsed\r\n"); - furi_string_free(temp_str); + furi_string_secure_free(temp_str); token_info_free(token_info); return; } - furi_string_reset(temp_str); - furi_string_free(temp_str); + furi_string_secure_free(temp_str); bool load_generate_token_scene = false; if(plugin_state->current_scene == TotpSceneGenerateToken) { @@ -202,11 +211,7 @@ void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args, Cl load_generate_token_scene = true; } - if(plugin_state->tokens_list == NULL) { - plugin_state->tokens_list = list_init_head(token_info); - } else { - list_add(plugin_state->tokens_list, token_info); - } + TOTP_LIST_INIT_OR_ADD(plugin_state->tokens_list, token_info); plugin_state->tokens_count++; totp_config_file_save_new_token(token_info); diff --git a/applications/plugins/totp/services/config/config.c b/applications/plugins/totp/services/config/config.c index 0854d79ad..e751f7990 100644 --- a/applications/plugins/totp/services/config/config.c +++ b/applications/plugins/totp/services/config/config.c @@ -10,7 +10,7 @@ #define CONFIG_FILE_PATH CONFIG_FILE_DIRECTORY_PATH "/totp.conf" #define CONFIG_FILE_BACKUP_PATH CONFIG_FILE_PATH ".backup" -static uint8_t token_info_get_digits_as_int(TokenInfo* token_info) { +static uint8_t token_info_get_digits_as_int(const TokenInfo* token_info) { switch(token_info->digits) { case TOTP_6_DIGITS: return 6; @@ -32,7 +32,7 @@ static void token_info_set_digits_from_int(TokenInfo* token_info, uint8_t digits } } -static char* token_info_get_algo_as_cstr(TokenInfo* token_info) { +static char* token_info_get_algo_as_cstr(const TokenInfo* token_info) { switch(token_info->algo) { case SHA1: return TOTP_CONFIG_TOKEN_ALGO_SHA1_NAME; @@ -45,7 +45,7 @@ static char* token_info_get_algo_as_cstr(TokenInfo* token_info) { return NULL; } -static void token_info_set_algo_from_str(TokenInfo* token_info, FuriString* str) { +static void token_info_set_algo_from_str(TokenInfo* token_info, const FuriString* str) { if(furi_string_cmpi_str(str, TOTP_CONFIG_TOKEN_ALGO_SHA1_NAME) == 0) { token_info->algo = SHA1; } else if(furi_string_cmpi_str(str, TOTP_CONFIG_TOKEN_ALGO_SHA256_NAME) == 0) { @@ -152,7 +152,7 @@ FlipperFormat* totp_open_config_file(Storage* storage) { return fff_data_file; } -void totp_config_file_save_new_token_i(FlipperFormat* file, TokenInfo* token_info) { +void totp_config_file_save_new_token_i(FlipperFormat* file, const TokenInfo* token_info) { flipper_format_seek_to_end(file); flipper_format_write_string_cstr(file, TOTP_CONFIG_KEY_TOKEN_NAME, token_info->name); bool token_is_valid = token_info->token != NULL && token_info->token_length > 0; @@ -170,7 +170,7 @@ void totp_config_file_save_new_token_i(FlipperFormat* file, TokenInfo* token_inf flipper_format_write_uint32(file, TOTP_CONFIG_KEY_TOKEN_DIGITS, &digits_count_as_uint32, 1); } -void totp_config_file_save_new_token(TokenInfo* token_info) { +void totp_config_file_save_new_token(const TokenInfo* token_info) { Storage* cfg_storage = totp_open_storage(); FlipperFormat* file = totp_open_config_file(cfg_storage); @@ -190,7 +190,7 @@ void totp_config_file_update_timezone_offset(float new_timezone_offset) { totp_close_storage(); } -void totp_full_save_config_file(PluginState* const plugin_state) { +void totp_full_save_config_file(const PluginState* const plugin_state) { Storage* storage = totp_open_storage(); FlipperFormat* fff_data_file = flipper_format_file_alloc(storage); @@ -209,7 +209,7 @@ void totp_full_save_config_file(PluginState* const plugin_state) { flipper_format_write_bool(fff_data_file, TOTP_CONFIG_KEY_PINSET, &plugin_state->pin_set, 1); ListNode* node = plugin_state->tokens_list; while(node != NULL) { - TokenInfo* token_info = node->data; + const TokenInfo* token_info = node->data; totp_config_file_save_new_token_i(fff_data_file, token_info); node = node->next; } @@ -333,7 +333,7 @@ TokenLoadingResult totp_config_file_load_tokens(PluginState* const plugin_state) } TokenLoadingResult result = TokenLoadingResultSuccess; - uint8_t index = 0; + uint16_t index = 0; bool has_any_plain_secret = false; while(true) { @@ -343,9 +343,9 @@ TokenLoadingResult totp_config_file_load_tokens(PluginState* const plugin_state) TokenInfo* tokenInfo = token_info_alloc(); - const char* temp_cstr = furi_string_get_cstr(temp_str); - tokenInfo->name = (char*)malloc(strlen(temp_cstr) + 1); - strcpy(tokenInfo->name, temp_cstr); + size_t temp_cstr_len = furi_string_size(temp_str); + tokenInfo->name = (char*)malloc(temp_cstr_len + 1); + strlcpy(tokenInfo->name, furi_string_get_cstr(temp_str), temp_cstr_len + 1); uint32_t secret_bytes_count; if(!flipper_format_get_value_count( @@ -355,9 +355,11 @@ TokenLoadingResult totp_config_file_load_tokens(PluginState* const plugin_state) if(secret_bytes_count == 1) { // Plain secret key if(flipper_format_read_string(fff_data_file, TOTP_CONFIG_KEY_TOKEN_SECRET, temp_str)) { - temp_cstr = furi_string_get_cstr(temp_str); if(token_info_set_secret( - tokenInfo, temp_cstr, strlen(temp_cstr), &plugin_state->iv[0])) { + tokenInfo, + furi_string_get_cstr(temp_str), + furi_string_size(temp_str), + &plugin_state->iv[0])) { FURI_LOG_W(LOGGING_TAG, "Token \"%s\" has plain secret", tokenInfo->name); } else { tokenInfo->token = NULL; @@ -407,11 +409,7 @@ TokenLoadingResult totp_config_file_load_tokens(PluginState* const plugin_state) FURI_LOG_D(LOGGING_TAG, "Found token \"%s\"", tokenInfo->name); - if(plugin_state->tokens_list == NULL) { - plugin_state->tokens_list = list_init_head(tokenInfo); - } else { - list_add(plugin_state->tokens_list, tokenInfo); - } + TOTP_LIST_INIT_OR_ADD(plugin_state->tokens_list, tokenInfo); index++; } @@ -419,7 +417,7 @@ TokenLoadingResult totp_config_file_load_tokens(PluginState* const plugin_state) plugin_state->tokens_count = index; plugin_state->token_list_loaded = true; - FURI_LOG_D(LOGGING_TAG, "Found %" PRIu8 " tokens", index); + FURI_LOG_D(LOGGING_TAG, "Found %" PRIu16 " tokens", index); furi_string_free(temp_str); totp_close_config_file(fff_data_file); diff --git a/applications/plugins/totp/services/config/config.h b/applications/plugins/totp/services/config/config.h index 76cb40b2c..d452ad4b3 100644 --- a/applications/plugins/totp/services/config/config.h +++ b/applications/plugins/totp/services/config/config.h @@ -16,8 +16,8 @@ Storage* totp_open_storage(); void totp_close_storage(); FlipperFormat* totp_open_config_file(Storage* storage); void totp_close_config_file(FlipperFormat* file); -void totp_full_save_config_file(PluginState* const plugin_state); +void totp_full_save_config_file(const PluginState* const plugin_state); void totp_config_file_load_base(PluginState* const plugin_state); TokenLoadingResult totp_config_file_load_tokens(PluginState* const plugin_state); -void totp_config_file_save_new_token(TokenInfo* token_info); +void totp_config_file_save_new_token(const TokenInfo* token_info); void totp_config_file_update_timezone_offset(float new_timezone_offset); diff --git a/applications/plugins/totp/services/crypto/crypto.c b/applications/plugins/totp/services/crypto/crypto.c index ade2f9f49..79e41e6fd 100644 --- a/applications/plugins/totp/services/crypto/crypto.c +++ b/applications/plugins/totp/services/crypto/crypto.c @@ -3,6 +3,7 @@ #include #include "../config/config.h" #include "../../types/common.h" +#include "memset_s.h" #define CRYPTO_KEY_SLOT 2 #define CRYPTO_VERIFY_KEY "FFF_Crypto_pass" @@ -11,13 +12,13 @@ uint8_t* totp_crypto_encrypt( const uint8_t* plain_data, - const uint8_t plain_data_length, + const size_t plain_data_length, const uint8_t* iv, - uint8_t* encrypted_data_length) { + size_t* encrypted_data_length) { uint8_t* encrypted_data; size_t remain = plain_data_length % CRYPTO_ALIGNMENT_FACTOR; if(remain) { - uint8_t plain_data_aligned_length = plain_data_length - remain + CRYPTO_ALIGNMENT_FACTOR; + size_t plain_data_aligned_length = plain_data_length - remain + CRYPTO_ALIGNMENT_FACTOR; uint8_t* plain_data_aligned = malloc(plain_data_aligned_length); memset(plain_data_aligned, 0, plain_data_aligned_length); memcpy(plain_data_aligned, plain_data, plain_data_length); @@ -29,7 +30,7 @@ uint8_t* totp_crypto_encrypt( furi_hal_crypto_encrypt(plain_data_aligned, encrypted_data, plain_data_aligned_length); furi_hal_crypto_store_unload_key(CRYPTO_KEY_SLOT); - memset(plain_data_aligned, 0, plain_data_aligned_length); + memset_s(plain_data_aligned, sizeof(plain_data_aligned), 0, plain_data_aligned_length); free(plain_data_aligned); } else { encrypted_data = malloc(plain_data_length); @@ -45,9 +46,9 @@ uint8_t* totp_crypto_encrypt( uint8_t* totp_crypto_decrypt( const uint8_t* encrypted_data, - const uint8_t encrypted_data_length, + const size_t encrypted_data_length, const uint8_t* iv, - uint8_t* decrypted_data_length) { + size_t* decrypted_data_length) { *decrypted_data_length = encrypted_data_length; uint8_t* decrypted_data = malloc(*decrypted_data_length); furi_hal_crypto_store_load_key(CRYPTO_KEY_SLOT, iv); @@ -56,7 +57,7 @@ uint8_t* totp_crypto_decrypt( return decrypted_data; } -void totp_crypto_seed_iv(PluginState* plugin_state, uint8_t* pin, uint8_t pin_length) { +void totp_crypto_seed_iv(PluginState* plugin_state, const uint8_t* pin, uint8_t pin_length) { if(plugin_state->crypto_verify_data == NULL) { FURI_LOG_D(LOGGING_TAG, "Generating new IV"); furi_hal_random_fill_buf(&plugin_state->base_iv[0], TOTP_IV_SIZE); @@ -118,8 +119,8 @@ void totp_crypto_seed_iv(PluginState* plugin_state, uint8_t* pin, uint8_t pin_le } bool totp_crypto_verify_key(const PluginState* plugin_state) { - uint8_t decrypted_key_length; - uint8_t* decrypted_key = totp_crypto_decrypt( + size_t decrypted_key_length; + const uint8_t* decrypted_key = totp_crypto_decrypt( plugin_state->crypto_verify_data, plugin_state->crypto_verify_data_length, &plugin_state->iv[0], diff --git a/applications/plugins/totp/services/crypto/crypto.h b/applications/plugins/totp/services/crypto/crypto.h index 9fc319659..f0a28f798 100644 --- a/applications/plugins/totp/services/crypto/crypto.h +++ b/applications/plugins/totp/services/crypto/crypto.h @@ -4,13 +4,13 @@ uint8_t* totp_crypto_encrypt( const uint8_t* plain_data, - const uint8_t plain_data_length, + const size_t plain_data_length, const uint8_t* iv, - uint8_t* encrypted_data_length); + size_t* encrypted_data_length); uint8_t* totp_crypto_decrypt( const uint8_t* encrypted_data, - const uint8_t encrypted_data_length, + const size_t encrypted_data_length, const uint8_t* iv, - uint8_t* decrypted_data_length); -void totp_crypto_seed_iv(PluginState* plugin_state, uint8_t* pin, uint8_t pin_length); + size_t* decrypted_data_length); +void totp_crypto_seed_iv(PluginState* plugin_state, const uint8_t* pin, uint8_t pin_length); bool totp_crypto_verify_key(const PluginState* plugin_state); \ No newline at end of file diff --git a/applications/plugins/totp/services/crypto/memset_s.c b/applications/plugins/totp/services/crypto/memset_s.c new file mode 100644 index 000000000..81c285c0d --- /dev/null +++ b/applications/plugins/totp/services/crypto/memset_s.c @@ -0,0 +1,22 @@ +#include "memset_s.h" + +#define RSIZE_MAX 0x7fffffffffffffffUL + +errno_t memset_s(void* s, rsize_t smax, int c, rsize_t n) { + if(!s || smax > RSIZE_MAX) { + return EINVAL; + } + + errno_t violation_present = 0; + if(n > smax) { + n = smax; + violation_present = EINVAL; + } + + volatile unsigned char* v = s; + for(rsize_t i = 0u; i < n; ++i) { + *v++ = (unsigned char)c; + } + + return violation_present; +} \ No newline at end of file diff --git a/applications/plugins/totp/services/crypto/memset_s.h b/applications/plugins/totp/services/crypto/memset_s.h new file mode 100644 index 000000000..2889e23b2 --- /dev/null +++ b/applications/plugins/totp/services/crypto/memset_s.h @@ -0,0 +1,16 @@ +#pragma once + +#include +#include +#include + +#ifndef _RSIZE_T_DECLARED +typedef uint64_t rsize_t; +#define _RSIZE_T_DECLARED +#endif +#ifndef _ERRNOT_DECLARED +typedef int16_t errno_t; +#define _ERRNOT_DECLARED +#endif + +errno_t memset_s(void* s, rsize_t smax, int c, rsize_t n); \ No newline at end of file diff --git a/applications/plugins/totp/services/list/list.c b/applications/plugins/totp/services/list/list.c index 3a3317980..20d92e71b 100644 --- a/applications/plugins/totp/services/list/list.c +++ b/applications/plugins/totp/services/list/list.c @@ -26,7 +26,7 @@ ListNode* list_add(ListNode* head, void* data) { return head; } -ListNode* list_find(ListNode* head, void* data) { +ListNode* list_find(ListNode* head, const void* data) { ListNode* it; for(it = head; it != NULL; it = it->next) @@ -66,7 +66,8 @@ ListNode* list_remove(ListNode* head, ListNode* ep) { } void list_free(ListNode* head) { - ListNode *it = head, *tmp; + ListNode* it = head; + ListNode* tmp; while(it != NULL) { tmp = it; diff --git a/applications/plugins/totp/services/list/list.h b/applications/plugins/totp/services/list/list.h index 771eac565..93acb0f34 100644 --- a/applications/plugins/totp/services/list/list.h +++ b/applications/plugins/totp/services/list/list.h @@ -14,7 +14,7 @@ ListNode* list_add( void* data); /* adds element with specified data to the end of the list and returns new head node. */ ListNode* list_find( ListNode* head, - void* data); /* returns pointer of element with specified data in list. */ + const void* data); /* returns pointer of element with specified data in list. */ ListNode* list_element_at( ListNode* head, uint16_t index); /* returns pointer of element with specified index in list. */ @@ -22,3 +22,12 @@ ListNode* list_remove( ListNode* head, ListNode* ep); /* removes element from the list and returns new head node. */ void list_free(ListNode* head); /* deletes all elements of the list. */ + +#define TOTP_LIST_INIT_OR_ADD(head, item) \ + do { \ + if(head == NULL) { \ + head = list_init_head(item); \ + } else { \ + list_add(head, item); \ + } \ + } while(false) diff --git a/applications/plugins/totp/services/nullable/nullable.h b/applications/plugins/totp/services/nullable/nullable.h new file mode 100644 index 000000000..4f9b7bc01 --- /dev/null +++ b/applications/plugins/totp/services/nullable/nullable.h @@ -0,0 +1,17 @@ +#pragma once + +#include +#include + +#define TOTP_NULLABLE_STRUCT(value_type) \ + typedef struct TotpNullable_##value_type { \ + bool is_null; \ + value_type value; \ + } TotpNullable_##value_type + +#define TOTP_NULLABLE_NULL(s) s.is_null = true +#define TOTP_NULLABLE_VALUE(s, v) \ + s.is_null = false; \ + s.value = v + +TOTP_NULLABLE_STRUCT(uint16_t); diff --git a/applications/plugins/totp/services/roll_value/roll_value.c b/applications/plugins/totp/services/roll_value/roll_value.c new file mode 100644 index 000000000..b8f30e078 --- /dev/null +++ b/applications/plugins/totp/services/roll_value/roll_value.c @@ -0,0 +1,28 @@ +#include "roll_value.h" + +#define TOTP_ROLL_VALUE_FN(type, step_type) \ + TOTP_ROLL_VALUE_FN_HEADER(type, step_type) { \ + type v = *value; \ + if(step > 0 && v > max - step) { \ + if(overflow_behavior == RollOverflowBehaviorRoll) { \ + v = min; \ + } else if(overflow_behavior == RollOverflowBehaviorStop) { \ + v = max; \ + } \ + } else if(step < 0 && v < min - step) { \ + if(overflow_behavior == RollOverflowBehaviorRoll) { \ + v = max; \ + } else if(overflow_behavior == RollOverflowBehaviorStop) { \ + v = min; \ + } \ + } else { \ + v += step; \ + } \ + *value = v; \ + } + +TOTP_ROLL_VALUE_FN(int8_t, int8_t) + +TOTP_ROLL_VALUE_FN(uint8_t, int8_t) + +TOTP_ROLL_VALUE_FN(uint16_t, int16_t); \ No newline at end of file diff --git a/applications/plugins/totp/services/roll_value/roll_value.h b/applications/plugins/totp/services/roll_value/roll_value.h new file mode 100644 index 000000000..87337597f --- /dev/null +++ b/applications/plugins/totp/services/roll_value/roll_value.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +typedef enum { RollOverflowBehaviorStop, RollOverflowBehaviorRoll } TotpRollValueOverflowBehavior; + +#define TOTP_ROLL_VALUE_FN_HEADER(type, step_type) \ + void totp_roll_value_##type( \ + type* value, \ + step_type step, \ + type min, \ + type max, \ + TotpRollValueOverflowBehavior overflow_behavior) + +TOTP_ROLL_VALUE_FN_HEADER(int8_t, int8_t); +TOTP_ROLL_VALUE_FN_HEADER(uint8_t, int8_t); +TOTP_ROLL_VALUE_FN_HEADER(uint16_t, int16_t); \ No newline at end of file diff --git a/applications/plugins/totp/services/totp/totp.c b/applications/plugins/totp/services/totp/totp.c index 90e49367d..68531e171 100644 --- a/applications/plugins/totp/services/totp/totp.c +++ b/applications/plugins/totp/services/totp/totp.c @@ -42,14 +42,14 @@ uint32_t otp_generate( TOTP_ALGO algo, uint8_t digits, const uint8_t* plain_secret, - uint8_t plain_secret_length, + size_t plain_secret_length, uint64_t input) { uint8_t* hmac = malloc(64); memset(hmac, 0, 64); uint64_t input_swapped = swap_uint64(input); - int hmac_len = (*(algo))(plain_secret, plain_secret_length, (uint8_t*)&input_swapped, 8, hmac); + int hmac_len = (*algo)(plain_secret, plain_secret_length, (uint8_t*)&input_swapped, 8, hmac); if(hmac_len == 0) { free(hmac); return OTP_ERROR; @@ -80,7 +80,7 @@ uint32_t totp_at( TOTP_ALGO algo, uint8_t digits, const uint8_t* plain_secret, - uint8_t plain_secret_length, + size_t plain_secret_length, uint64_t for_time, float timezone, uint8_t interval) { @@ -96,9 +96,9 @@ uint32_t totp_at( static int totp_algo_sha1( const uint8_t* key, - uint8_t key_length, + size_t key_length, const uint8_t* input, - uint8_t input_length, + size_t input_length, uint8_t* output) { hmac_sha1(key, key_length, input, input_length, output); return HMAC_SHA1_RESULT_SIZE; @@ -106,9 +106,9 @@ static int totp_algo_sha1( static int totp_algo_sha256( const uint8_t* key, - uint8_t key_length, + size_t key_length, const uint8_t* input, - uint8_t input_length, + size_t input_length, uint8_t* output) { hmac_sha256(key, key_length, input, input_length, output); return HMAC_SHA256_RESULT_SIZE; @@ -116,9 +116,9 @@ static int totp_algo_sha256( static int totp_algo_sha512( const uint8_t* key, - uint8_t key_length, + size_t key_length, const uint8_t* input, - uint8_t input_length, + size_t input_length, uint8_t* output) { hmac_sha512(key, key_length, input, input_length, output); return HMAC_SHA512_RESULT_SIZE; diff --git a/applications/plugins/totp/services/totp/totp.h b/applications/plugins/totp/services/totp/totp.h index 31e70e01b..431ca11aa 100644 --- a/applications/plugins/totp/services/totp/totp.h +++ b/applications/plugins/totp/services/totp/totp.h @@ -17,9 +17,9 @@ */ typedef int (*TOTP_ALGO)( const uint8_t* key, - uint8_t key_length, + size_t key_length, const uint8_t* input, - uint8_t input_length, + size_t input_length, uint8_t* output); /* @@ -47,7 +47,7 @@ uint32_t totp_at( TOTP_ALGO algo, uint8_t digits, const uint8_t* plain_secret, - uint8_t plain_secret_length, + size_t plain_secret_length, uint64_t for_time, float timezone, uint8_t interval); diff --git a/applications/plugins/totp/services/ui/icons.h b/applications/plugins/totp/services/ui/icons.h deleted file mode 100644 index 2ce25a898..000000000 --- a/applications/plugins/totp/services/ui/icons.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include -#include - -#define ICON_ARROW_LEFT_8x9_WIDTH 8 -#define ICON_ARROW_LEFT_8x9_HEIGHT 9 -static const uint8_t ICON_ARROW_LEFT_8x9[] = {0x80, 0xe0, 0xf8, 0xfe, 0xff, 0xfe, 0xf8, 0xe0, 0x80}; - -#define ICON_ARROW_RIGHT_8x9_WIDTH 8 -#define ICON_ARROW_RIGHT_8x9_HEIGHT 9 -static const uint8_t ICON_ARROW_RIGHT_8x9[] = - {0x01, 0x07, 0x1f, 0x7f, 0xff, 0x7f, 0x1f, 0x07, 0x01}; diff --git a/applications/plugins/totp/services/ui/ui_controls.c b/applications/plugins/totp/services/ui/ui_controls.c index 7f6a4dd4d..af029dd9f 100644 --- a/applications/plugins/totp/services/ui/ui_controls.c +++ b/applications/plugins/totp/services/ui/ui_controls.c @@ -1,11 +1,15 @@ #include "ui_controls.h" +#include #include "constants.h" -#include "icons.h" #define TEXT_BOX_HEIGHT 13 #define TEXT_BOX_MARGIN 4 -void ui_control_text_box_render(Canvas* const canvas, int8_t y, char* text, bool is_selected) { +void ui_control_text_box_render( + Canvas* const canvas, + int16_t y, + const char* text, + bool is_selected) { if(y < -TEXT_BOX_HEIGHT) { return; } @@ -44,7 +48,7 @@ void ui_control_select_render( int16_t x, int16_t y, uint8_t width, - char* text, + const char* text, bool is_selected) { if(y < -TEXT_BOX_HEIGHT) { return; @@ -77,20 +81,10 @@ void ui_control_select_render( canvas_draw_str_aligned( canvas, x + (width >> 1), TEXT_BOX_MARGIN + 3 + y, AlignCenter, AlignTop, text); - canvas_draw_xbm( - canvas, - x + TEXT_BOX_MARGIN + 2, - TEXT_BOX_MARGIN + 2 + y, - ICON_ARROW_LEFT_8x9_WIDTH, - ICON_ARROW_LEFT_8x9_HEIGHT, - &ICON_ARROW_LEFT_8x9[0]); - canvas_draw_xbm( - canvas, - x + width - TEXT_BOX_MARGIN - 10, - TEXT_BOX_MARGIN + 2 + y, - ICON_ARROW_RIGHT_8x9_WIDTH, - ICON_ARROW_RIGHT_8x9_HEIGHT, - &ICON_ARROW_RIGHT_8x9[0]); + canvas_draw_icon( + canvas, x + TEXT_BOX_MARGIN + 2, TEXT_BOX_MARGIN + 2 + y, &I_totp_arrow_left_8x9); + canvas_draw_icon( + canvas, x + width - TEXT_BOX_MARGIN - 10, TEXT_BOX_MARGIN + 2 + y, &I_totp_arrow_right_8x9); } void ui_control_button_render( @@ -99,7 +93,7 @@ void ui_control_button_render( int16_t y, uint8_t width, uint8_t height, - char* text, + const char* text, bool is_selected) { if(y < -height) { return; diff --git a/applications/plugins/totp/services/ui/ui_controls.h b/applications/plugins/totp/services/ui/ui_controls.h index e86b3e5d9..ef3af5f55 100644 --- a/applications/plugins/totp/services/ui/ui_controls.h +++ b/applications/plugins/totp/services/ui/ui_controls.h @@ -3,19 +3,23 @@ #include #include -void ui_control_text_box_render(Canvas* const canvas, int8_t y, char* text, bool is_selected); +void ui_control_text_box_render( + Canvas* const canvas, + int16_t y, + const char* text, + bool is_selected); void ui_control_button_render( Canvas* const canvas, int16_t x, int16_t y, uint8_t width, uint8_t height, - char* text, + const char* text, bool is_selected); void ui_control_select_render( Canvas* const canvas, int16_t x, int16_t y, uint8_t width, - char* text, + const char* text, bool is_selected); diff --git a/applications/plugins/totp/totp_app.c b/applications/plugins/totp/totp_app.c index ede8416b6..3bc85e211 100644 --- a/applications/plugins/totp/totp_app.c +++ b/applications/plugins/totp/totp_app.c @@ -24,7 +24,7 @@ static void render_callback(Canvas* const canvas, void* ctx) { PluginState* plugin_state = acquire_mutex((ValueMutex*)ctx, 25); - if(plugin_state != NULL && !plugin_state->changing_scene) { + if (plugin_state != NULL && !plugin_state->changing_scene) { totp_scene_director_render(canvas, plugin_state); } @@ -49,43 +49,29 @@ static bool totp_plugin_state_init(PluginState* const plugin_state) { totp_scene_director_init_scenes(plugin_state); - if(plugin_state->crypto_verify_data == NULL) { + if (plugin_state->crypto_verify_data == NULL) { DialogMessage* message = dialog_message_alloc(); dialog_message_set_buttons(message, "No", NULL, "Yes"); - dialog_message_set_text( - message, - "Would you like to setup PIN?", - SCREEN_WIDTH_CENTER, - SCREEN_HEIGHT_CENTER, - AlignCenter, - AlignCenter); + dialog_message_set_text(message, "Would you like to setup PIN?", SCREEN_WIDTH_CENTER, SCREEN_HEIGHT_CENTER, AlignCenter, AlignCenter); DialogMessageButton dialog_result = dialog_message_show(plugin_state->dialogs, message); dialog_message_free(message); - if(dialog_result == DialogMessageButtonRight) { + if (dialog_result == DialogMessageButtonRight) { totp_scene_director_activate_scene(plugin_state, TotpSceneAuthentication, NULL); } else { totp_crypto_seed_iv(plugin_state, NULL, 0); totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL); } - } else if(plugin_state->pin_set) { + } else if (plugin_state->pin_set) { totp_scene_director_activate_scene(plugin_state, TotpSceneAuthentication, NULL); } else { totp_crypto_seed_iv(plugin_state, NULL, 0); - if(totp_crypto_verify_key(plugin_state)) { + if (totp_crypto_verify_key(plugin_state)) { totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL); } else { - FURI_LOG_E( - LOGGING_TAG, - "Digital signature verification failed. Looks like conf file was created on another flipper and can't be used on any other"); + FURI_LOG_E(LOGGING_TAG, "Digital signature verification failed. Looks like conf file was created on another flipper and can't be used on any other"); DialogMessage* message = dialog_message_alloc(); dialog_message_set_buttons(message, "Exit", NULL, NULL); - dialog_message_set_text( - message, - "Digital signature verification failed", - SCREEN_WIDTH_CENTER, - SCREEN_HEIGHT_CENTER, - AlignCenter, - AlignCenter); + dialog_message_set_text(message, "Digital signature verification failed", SCREEN_WIDTH_CENTER, SCREEN_HEIGHT_CENTER, AlignCenter, AlignCenter); dialog_message_show(plugin_state->dialogs, message); dialog_message_free(message); return false; @@ -108,7 +94,7 @@ static void totp_plugin_state_free(PluginState* plugin_state) { ListNode* node = plugin_state->tokens_list; ListNode* tmp; - while(node != NULL) { + while (node != NULL) { tmp = node->next; TokenInfo* tokenInfo = node->data; token_info_free(tokenInfo); @@ -116,7 +102,7 @@ static void totp_plugin_state_free(PluginState* plugin_state) { node = tmp; } - if(plugin_state->crypto_verify_data != NULL) { + if (plugin_state->crypto_verify_data != NULL) { free(plugin_state->crypto_verify_data); } free(plugin_state); @@ -126,7 +112,7 @@ int32_t totp_app() { FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(PluginEvent)); PluginState* plugin_state = malloc(sizeof(PluginState)); - if(!totp_plugin_state_init(plugin_state)) { + if (!totp_plugin_state_init(plugin_state)) { FURI_LOG_E(LOGGING_TAG, "App state initialization failed\r\n"); totp_plugin_state_free(plugin_state); return 254; @@ -151,25 +137,23 @@ int32_t totp_app() { bool processing = true; uint32_t last_user_interaction_time = furi_get_tick(); while(processing) { - if(plugin_state->changing_scene) continue; + if (plugin_state->changing_scene) continue; FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); - PluginState* plugin_state = acquire_mutex_block(&state_mutex); + PluginState* plugin_state_m = acquire_mutex_block(&state_mutex); if(event_status == FuriStatusOk) { - if(event.type == EventTypeKey) { + if (event.type == EventTypeKey) { last_user_interaction_time = furi_get_tick(); } - processing = totp_scene_director_handle_event(&event, plugin_state); - } else if( - plugin_state->pin_set && plugin_state->current_scene != TotpSceneAuthentication && - furi_get_tick() - last_user_interaction_time > IDLE_TIMEOUT) { - totp_scene_director_activate_scene(plugin_state, TotpSceneAuthentication, NULL); + processing = totp_scene_director_handle_event(&event, plugin_state_m); + } else if (plugin_state_m->pin_set && plugin_state_m->current_scene != TotpSceneAuthentication && furi_get_tick() - last_user_interaction_time > IDLE_TIMEOUT) { + totp_scene_director_activate_scene(plugin_state_m, TotpSceneAuthentication, NULL); } view_port_update(view_port); - release_mutex(&state_mutex, plugin_state); + release_mutex(&state_mutex, plugin_state_m); } view_port_enabled_set(view_port, false); diff --git a/applications/plugins/totp/types/plugin_state.h b/applications/plugins/totp/types/plugin_state.h index 98afe53cf..9b16d7d57 100644 --- a/applications/plugins/totp/types/plugin_state.h +++ b/applications/plugins/totp/types/plugin_state.h @@ -19,10 +19,10 @@ typedef struct { float timezone_offset; ListNode* tokens_list; bool token_list_loaded; - uint8_t tokens_count; + uint16_t tokens_count; uint8_t* crypto_verify_data; - uint8_t crypto_verify_data_length; + size_t crypto_verify_data_length; bool pin_set; uint8_t iv[TOTP_IV_SIZE]; uint8_t base_iv[TOTP_IV_SIZE]; diff --git a/applications/plugins/totp/types/token_info.c b/applications/plugins/totp/types/token_info.c index 09ad1230a..17b2af9aa 100644 --- a/applications/plugins/totp/types/token_info.c +++ b/applications/plugins/totp/types/token_info.c @@ -5,6 +5,7 @@ #include "common.h" #include "../services/base32/base32.h" #include "../services/crypto/crypto.h" +#include "../services/crypto/memset_s.h" TokenInfo* token_info_alloc() { TokenInfo* tokenInfo = malloc(sizeof(TokenInfo)); @@ -23,11 +24,11 @@ void token_info_free(TokenInfo* token_info) { bool token_info_set_secret( TokenInfo* token_info, const char* base32_token_secret, - uint8_t token_secret_length, - uint8_t* iv) { + size_t token_secret_length, + const uint8_t* iv) { uint8_t* plain_secret = malloc(token_secret_length); int plain_secret_length = - base32_decode((uint8_t*)base32_token_secret, plain_secret, token_secret_length); + base32_decode((const uint8_t*)base32_token_secret, plain_secret, token_secret_length); bool result; if(plain_secret_length >= 0) { token_info->token = @@ -37,12 +38,12 @@ bool token_info_set_secret( result = false; } - memset(plain_secret, 0, token_secret_length); + memset_s(plain_secret, sizeof(plain_secret), 0, token_secret_length); free(plain_secret); return result; } -uint8_t token_info_get_digits_count(TokenInfo* token_info) { +uint8_t token_info_get_digits_count(const TokenInfo* token_info) { switch(token_info->digits) { case TOTP_6_DIGITS: return 6; diff --git a/applications/plugins/totp/types/token_info.h b/applications/plugins/totp/types/token_info.h index e40c6e9bf..4f1223367 100644 --- a/applications/plugins/totp/types/token_info.h +++ b/applications/plugins/totp/types/token_info.h @@ -8,7 +8,7 @@ typedef enum { TOTP_6_DIGITS, TOTP_8_DIGITS } TokenDigitsCount; typedef struct { uint8_t* token; - uint8_t token_length; + size_t token_length; char* name; TokenHashAlgo algo; TokenDigitsCount digits; @@ -19,6 +19,6 @@ void token_info_free(TokenInfo* token_info); bool token_info_set_secret( TokenInfo* token_info, const char* base32_token_secret, - uint8_t token_secret_length, - uint8_t* iv); -uint8_t token_info_get_digits_count(TokenInfo* token_info); + size_t token_secret_length, + const uint8_t* iv); +uint8_t token_info_get_digits_count(const TokenInfo* token_info); From fe199ab54a054f52b6609274933bdcf14e9ee10a Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Wed, 2 Nov 2022 23:19:33 +0300 Subject: [PATCH 16/23] Fix part 2 --- applications/plugins/arkanoid/arkanoid_game.c | 7 +++---- applications/plugins/barcode_generator/barcode_generator.c | 5 ++--- applications/plugins/flappy_bird/flappy_bird.c | 5 ++--- applications/plugins/gps_nmea_uart/gps.c | 4 ++-- applications/plugins/minesweeper/minesweeper.c | 4 ++++ applications/plugins/mousejacker/mousejacker.c | 2 ++ applications/plugins/nrfsniff/nrfsniff.c | 2 ++ applications/plugins/sentry_safe/sentry_safe.c | 2 ++ applications/plugins/tictactoe_game/tictactoe_game.c | 5 ++--- 9 files changed, 21 insertions(+), 15 deletions(-) diff --git a/applications/plugins/arkanoid/arkanoid_game.c b/applications/plugins/arkanoid/arkanoid_game.c index 91ae8e736..d0026e226 100644 --- a/applications/plugins/arkanoid/arkanoid_game.c +++ b/applications/plugins/arkanoid/arkanoid_game.c @@ -448,14 +448,13 @@ int32_t arkanoid_game_app(void* p) { arkanoid_state->ball_state.dy = -1; //start the game flag arkanoid_state->gameStarted = true; - break; } + break; + default: + break; } } } - } else { - // Event timeout - FURI_LOG_D(TAG, "furi_message_queue: Event timeout"); } view_port_update(view_port); diff --git a/applications/plugins/barcode_generator/barcode_generator.c b/applications/plugins/barcode_generator/barcode_generator.c index d03d45495..0418d672c 100644 --- a/applications/plugins/barcode_generator/barcode_generator.c +++ b/applications/plugins/barcode_generator/barcode_generator.c @@ -523,12 +523,11 @@ int32_t barcode_UPCA_generator_app(void* p) { plugin_state->modeIndex = 0; } break; + default: + break; } } } - } else { - FURI_LOG_D("barcode_UPCA_generator", "osMessageQueue: event timeout"); - // event timeout } view_port_update(view_port); diff --git a/applications/plugins/flappy_bird/flappy_bird.c b/applications/plugins/flappy_bird/flappy_bird.c index 9895c2c31..37b8fdebe 100644 --- a/applications/plugins/flappy_bird/flappy_bird.c +++ b/applications/plugins/flappy_bird/flappy_bird.c @@ -345,14 +345,13 @@ int32_t flappy_game_app(void* p) { case InputKeyBack: processing = false; break; + default: + break; } } } else if(event.type == EventTypeTick) { flappy_game_tick(game_state); } - } else { - //FURI_LOG_D(TAG, "osMessageQueue: event timeout"); - // event timeout } view_port_update(view_port); diff --git a/applications/plugins/gps_nmea_uart/gps.c b/applications/plugins/gps_nmea_uart/gps.c index 1df4882b5..62053cede 100644 --- a/applications/plugins/gps_nmea_uart/gps.c +++ b/applications/plugins/gps_nmea_uart/gps.c @@ -110,11 +110,11 @@ int32_t gps_app(void* p) { case InputKeyBack: processing = false; break; + default: + break; } } } - } else { - FURI_LOG_D("GPS", "FuriMessageQueue: event timeout"); } view_port_update(view_port); diff --git a/applications/plugins/minesweeper/minesweeper.c b/applications/plugins/minesweeper/minesweeper.c index 95044c04c..fa9fdcc78 100644 --- a/applications/plugins/minesweeper/minesweeper.c +++ b/applications/plugins/minesweeper/minesweeper.c @@ -476,6 +476,8 @@ int32_t minesweeper_app(void* p) { // Exit the plugin processing = false; break; + default: + break; } } else if(event.input.type == InputTypeLong) { // hold events @@ -493,6 +495,8 @@ int32_t minesweeper_app(void* p) { case InputKeyBack: processing = false; break; + default: + break; } } } diff --git a/applications/plugins/mousejacker/mousejacker.c b/applications/plugins/mousejacker/mousejacker.c index 79067bce3..3b1b2e6f7 100644 --- a/applications/plugins/mousejacker/mousejacker.c +++ b/applications/plugins/mousejacker/mousejacker.c @@ -372,6 +372,8 @@ int32_t mousejacker_app(void* p) { plugin_state->close_thread_please = false; processing = false; break; + default: + break; } } } diff --git a/applications/plugins/nrfsniff/nrfsniff.c b/applications/plugins/nrfsniff/nrfsniff.c index 315db831c..094775426 100644 --- a/applications/plugins/nrfsniff/nrfsniff.c +++ b/applications/plugins/nrfsniff/nrfsniff.c @@ -399,6 +399,8 @@ int32_t nrfsniff_app(void* p) { case InputKeyBack: if(event.input.type == InputTypeLong) processing = false; break; + default: + break; } } } diff --git a/applications/plugins/sentry_safe/sentry_safe.c b/applications/plugins/sentry_safe/sentry_safe.c index f88661beb..4d9c12fc7 100644 --- a/applications/plugins/sentry_safe/sentry_safe.c +++ b/applications/plugins/sentry_safe/sentry_safe.c @@ -143,6 +143,8 @@ int32_t sentry_safe_app(void* p) { case InputKeyBack: processing = false; break; + default: + break; } } } diff --git a/applications/plugins/tictactoe_game/tictactoe_game.c b/applications/plugins/tictactoe_game/tictactoe_game.c index b3a0d5c84..fe57d7c62 100644 --- a/applications/plugins/tictactoe_game/tictactoe_game.c +++ b/applications/plugins/tictactoe_game/tictactoe_game.c @@ -358,12 +358,11 @@ int32_t tictactoe_game_app(void* p) { case InputKeyOk: tictactoe_state->button_state = true; break; + default: + break; } } } - } else { - // Event timeout - FURI_LOG_D(TAG, "furi_message_queue: Event timeout"); } view_port_update(view_port); From 0b2867aaa411f7544023b6763e23fa58e8773f7b Mon Sep 17 00:00:00 2001 From: nminaylov Date: Wed, 2 Nov 2022 17:43:47 +0300 Subject: [PATCH 17/23] BadUSB scrolllock typo fix --- applications/main/bad_usb/bad_usb_script.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/main/bad_usb/bad_usb_script.c b/applications/main/bad_usb/bad_usb_script.c index 4d6066c17..41b6a21ea 100644 --- a/applications/main/bad_usb/bad_usb_script.c +++ b/applications/main/bad_usb/bad_usb_script.c @@ -86,7 +86,7 @@ static const DuckyKey ducky_keys[] = { {"PAGEUP", HID_KEYBOARD_PAGE_UP}, {"PAGEDOWN", HID_KEYBOARD_PAGE_DOWN}, {"PRINTSCREEN", HID_KEYBOARD_PRINT_SCREEN}, - {"SCROLLOCK", HID_KEYBOARD_SCROLL_LOCK}, + {"SCROLLLOCK", HID_KEYBOARD_SCROLL_LOCK}, {"SPACE", HID_KEYBOARD_SPACEBAR}, {"TAB", HID_KEYBOARD_TAB}, {"MENU", HID_KEYBOARD_APPLICATION}, From 345d9704fd70857943df75354402a989b940a3ed Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Wed, 2 Nov 2022 23:39:54 +0300 Subject: [PATCH 18/23] Plugins: Added Game15 + run fbt format --- applications/plugins/game15/README.md | 13 + applications/plugins/game15/application.fam | 12 + applications/plugins/game15/game15.c | 469 ++++++++++++++++++ applications/plugins/game15/game15_10px.png | Bin 0 -> 152 bytes applications/plugins/game15/images/Game15.png | Bin 0 -> 2078 bytes .../plugins/game15/images/Game15Popup.png | Bin 0 -> 2267 bytes .../plugins/game15/images/Game15Restore.png | Bin 0 -> 2156 bytes applications/plugins/game15/sandbox.c | 93 ++++ applications/plugins/game15/sandbox.h | 24 + applications/plugins/gps_nmea_uart/README.md | 1 + applications/plugins/morse_code/morse_code.c | 97 ++-- .../plugins/morse_code/morse_code_worker.c | 70 ++- .../plugins/morse_code/morse_code_worker.h | 10 +- applications/plugins/totp/totp_app.c | 44 +- 14 files changed, 727 insertions(+), 106 deletions(-) create mode 100644 applications/plugins/game15/README.md create mode 100644 applications/plugins/game15/application.fam create mode 100644 applications/plugins/game15/game15.c create mode 100644 applications/plugins/game15/game15_10px.png create mode 100644 applications/plugins/game15/images/Game15.png create mode 100644 applications/plugins/game15/images/Game15Popup.png create mode 100644 applications/plugins/game15/images/Game15Restore.png create mode 100644 applications/plugins/game15/sandbox.c create mode 100644 applications/plugins/game15/sandbox.h diff --git a/applications/plugins/game15/README.md b/applications/plugins/game15/README.md new file mode 100644 index 000000000..b1710c919 --- /dev/null +++ b/applications/plugins/game15/README.md @@ -0,0 +1,13 @@ + +# Game "15" for Flipper Zero + +[Original link](https://github.com/x27/flipperzero-game15) + +Logic game [Wikipedia](https://en.wikipedia.org/wiki/15_puzzle) + +![Game screen](images/Game15.png) + +![Restore game](images/Game15Restore.png) + +![Popoup](images/Game15Popup.png) + diff --git a/applications/plugins/game15/application.fam b/applications/plugins/game15/application.fam new file mode 100644 index 000000000..ab00316c1 --- /dev/null +++ b/applications/plugins/game15/application.fam @@ -0,0 +1,12 @@ +App( + appid="game15", + name="Game 15", + apptype=FlipperAppType.EXTERNAL, + entry_point="game15_app", + cdefines=["APP_GAME15"], + requires=["gui"], + stack_size=1 * 1024, + fap_icon="game15_10px.png", + order=30, + fap_category="Games", +) diff --git a/applications/plugins/game15/game15.c b/applications/plugins/game15/game15.c new file mode 100644 index 000000000..aad5f1330 --- /dev/null +++ b/applications/plugins/game15/game15.c @@ -0,0 +1,469 @@ +#include +#include +#include +#include +#include + +#include "sandbox.h" + +#define FPS 20 +#define CELL_WIDTH 10 +#define CELL_HEIGHT 8 +#define MOVE_TICKS 5 +#define KEY_STACK_SIZE 16 +#define SAVING_DIRECTORY "/ext/apps/Games" +#define SAVING_FILENAME SAVING_DIRECTORY "/game15.save" +#define POPUP_MENU_ITEMS 2 + +typedef enum { + DirectionNone, + DirectionUp, + DirectionDown, + DirectionLeft, + DirectionRight +} direction_e; + +typedef enum { ScenePlay, SceneWin, ScenePopup } scene_e; + +typedef struct { + uint8_t cell_index; + uint8_t zero_index; + uint8_t move_direction; + uint8_t move_ticks; +} moving_cell_t; + +typedef struct { + uint16_t top_record; + scene_e scene; + uint16_t move_count; + uint32_t tick_count; + uint8_t board[16]; +} game_state_t; + +static game_state_t game_state; +static NotificationApp* notification; +static moving_cell_t moving_cell; +static uint8_t loaded_saving_ticks; +static uint8_t popup_menu_selected_item; + +static const char* popup_menu_strings[] = {"Continue", "Reset"}; + +static uint8_t keys[KEY_STACK_SIZE]; +static uint8_t key_stack_head = 0; + +static const uint8_t pic_cells[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x30, 0xfc, 0x38, 0xfc, 0x30, 0xfc, 0x30, 0xfc, 0x30, 0xfc, 0x30, 0xfc, 0x30, 0xfc, 0x30, 0xfc, + 0x78, 0xfc, 0xcc, 0xfc, 0xcc, 0xfc, 0x60, 0xfc, 0x30, 0xfc, 0x18, 0xfc, 0x0c, 0xfc, 0xfc, 0xfc, + 0x78, 0xfc, 0xcc, 0xfc, 0xcc, 0xfc, 0x60, 0xfc, 0xc0, 0xfc, 0xcc, 0xfc, 0xcc, 0xfc, 0x78, 0xfc, + 0x70, 0xfc, 0x78, 0xfc, 0x68, 0xfc, 0x6c, 0xfc, 0x6c, 0xfc, 0xec, 0xfc, 0xfc, 0xfc, 0x60, 0xfc, + 0xfc, 0xfc, 0x0c, 0xfc, 0x0c, 0xfc, 0x7c, 0xfc, 0xc0, 0xfc, 0xcc, 0xfc, 0xcc, 0xfc, 0x78, 0xfc, + 0x78, 0xfc, 0x0c, 0xfc, 0x0c, 0xfc, 0x7c, 0xfc, 0xcc, 0xfc, 0xcc, 0xfc, 0xcc, 0xfc, 0x78, 0xfc, + 0xfc, 0xfc, 0xc0, 0xfc, 0xc0, 0xfc, 0xc0, 0xfc, 0xc0, 0xfc, 0xc0, 0xfc, 0xc0, 0xfc, 0xc0, 0xfc, + 0x78, 0xfc, 0xcc, 0xfc, 0xcc, 0xfc, 0x78, 0xfc, 0xcc, 0xfc, 0xcc, 0xfc, 0xcc, 0xfc, 0x78, 0xfc, + 0x78, 0xfc, 0xcc, 0xfc, 0xcc, 0xfc, 0xcc, 0xfc, 0xf8, 0xfc, 0xc0, 0xfc, 0xc0, 0xfc, 0x78, 0xfc, + 0xe6, 0xfd, 0x37, 0xff, 0x36, 0xff, 0x36, 0xff, 0x36, 0xff, 0x36, 0xff, 0x36, 0xff, 0xe6, 0xfd, + 0x8c, 0xfd, 0xce, 0xfd, 0x8c, 0xfd, 0x8c, 0xfd, 0x8c, 0xfd, 0x8c, 0xfd, 0x8c, 0xfd, 0x8c, 0xfd, + 0xe6, 0xfd, 0x37, 0xff, 0x36, 0xff, 0x86, 0xfd, 0xc6, 0xfc, 0x66, 0xfc, 0x36, 0xfc, 0xf6, 0xff, + 0xe6, 0xfd, 0x37, 0xff, 0x36, 0xff, 0x86, 0xfd, 0x06, 0xff, 0x36, 0xff, 0x36, 0xff, 0xe6, 0xfd, + 0xc6, 0xfd, 0xe7, 0xfd, 0xa6, 0xfd, 0xb6, 0xfd, 0xb6, 0xfd, 0xb6, 0xff, 0xf6, 0xff, 0x86, 0xfd, + 0xf6, 0xff, 0x37, 0xfc, 0x36, 0xfc, 0xf6, 0xfd, 0x06, 0xff, 0x36, 0xff, 0x36, 0xff, 0xe6, 0xfd, +}; + +static const uint8_t pic_digits[] = { + 0xf0, 0xf2, 0xf2, 0xf2, 0xf2, 0xf0, 0xf9, 0xf8, 0xf9, 0xf9, 0xf9, 0xf0, 0xf0, 0xf2, 0xf3, + 0xf1, 0xfc, 0xf0, 0xf0, 0xf3, 0xf1, 0xf3, 0xf2, 0xf0, 0xf3, 0xf1, 0xf2, 0xf2, 0xf0, 0xf3, + 0xf0, 0xfc, 0xf0, 0xf3, 0xf2, 0xf0, 0x00, 0x0c, 0x00, 0x02, 0x02, 0x00, 0x00, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x00, 0x03, 0x03, 0x00, +}; + +static const uint8_t pic_top[] = {11, 4, 0x88, 0xf8, 0xad, 0xfa, 0xad, 0xf8, 0x8d, 0xfe}; +static const uint8_t pic_move[] = + {17, 4, 0x2e, 0x2a, 0xfe, 0xa4, 0xaa, 0xff, 0xaa, 0x2a, 0xff, 0x2e, 0x36, 0xfe}; +static const uint8_t pic_time[] = {15, 4, 0xa8, 0x8b, 0x2d, 0xe9, 0xad, 0xca, 0xad, 0x8b}; + +static const uint8_t pic_puzzled[] = { + 0xff, 0xcf, 0x00, 0xf3, 0xff, 0xfc, 0x3f, 0x03, 0xc0, 0xff, 0xf3, 0x0f, 0xdc, 0xff, 0xcf, + 0x00, 0xf3, 0xff, 0xfc, 0x3f, 0x03, 0xc0, 0xff, 0xf3, 0x0f, 0xdc, 0x03, 0xcc, 0x00, 0x03, + 0x38, 0x00, 0x0e, 0x03, 0xc0, 0x00, 0x30, 0x30, 0xdc, 0x03, 0xcc, 0x00, 0x03, 0x1c, 0x00, + 0x07, 0x03, 0xc0, 0x00, 0x30, 0x30, 0xdc, 0xff, 0xcf, 0x00, 0x03, 0x0e, 0x80, 0x03, 0x03, + 0xc0, 0xff, 0x33, 0xc0, 0xdc, 0xff, 0xcf, 0x00, 0x03, 0x07, 0xc0, 0x01, 0x03, 0xc0, 0xff, + 0x33, 0xc0, 0xdc, 0x03, 0xc0, 0x00, 0x83, 0x03, 0xe0, 0x00, 0x03, 0xc0, 0x00, 0x30, 0xc0, + 0xd0, 0x03, 0xc0, 0x00, 0xc3, 0x01, 0x70, 0x00, 0x03, 0xc0, 0x00, 0x30, 0xc0, 0xd0, 0x03, + 0xc0, 0xff, 0xf3, 0xff, 0xfc, 0x3f, 0xff, 0xcf, 0xff, 0xf3, 0xff, 0xdc, 0x03, 0xc0, 0xff, + 0xf3, 0xff, 0xfc, 0x3f, 0xff, 0xcf, 0xff, 0xf3, 0xff, 0xdc}; + +static void key_stack_init() { + key_stack_head = 0; +} + +static uint8_t key_stack_pop() { + return keys[--key_stack_head]; +} + +static bool key_stack_is_empty() { + return key_stack_head == 0; +} + +static int key_stack_push(uint8_t value) { + if(key_stack_head != KEY_STACK_SIZE) { + keys[key_stack_head] = value; + key_stack_head++; + return key_stack_head; + } else + return -1; +} + +static bool storage_game_state_load() { + Storage* storage = furi_record_open(RECORD_STORAGE); + File* file = storage_file_alloc(storage); + + uint16_t bytes_readed = 0; + if(storage_file_open(file, SAVING_FILENAME, FSAM_READ, FSOM_OPEN_EXISTING)) + bytes_readed = storage_file_read(file, &game_state, sizeof(game_state_t)); + storage_file_close(file); + storage_file_free(file); + furi_record_close(RECORD_STORAGE); + return bytes_readed == sizeof(game_state_t); +} + +static void storage_game_state_save() { + Storage* storage = furi_record_open(RECORD_STORAGE); + + if(storage_common_stat(storage, SAVING_DIRECTORY, NULL) == FSE_NOT_EXIST) { + if(!storage_simply_mkdir(storage, SAVING_DIRECTORY)) { + return; + } + } + + File* file = storage_file_alloc(storage); + if(storage_file_open(file, SAVING_FILENAME, FSAM_WRITE, FSOM_CREATE_ALWAYS)) { + storage_file_write(file, &game_state, sizeof(game_state_t)); + } + storage_file_close(file); + storage_file_free(file); + furi_record_close(RECORD_STORAGE); +} + +static void set_moving_cell_by_direction(direction_e direction) { + moving_cell.move_direction = DirectionNone; + moving_cell.zero_index = 0xff; + + for(int i = 0; i < 16; i++) { + if(!game_state.board[i]) { + moving_cell.zero_index = i; + break; + } + } + if(moving_cell.zero_index == 0xff) return; + + uint8_t x = moving_cell.zero_index % 4; + uint8_t y = moving_cell.zero_index / 4; + + moving_cell.cell_index = moving_cell.zero_index; + + if(direction == DirectionUp && y < 3) + moving_cell.cell_index += 4; + else if(direction == DirectionDown && y > 0) + moving_cell.cell_index -= 4; + else if(direction == DirectionLeft && x < 3) + moving_cell.cell_index++; + else if(direction == DirectionRight && x > 0) + moving_cell.cell_index--; + else + return; + + moving_cell.move_ticks = 0; + moving_cell.move_direction = direction; +} + +static bool is_board_has_solution() { + uint8_t i, j, inv = 0; + for(i = 0; i < 16; ++i) + if(game_state.board[i]) + for(j = 0; j < i; ++j) + if(game_state.board[j] > game_state.board[i]) ++inv; + for(i = 0; i < 16; ++i) + if(game_state.board[i] == 0) inv += 1 + i / 4; + + return inv % 2 == 0; +} + +static void board_init() { + for(int i = 0; i < 16; i++) { + game_state.board[i] = (i + 1) % 16; + } + + do { + for(int i = 15; i >= 1; i--) { + int j = rand() % (i + 1); + uint8_t tmp = game_state.board[j]; + game_state.board[j] = game_state.board[i]; + game_state.board[i] = tmp; + } + } while(!is_board_has_solution()); +} + +static void game_init() { + game_state.scene = ScenePlay; + game_state.move_count = 0; + game_state.tick_count = 0; + moving_cell.move_direction = DirectionNone; + board_init(); + key_stack_init(); + popup_menu_selected_item = 0; +} + +static bool is_board_solved() { + for(int i = 0; i < 16; i++) + if(((i + 1) % 16) != game_state.board[i]) return false; + return true; +} + +static void game_tick() { + switch(game_state.scene) { + case ScenePlay: + game_state.tick_count++; + if(loaded_saving_ticks) loaded_saving_ticks--; + if(moving_cell.move_direction == DirectionNone && !key_stack_is_empty()) { + set_moving_cell_by_direction(key_stack_pop()); + if(moving_cell.move_direction == DirectionNone) { + notification_message(notification, &sequence_single_vibro); + key_stack_init(); + } + } + + if(moving_cell.move_direction != DirectionNone) { + moving_cell.move_ticks++; + if(moving_cell.move_ticks == MOVE_TICKS) { + game_state.board[moving_cell.zero_index] = + game_state.board[moving_cell.cell_index]; + game_state.board[moving_cell.cell_index] = 0; + moving_cell.move_direction = DirectionNone; + game_state.move_count++; + } + if(is_board_solved()) { + notification_message(notification, &sequence_double_vibro); + if(game_state.move_count < game_state.top_record || game_state.top_record == 0) { + game_state.top_record = game_state.move_count; + storage_game_state_save(); + } + game_state.scene = SceneWin; + } + } + break; + + case SceneWin: + if(!key_stack_is_empty()) game_init(); + break; + + case ScenePopup: + if(!key_stack_is_empty()) { + switch(key_stack_pop()) { + case DirectionDown: + popup_menu_selected_item++; + popup_menu_selected_item = popup_menu_selected_item % POPUP_MENU_ITEMS; + break; + case DirectionUp: + popup_menu_selected_item--; + popup_menu_selected_item = popup_menu_selected_item % POPUP_MENU_ITEMS; + break; + case DirectionNone: + if(popup_menu_selected_item == 0) { + game_state.scene = ScenePlay; + notification_message(notification, &sequence_single_vibro); + } else if(popup_menu_selected_item == 1) { + notification_message(notification, &sequence_single_vibro); + game_init(); + } + break; + } + } + break; + } +} + +static void draw_cell(Canvas* canvas, uint8_t x, uint8_t y, uint8_t cell_number) { + canvas_set_color(canvas, ColorBlack); + canvas_draw_rframe(canvas, x, y, 18, 14, 1); + canvas_set_color(canvas, ColorBlack); + canvas_draw_xbm(canvas, x + 4, y + 3, CELL_WIDTH, CELL_HEIGHT, pic_cells + cell_number * 16); +} + +static void board_draw(Canvas* canvas) { + for(int i = 0; i < 16; i++) { + if(game_state.board[i]) { + if(moving_cell.move_direction == DirectionNone || moving_cell.cell_index != i) + draw_cell(canvas, (i % 4) * 20 + 7, (i / 4) * 16 + 1, game_state.board[i]); + if(moving_cell.move_direction != DirectionNone && moving_cell.cell_index == i) { + uint8_t from_x = (moving_cell.cell_index % 4) * 20 + 7; + uint8_t from_y = (moving_cell.cell_index / 4) * 16 + 1; + uint8_t to_x = (moving_cell.zero_index % 4) * 20 + 7; + uint8_t to_y = (moving_cell.zero_index / 4) * 16 + 1; + int now_x = from_x + (to_x - from_x) * moving_cell.move_ticks / MOVE_TICKS; + int now_y = from_y + (to_y - from_y) * moving_cell.move_ticks / MOVE_TICKS; + draw_cell(canvas, now_x, now_y, game_state.board[i]); + } + } + } +} + +static void number_draw(Canvas* canvas, uint8_t y, uint32_t value) { + uint8_t x = 121; + while(true) { + uint8_t digit = value % 10; + canvas_draw_xbm(canvas, x, y, 4, 6, pic_digits + digit * 6); + x -= 5; + value = value / 10; + if(!value) break; + } +} + +static void plate_draw( + Canvas* canvas, + uint8_t y, + const uint8_t* header, + uint32_t value, + bool dont_draw_zero_value) { + canvas_set_color(canvas, ColorBlack); + canvas_draw_rbox(canvas, 92, y, 35, 19, 2); + canvas_set_color(canvas, ColorBlack); + canvas_draw_xbm(canvas, 95, y + 3, header[0], header[1], &header[2]); + if((!value && !dont_draw_zero_value) || value) number_draw(canvas, y + 10, value); +} + +static void info_draw(Canvas* canvas) { + plate_draw(canvas, 1, pic_top, game_state.top_record, true); + plate_draw(canvas, 22, pic_move, game_state.move_count, false); + plate_draw(canvas, 43, pic_time, game_state.tick_count / FPS, false); +} + +static void gray_screen(Canvas* const canvas) { + canvas_set_color(canvas, ColorWhite); + for(int x = 0; x < 128; x += 2) { + for(int y = 0; y < 64; y++) { + canvas_draw_dot(canvas, x + (y % 2 == 1 ? 0 : 1), y); + } + } +} + +static void render_callback(Canvas* const canvas) { + canvas_set_color(canvas, ColorWhite); + canvas_draw_box(canvas, 0, 0, 128, 64); + + if(game_state.scene == ScenePlay || game_state.scene == SceneWin || + game_state.scene == ScenePopup) { + canvas_set_color(canvas, ColorBlack); + board_draw(canvas); + info_draw(canvas); + + if(loaded_saving_ticks && game_state.scene != ScenePopup) { + canvas_set_color(canvas, ColorWhite); + canvas_draw_rbox(canvas, 20, 24, 88, 16, 4); + canvas_set_color(canvas, ColorBlack); + canvas_draw_rframe(canvas, 20, 24, 88, 16, 4); + canvas_draw_str_aligned(canvas, 64, 32, AlignCenter, AlignCenter, "Restore game ..."); + } + } + + if(game_state.scene == SceneWin) { + gray_screen(canvas); + canvas_draw_box(canvas, 7, 20, 114, 24); + canvas_set_color(canvas, ColorBlack); + canvas_draw_box(canvas, 8, 21, 112, 22); + canvas_set_color(canvas, ColorWhite); + canvas_draw_box(canvas, 10, 23, 108, 18); + canvas_set_color(canvas, ColorBlack); + canvas_draw_xbm(canvas, 14, 27, 100, 10, pic_puzzled); + } else if(game_state.scene == ScenePopup) { + gray_screen(canvas); + canvas_set_color(canvas, ColorWhite); + canvas_draw_rbox(canvas, 28, 16, 72, 32, 4); + canvas_set_color(canvas, ColorBlack); + canvas_draw_rframe(canvas, 28, 16, 72, 32, 4); + + for(int i = 0; i < POPUP_MENU_ITEMS; i++) { + if(i == popup_menu_selected_item) { + canvas_set_color(canvas, ColorBlack); + canvas_draw_box(canvas, 34, 20 + 12 * i, 60, 12); + } + + canvas_set_color(canvas, i == popup_menu_selected_item ? ColorWhite : ColorBlack); + canvas_draw_str_aligned( + canvas, 64, 26 + 12 * i, AlignCenter, AlignCenter, popup_menu_strings[i]); + } + } +} + +static void game_event_handler(GameEvent const event) { + if(event.type == EventTypeKey) { + if(event.input.type == InputTypePress) { + switch(event.input.key) { + case InputKeyUp: + key_stack_push(DirectionUp); + break; + case InputKeyDown: + key_stack_push(DirectionDown); + break; + case InputKeyRight: + key_stack_push(DirectionRight); + break; + case InputKeyLeft: + key_stack_push(DirectionLeft); + break; + case InputKeyOk: + if(game_state.scene == ScenePlay) { + game_state.scene = ScenePopup; + key_stack_init(); + } else + key_stack_push(DirectionNone); + break; + case InputKeyBack: + if(game_state.scene == ScenePopup) { + game_state.scene = ScenePlay; + } else { + storage_game_state_save(); + sandbox_loop_exit(); + } + break; + default: + break; + } + } + } else if(event.type == EventTypeTick) { + game_tick(); + } +} + +static void game_alloc() { + srand(DWT->CYCCNT); + key_stack_init(); + notification = furi_record_open(RECORD_NOTIFICATION); + notification_message_block(notification, &sequence_display_backlight_enforce_on); +} + +static void game_free() { + notification_message_block(notification, &sequence_display_backlight_enforce_auto); + furi_record_close(RECORD_NOTIFICATION); +} + +int32_t game15_app() { + game_alloc(); + game_init(); + + loaded_saving_ticks = 0; + if(storage_game_state_load()) { + if(game_state.scene != ScenePlay) + game_init(); + else + loaded_saving_ticks = FPS; + } else + game_init(); + + sandbox_init( + FPS, (SandboxRenderCallback)render_callback, (SandboxEventHandler)game_event_handler); + sandbox_loop(); + sandbox_free(); + game_free(); + return 0; +} diff --git a/applications/plugins/game15/game15_10px.png b/applications/plugins/game15/game15_10px.png new file mode 100644 index 0000000000000000000000000000000000000000..16c4f103806d90d1b8b2c6467487398774db40a6 GIT binary patch literal 152 zcmeAS@N?(olHy`uVBq!ia0vp^AT}2xGmzZ=C-xtZVk{1FcVbv~PUa<$!;&U>c zv7h@-A}f&37T^=&3Z(!4|G)I+{JTIFXMsm#F#`kNVGw3Kp1&dmC@Age;us=vIhmp9 q7h78cTU&vFB)gjfTfl@yMuv<^cBUmM%QAt=7(8A5T-G@yGywn)A1I#y literal 0 HcmV?d00001 diff --git a/applications/plugins/game15/images/Game15.png b/applications/plugins/game15/images/Game15.png new file mode 100644 index 0000000000000000000000000000000000000000..f13c2907b531fa5441541ac53a96347f7684ae72 GIT binary patch literal 2078 zcmaJ?X;4#F7`+dqh_X0ztW`v?j-!=P+GYf?grJ}-Do{lzm_SiW1f-zs2@%F+T!Fd) zk+4{*gs@f#2mu0a86hN!VN;US5hMi2Lm+uVBxz6_E_T`3_;ZqOSZN7<&5%IS4 z*LF(`o=#Zvo=hG;$FLnRx+6=oFtPJ>d3NwEx5oHrO>2AKsr}~4w^BmNG~%2W?45#u zyww0~Hv*|XDdie{u11rf%ulo!zk;@>M+G+Eyr#%W^)&z%vJZbT`a(S< zvG3x&-!$^>b_ZvCV4S*hpmHg2UXOq!o&cOS2jJ#{xyQi9Wlt9sMx=3q3v){;(}}!8 z_!voEtiXSWG(C0LZ!VbCX6!6fICeCuhK4x9LYyv&A~3^l1ytJZ%Npn9W7S0#b)(+t& z4;#$&%m;~=BHq6Wfa-iUP74h(LC1go&kXCS$WmhMDq;hz zI4eC=;PE*{SLG6NeS7e}s9^b8I>b%j2`ljX>$sf?>u&#a&imPy&RKFX-Ld_y>$3I__Z!llU*Q*@2`Iu?(j!6A^!GKIi=>PUr%T3tnP z$bovDsw5aiFT-7#ruDSSno*?b)a(+q1UZAKy}7l1`AI<%a`8ksNdL68D!mO%r-Z5> zl_#?NY%!KP~q$IWQ@km1MSxDkD+0D8`s^Lwj&Ou5g z+Pc=b-mo|^+e|3nJ|K1djS|-o)MJhk6UCECh>rt&&?5Yck^SXx^vH;NAgM&k$>HP~ zwk~H4xG3pJma29GO@FRsU3fglE|V&bOU_*vTl3P94+$sodwu4O9{bRmh`!)7O0O7e zDsGpa#o%%q$-tjDScG=k6XI;GkKgk@Bn^ah8I)j0!<6Md;-RoAw@w*1c#_jWcFU*q!kW6W+?j{p9m@O=YWJLH zMIS^n8V~5f>nt7zfW^X0F7wfj{VH_gp+= z?@vjQkL+p?vNW0wto$A0Dx}rV9Ght;)Mo~jyzHlp{6s25rPB%b_M#UWi1E?kq={c4 z4OizOzUtScUiR51*BzQo)!j0hc34zr&gaWnXj$I6ELFe;+Bbj)?R=4EVyCP`C;69r ze(0lm@*C+js97Cj*|m=|8@=#~qRu!Lof_fSn}v(9Jvl!{cE`|^OTJxEH-3!3-XuBn zNOA;HGOOP>_3kaa;U82|J?{dZ4e_ose&^=v^fqQNVO%0lxCg@+iP!&HdB0ud?X9-- zD#Ju|?Yr@(u$!1EVO-_Cpuk{OR60`{m5Wv#VV5hoE`beeiaK}L!o}N+LAUe*eu!?L zoIaJqH3T`Irtin4Ryh?=gqeP*F}8J{QPO13k;AYSwfc#!rUn_$?r+ik@PWq;FW2(z HznuIBq;E*m literal 0 HcmV?d00001 diff --git a/applications/plugins/game15/images/Game15Popup.png b/applications/plugins/game15/images/Game15Popup.png new file mode 100644 index 0000000000000000000000000000000000000000..1df14729fc0e2bf59b9603ba5a0ee159ccadc6e3 GIT binary patch literal 2267 zcmZWre^3)=8vX*M@y8fw9hy50#9qfKQ_h2;9E}=4%N4O#VJZOwLU7b#;Y1(=G$D|) z?J(L?`~~Wv1d3D$7%Tzf5!qy}RuoAhN|FkMFmSS%01Lz_|L*ZPK_SXY><4p9FQr*^AZ}ehiLg?V$r3hE=udcN7n^T#lr#PX6^&avB8#rhG{L_5NXdYu2;vxGc>+uaZ<7qn zOG?L9fen}NJvRcd6AL9zw=2+_MR|}mNeCHHquJEQ0Wog_Q2PdmZnzK*gt|;FMC+BB zZn;hc15tw4((3jFnkvndEiE)af6_S8o5V=7V@BH5r6a7~2!rZ=`K>8|W~8`RldSWPNthz7uA504-&SX*FuPcT%i zRdf&j_($Uy=(m~FB#=w>)E!37wa&!WUq=GDfGd`xbLP)1A>a=yJ%kyemDiB)u9y0j zmdHJFhcHo5B1hks;tIU}qN*G@VG<0rF+?nlJXM*BRiUdzyFBF{revHnyC%|{4<=sf zW2Ke$d$Kl5QB)h$h0|2vQU&2evgR40tR}~SScWOna;K!ul`br2;B9`(qb9CL2QGAF zAtWoXR7JHfTP!K2)TAmWq?kUrvD|D&uOkLqmQmwqv@yp3_$UT%u3L=>pEoXz>my3D zet|Chm43Kr{oe#!RT%|)#WL6RkihhMk1`zvYid&IlikojC678c@vwhinbNz-Am2|~ z0(5id0@Fvbz~S`P>FOMzwM$Rv;e~Kf+mIY_etf-9X#L5OO35kq9gO7A2gMcT0bwVci}Xe4{jlUgyv7e4l165j3nl(7;}H|U!o zJzed};mqD=R%T)ojYyLC%BJ55d(Oj?H6x2V%SzB$8x@@YwP9{-*ce6*H8e-gjcWs6 zo;ll*Pk+}*6<*(06MhIe=OjH*@69YaJFbuCKrXKh7d)q_ zz1sWd{3ucTK5FB|1?MZ_qSdyEP>IAwQ;p9AR~u-mGPYoZZvGSvfNZjOtn(-f@%?l5 z(2=VI$FcI`hfgD;MTKLLZFOB=`?Dsx>TyF6Oa4IYJ+5Dr{2Uu}fC9FT+Z_kyi2z~b zbIl{^_iu0I0->4MxJ%)pM^EiLPG-g0`_1}HBvjmXm;yv5Pnn62(xU|(wqA)dN3}n| zMQNUO5MAC)Q$>8@%+vdxU2jCj2@YKlPlI6fG&S z7~x%Fh_ZY5h^9IC8ryexoe`aVY#=yX@9-WECD%}kJ2wmGHzR_dswaAM-yMUFFW36{ z>V};#wnei&l5LCJo+=CE%*Z0&=WLr5OyLqHnMMh*+78iGr?rZD`D&OQ()imqS7BZh z5Vib^AjK_&9Lg_tc#CL8`vAKhdO-l&#ElXu?$W{FV+^b!gqqupxtD|Cw>SJ9DotBX zcF7o12KsaALp~_h*CM6=Y3I!;4&iOy>uFJUdUQnYBA83D3GZoXnKrbNa6%8S0aw1T zA;uzsJAH!Q^(5tGDXGm;nszrNq0E3lK3twa+0m&qx=iY)lfo@{|3m+m$J1xpT*v$8 zzwf0dN05OCfL-o^Q_)PiVLSg!6LH4jU{2!WMoe_XM0?(Wf$Q%+~On5Hk_s_zHjXEfF3agM-R@i0#6?upOWGKC0zBu z>8viq)ru$P@GQPH)-qr>rr*#QIyyN+98E3(6`v@6-Gm@Tsf)A_W><9R0RFcE;{LKH KM!GZOr_%0p2jT8RpRf&qLG3|7O#kd%P<=;%;^ z7Evn(NEL>sC@2(!1Z-6ztr8UyC6b3j%}PQNP?BvDNE!+qFZ|fKyR&=F{l0U)^WDwa z8Ae_>|I_&ZfQ6x3H|+*smi-n3oF9p;8!rBhcbT*En)2)7pF)xYyF==)=IuMO@l*e{OJ@D*oSLM+jKd*Ccg75QMYeTr zaH%3F3xLdX_7q*ZJw%w^-=R04CZ{ znTOJ8LxemQZB?zvXDBnUXbA{jiJ9CZsmEb!RbQQPeJM}h61PLj=DF&Sg6Ba5!43rR z?@@V@$FB$8I@elkd;@nZ9-=u4oGCee~zL z7r3i^NTRBZS}w4iB9>VWe6J`cIL|$G@_)z)SfwQ6UERR7f^Uo~kkbV}avnfgnuai- zyqdk@2Z)RJASTzy9z0SZq1mhL+Xb_WQ5iuK_9;ZAn#l&9o+{N$epp&+(8u1P(5EG1%bJCjf6jNFb@ zAc*!&$Q)<`@f}A{e48Uuc^PNTQf7ZFQ+&m5?4Ibs#u0f^W0ZBr%P5)c+cIP;#J)Fb z^Rba|%N2gpFZo2TWS;;4?BU*a8L8hPpavCEUT1q=d^*O7)5fLi7hi*FVF#}Wm3ivc z*BC_aVl|#?A@Pz?;BBPXdILA#_m8w-NaJS8NCnkAYjO-^NrV}RR>{$A`FDEe3i zm=}q9Mx~u6$}|=n1UDiStE^z&@zC-$Y=fY>Oy5292%q*HLu@}jUbdz+ z%@Zom9_!Nkbiap%99Oa4-#v?F=sP3Uw;PI@OAGgU=))L?kTwdhRaZ)y(f(%}($()N zB)xk}wThG4f#AEvCU0vHtm8j9An8Jfs*Y(^m{^pak*h(E?y29_Wpm*PD|bvz)wUd> z9IW`NySLZKpWSIVtO)PrcUxy^%^+8ZO&{@p6?5^jmp)wYLe zp5_km|2psw$=BmE@YHEiT@hRqGjy}#TysQ_5GcB!A@Gnnyz1+rF-1%L_S0G@x@QSm z+v6DY`gCOtmy9|nkIOVxHz5Pk@(m8CwH$Hie>gp%yY_WBwM_9ns#4=-hwHWduNKi& zAIkKRxvWtVrB-;)EPJlcRGT9+St>#;kM(>zNjNOGss@14Wy;N%C$LI-C2c;nf3*8e zzOc9x+M#I>bHDC*jiu)T1k!F~d#MB2;o~O~DdpVmkZU@WkEC`V@Ldk9!?AiV->ag0hRvw#+QW;u` z-~Q&n5k;a^_l`x&uOx{uU^xK0rwmxuDC%19pHcV>^^TC!)t0hD+hI9K`B)Ht*l_Q3 zL34&Hb%t@E#Aqq;pr${&+Yq3LdAahsCmgy>?pS|!v5-#dytrPDCzKSb8~UStI&#pD z2xgoJLIF0uF`rFaXwB`Bq}F%7JRPvChXkAldfzml@fEHX0ts!h_P zZ!?q35mjtL4peF44ac8{bx$jsJGtrd)?{i`{f8&dh6&jwE@9&Kza3vQ)#-9of4Fop=sqpgMTI96j$<3RQTtCJWJ6MH_o@P zD_jWxC+o>Bhwa7-VjvTv@pwi0^a7*xES`?yIx21;u<_<=FgGRmwwJ*QqE&~yiL`$r zfGa +#include +#include "sandbox.h" + +FuriMessageQueue* sandbox_event_queue; +FuriMutex** sandbox_mutex; +ViewPort* sandbox_view_port; +Gui* sandbox_gui; +FuriTimer* sandbox_timer; +bool sandbox_loop_processing; +SandboxRenderCallback sandbox_user_render_callback; +SandboxEventHandler sandbox_user_event_handler; + +static void sandbox_render_callback(Canvas* const canvas, void* context) { + UNUSED(context); + if(furi_mutex_acquire(sandbox_mutex, 25) != FuriStatusOk) return; + + if(sandbox_user_render_callback) sandbox_user_render_callback(canvas); + + furi_mutex_release(sandbox_mutex); +} + +static void sandbox_input_callback(InputEvent* input_event, void* context) { + UNUSED(context); + GameEvent event = {.type = EventTypeKey, .input = *input_event}; + furi_message_queue_put(sandbox_event_queue, &event, FuriWaitForever); +} + +static void sandbox_timer_callback(void* context) { + UNUSED(context); + GameEvent event = {.type = EventTypeTick}; + furi_message_queue_put(sandbox_event_queue, &event, 0); +} + +void sandbox_loop() { + sandbox_loop_processing = true; + while(sandbox_loop_processing) { + GameEvent event; + FuriStatus event_status = furi_message_queue_get(sandbox_event_queue, &event, 100); + if(event_status != FuriStatusOk) { + // timeout + continue; + } + + furi_mutex_acquire(sandbox_mutex, FuriWaitForever); + + if(sandbox_user_event_handler) sandbox_user_event_handler(event); + + view_port_update(sandbox_view_port); + furi_mutex_release(sandbox_mutex); + } +} + +void sandbox_loop_exit() { + sandbox_loop_processing = false; +} + +void sandbox_init( + uint8_t fps, + SandboxRenderCallback u_render_callback, + SandboxEventHandler u_event_handler) { + sandbox_user_render_callback = u_render_callback; + sandbox_user_event_handler = u_event_handler; + + sandbox_event_queue = furi_message_queue_alloc(8, sizeof(GameEvent)); + sandbox_mutex = furi_mutex_alloc(FuriMutexTypeNormal); + + sandbox_view_port = view_port_alloc(); + view_port_draw_callback_set(sandbox_view_port, sandbox_render_callback, NULL); + view_port_input_callback_set(sandbox_view_port, sandbox_input_callback, NULL); + + sandbox_gui = furi_record_open(RECORD_GUI); + gui_add_view_port(sandbox_gui, sandbox_view_port, GuiLayerFullscreen); + + if(fps > 0) { + sandbox_timer = furi_timer_alloc(sandbox_timer_callback, FuriTimerTypePeriodic, NULL); + furi_timer_start(sandbox_timer, furi_kernel_get_tick_frequency() / fps); + } else + sandbox_timer = NULL; +} + +void sandbox_free() { + if(sandbox_timer) furi_timer_free(sandbox_timer); + + gui_remove_view_port(sandbox_gui, sandbox_view_port); + view_port_enabled_set(sandbox_view_port, false); + view_port_free(sandbox_view_port); + + if(furi_mutex_acquire(sandbox_mutex, FuriWaitForever) == FuriStatusOk) { + furi_mutex_free(sandbox_mutex); + } + furi_message_queue_free(sandbox_event_queue); +} diff --git a/applications/plugins/game15/sandbox.h b/applications/plugins/game15/sandbox.h new file mode 100644 index 000000000..ea7dff37b --- /dev/null +++ b/applications/plugins/game15/sandbox.h @@ -0,0 +1,24 @@ +#pragma once + +#include + +typedef enum { + EventTypeTick, + EventTypeKey, +} EventType; + +typedef struct { + EventType type; + InputEvent input; +} GameEvent; + +typedef void (*SandboxRenderCallback)(Canvas* canvas); +typedef void (*SandboxEventHandler)(GameEvent event); + +void sandbox_init( + uint8_t fps, + SandboxRenderCallback render_callback, + SandboxEventHandler event_handler); +void sandbox_loop(); +void sandbox_loop_exit(); +void sandbox_free(); diff --git a/applications/plugins/gps_nmea_uart/README.md b/applications/plugins/gps_nmea_uart/README.md index 5e36dabda..7af0fa3b3 100644 --- a/applications/plugins/gps_nmea_uart/README.md +++ b/applications/plugins/gps_nmea_uart/README.md @@ -1,6 +1,7 @@ # GPS for Flipper Zero [Original link](https://github.com/ezod/flipperzero-gps) + [Adafruit Ultimate GPS Breakout]. ![ui](ui.png) diff --git a/applications/plugins/morse_code/morse_code.c b/applications/plugins/morse_code/morse_code.c index 0b4790721..a29454371 100644 --- a/applications/plugins/morse_code/morse_code.c +++ b/applications/plugins/morse_code/morse_code.c @@ -27,7 +27,6 @@ typedef struct { MorseCodeWorker* worker; } MorseCode; - static void render_callback(Canvas* const canvas, void* ctx) { MorseCode* morse_code = ctx; furi_check(furi_mutex_acquire(morse_code->model_mutex, FuriWaitForever) == FuriStatusOk); @@ -35,20 +34,26 @@ static void render_callback(Canvas* const canvas, void* ctx) { canvas_set_font(canvas, FontPrimary); //write words - elements_multiline_text_aligned(canvas, 64, 30, AlignCenter, AlignCenter, furi_string_get_cstr(morse_code->model->words)); - - // volume view_port + elements_multiline_text_aligned( + canvas, 64, 30, AlignCenter, AlignCenter, furi_string_get_cstr(morse_code->model->words)); + + // volume view_port uint8_t vol_bar_x_pos = 124; uint8_t vol_bar_y_pos = 0; - const uint8_t volume_h = - (64 / (COUNT_OF(MORSE_CODE_VOLUMES) - 1)) * morse_code->model->volume; + const uint8_t volume_h = (64 / (COUNT_OF(MORSE_CODE_VOLUMES) - 1)) * morse_code->model->volume; canvas_draw_frame(canvas, vol_bar_x_pos, vol_bar_y_pos, 4, 64); canvas_draw_box(canvas, vol_bar_x_pos, vol_bar_y_pos + (64 - volume_h), 4, volume_h); //dit bpm canvas_draw_str_aligned( - canvas, 0, 10, AlignLeft, AlignCenter, furi_string_get_cstr(furi_string_alloc_printf("Dit: %ld ms", morse_code->model->dit_delta))); - + canvas, + 0, + 10, + AlignLeft, + AlignCenter, + furi_string_get_cstr( + furi_string_alloc_printf("Dit: %ld ms", morse_code->model->dit_delta))); + //button info elements_button_center(canvas, "Press/Hold"); furi_mutex_release(morse_code->model_mutex); @@ -59,9 +64,7 @@ static void input_callback(InputEvent* input_event, void* ctx) { furi_message_queue_put(morse_code->input_queue, input_event, FuriWaitForever); } -static void morse_code_worker_callback( - FuriString* words, - void* context) { +static void morse_code_worker_callback(FuriString* words, void* context) { MorseCode* morse_code = context; furi_check(furi_mutex_acquire(morse_code->model_mutex, FuriWaitForever) == FuriStatusOk); morse_code->model->words = words; @@ -115,45 +118,45 @@ int32_t morse_code_app() { InputEvent input; morse_code_worker_start(morse_code->worker); morse_code_worker_set_volume( - morse_code->worker, MORSE_CODE_VOLUMES[morse_code->model->volume]); - morse_code_worker_set_dit_delta(morse_code->worker, morse_code->model->dit_delta); - while(furi_message_queue_get(morse_code->input_queue, &input, FuriWaitForever) == FuriStatusOk){ + morse_code->worker, MORSE_CODE_VOLUMES[morse_code->model->volume]); + morse_code_worker_set_dit_delta(morse_code->worker, morse_code->model->dit_delta); + while(furi_message_queue_get(morse_code->input_queue, &input, FuriWaitForever) == + FuriStatusOk) { furi_check(furi_mutex_acquire(morse_code->model_mutex, FuriWaitForever) == FuriStatusOk); if(input.key == InputKeyBack) { - furi_mutex_release(morse_code->model_mutex); - break; - }else if(input.key == InputKeyOk){ - if(input.type == InputTypePress) - morse_code_worker_play(morse_code->worker, true); - else if(input.type == InputTypeRelease) - morse_code_worker_play(morse_code->worker, false); - }else if(input.key == InputKeyUp && input.type == InputTypePress){ - if(morse_code->model->volume < COUNT_OF(MORSE_CODE_VOLUMES) - 1) - morse_code->model->volume++; - morse_code_worker_set_volume( - morse_code->worker, MORSE_CODE_VOLUMES[morse_code->model->volume]); - }else if(input.key == InputKeyDown && input.type == InputTypePress){ - if(morse_code->model->volume > 0) - morse_code->model->volume--; - morse_code_worker_set_volume( - morse_code->worker, MORSE_CODE_VOLUMES[morse_code->model->volume]); - }else if(input.key == InputKeyLeft && input.type == InputTypePress){ - if(morse_code->model->dit_delta > 10) - morse_code->model->dit_delta-=10; - morse_code_worker_set_dit_delta( - morse_code->worker, morse_code->model->dit_delta); - } - else if(input.key == InputKeyRight && input.type == InputTypePress){ - if(morse_code->model->dit_delta >= 10) - morse_code->model->dit_delta+=10; - morse_code_worker_set_dit_delta( - morse_code->worker, morse_code->model->dit_delta); - } - - FURI_LOG_D("Input", "%s %s %ld", input_get_key_name(input.key), input_get_type_name(input.type), input.sequence); - + furi_mutex_release(morse_code->model_mutex); + break; + } else if(input.key == InputKeyOk) { + if(input.type == InputTypePress) + morse_code_worker_play(morse_code->worker, true); + else if(input.type == InputTypeRelease) + morse_code_worker_play(morse_code->worker, false); + } else if(input.key == InputKeyUp && input.type == InputTypePress) { + if(morse_code->model->volume < COUNT_OF(MORSE_CODE_VOLUMES) - 1) + morse_code->model->volume++; + morse_code_worker_set_volume( + morse_code->worker, MORSE_CODE_VOLUMES[morse_code->model->volume]); + } else if(input.key == InputKeyDown && input.type == InputTypePress) { + if(morse_code->model->volume > 0) morse_code->model->volume--; + morse_code_worker_set_volume( + morse_code->worker, MORSE_CODE_VOLUMES[morse_code->model->volume]); + } else if(input.key == InputKeyLeft && input.type == InputTypePress) { + if(morse_code->model->dit_delta > 10) morse_code->model->dit_delta -= 10; + morse_code_worker_set_dit_delta(morse_code->worker, morse_code->model->dit_delta); + } else if(input.key == InputKeyRight && input.type == InputTypePress) { + if(morse_code->model->dit_delta >= 10) morse_code->model->dit_delta += 10; + morse_code_worker_set_dit_delta(morse_code->worker, morse_code->model->dit_delta); + } + + FURI_LOG_D( + "Input", + "%s %s %ld", + input_get_key_name(input.key), + input_get_type_name(input.type), + input.sequence); + furi_mutex_release(morse_code->model_mutex); - view_port_update(morse_code->view_port); + view_port_update(morse_code->view_port); } morse_code_worker_stop(morse_code->worker); morse_code_free(morse_code); diff --git a/applications/plugins/morse_code/morse_code_worker.c b/applications/plugins/morse_code/morse_code_worker.c index 54ee747c5..b465abc5b 100644 --- a/applications/plugins/morse_code/morse_code_worker.c +++ b/applications/plugins/morse_code/morse_code_worker.c @@ -2,19 +2,20 @@ #include #include - #define TAG "MorseCodeWorker" #define MORSE_CODE_VERSION 0 //A-Z0-1 -const char morse_array[36][6] ={ - ".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.", - "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..", ".----", "..---", "...--", "....-", ".....", - "-....", "--...", "---..", "----.", "-----" - }; -const char symbol_array[36] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', - 'U', 'V', 'W', 'X', 'Y', 'Z', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0'}; +const char morse_array[36][6] = {".-", "-...", "-.-.", "-..", ".", "..-.", + "--.", "....", "..", ".---", "-.-", ".-..", + "--", "-.", "---", ".--.", "--.-", ".-.", + "...", "-", "..-", "...-", ".--", "-..-", + "-.--", "--..", ".----", "..---", "...--", "....-", + ".....", "-....", "--...", "---..", "----.", "-----"}; +const char symbol_array[36] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', + 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', + 'Y', 'Z', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0'}; struct MorseCodeWorker { FuriThread* thread; @@ -28,31 +29,28 @@ struct MorseCodeWorker { FuriString* words; }; -void morse_code_worker_fill_buffer(MorseCodeWorker* instance, uint32_t duration){ +void morse_code_worker_fill_buffer(MorseCodeWorker* instance, uint32_t duration) { FURI_LOG_D("MorseCode: Duration", "%ld", duration); - if( duration <= instance->dit_delta) + if(duration <= instance->dit_delta) furi_string_push_back(instance->buffer, *DOT); else if(duration <= (instance->dit_delta * 3)) furi_string_push_back(instance->buffer, *LINE); - if(furi_string_size(instance->buffer) > 5) - furi_string_reset(instance->buffer); + if(furi_string_size(instance->buffer) > 5) furi_string_reset(instance->buffer); FURI_LOG_D("MorseCode: Buffer", "%s", furi_string_get_cstr(instance->buffer)); } -void morse_code_worker_fill_letter(MorseCodeWorker* instance){ - if(furi_string_size(instance->words) > 63) - furi_string_reset(instance->words); - for (size_t i = 0; i < sizeof(morse_array); i++){ - if(furi_string_cmp_str(instance->buffer, morse_array[i]) == 0){ - furi_string_push_back(instance->words, symbol_array[i]); - furi_string_reset(instance->buffer); - break; - } +void morse_code_worker_fill_letter(MorseCodeWorker* instance) { + if(furi_string_size(instance->words) > 63) furi_string_reset(instance->words); + for(size_t i = 0; i < sizeof(morse_array); i++) { + if(furi_string_cmp_str(instance->buffer, morse_array[i]) == 0) { + furi_string_push_back(instance->words, symbol_array[i]); + furi_string_reset(instance->buffer); + break; } + } FURI_LOG_D("MorseCode: Words", "%s", furi_string_get_cstr(instance->words)); } - static int32_t morse_code_worker_thread_callback(void* context) { furi_assert(context); MorseCodeWorker* instance = context; @@ -61,16 +59,16 @@ static int32_t morse_code_worker_thread_callback(void* context) { uint32_t end_tick = 0; bool pushed = true; bool spaced = true; - while(instance->is_running){ + while(instance->is_running) { furi_delay_ms(SLEEP); - if(instance->play){ - if(!was_playing){ + if(instance->play) { + if(!was_playing) { start_tick = furi_get_tick(); furi_hal_speaker_start(FREQUENCY, instance->volume); was_playing = true; } - }else{ - if(was_playing){ + } else { + if(was_playing) { pushed = false; spaced = false; furi_hal_speaker_stop(); @@ -80,21 +78,21 @@ static int32_t morse_code_worker_thread_callback(void* context) { start_tick = 0; } } - if(!pushed){ - if(end_tick + (instance->dit_delta * 3) < furi_get_tick()){ + if(!pushed) { + if(end_tick + (instance->dit_delta * 3) < furi_get_tick()) { //NEW LETTER morse_code_worker_fill_letter(instance); if(instance->callback) - instance->callback(instance->words, instance->callback_context); + instance->callback(instance->words, instance->callback_context); pushed = true; } } - if(!spaced){ - if(end_tick + (instance->dit_delta * 7) < furi_get_tick()){ + if(!spaced) { + if(end_tick + (instance->dit_delta * 7) < furi_get_tick()) { //NEW WORD furi_string_push_back(instance->words, *SPACE); if(instance->callback) - instance->callback(instance->words, instance->callback_context); + instance->callback(instance->words, instance->callback_context); spaced = true; } } @@ -132,17 +130,17 @@ void morse_code_worker_set_callback( instance->callback_context = context; } -void morse_code_worker_play(MorseCodeWorker* instance, bool play){ +void morse_code_worker_play(MorseCodeWorker* instance, bool play) { furi_assert(instance); instance->play = play; } -void morse_code_worker_set_volume(MorseCodeWorker* instance, float level){ +void morse_code_worker_set_volume(MorseCodeWorker* instance, float level) { furi_assert(instance); instance->volume = level; } -void morse_code_worker_set_dit_delta(MorseCodeWorker* instance, uint32_t delta){ +void morse_code_worker_set_dit_delta(MorseCodeWorker* instance, uint32_t delta) { furi_assert(instance); instance->dit_delta = delta; } diff --git a/applications/plugins/morse_code/morse_code_worker.h b/applications/plugins/morse_code/morse_code_worker.h index cc84a2674..524876476 100644 --- a/applications/plugins/morse_code/morse_code_worker.h +++ b/applications/plugins/morse_code/morse_code_worker.h @@ -10,9 +10,7 @@ #define LINE "-" #define SPACE " " -typedef void (*MorseCodeWorkerCallback)( - FuriString* buffer, - void* context); +typedef void (*MorseCodeWorkerCallback)(FuriString* buffer, void* context); typedef struct MorseCodeWorker MorseCodeWorker; @@ -34,9 +32,3 @@ void morse_code_worker_play(MorseCodeWorker* instance, bool play); void morse_code_worker_set_volume(MorseCodeWorker* instance, float level); void morse_code_worker_set_dit_delta(MorseCodeWorker* instance, uint32_t delta); - - - - - - diff --git a/applications/plugins/totp/totp_app.c b/applications/plugins/totp/totp_app.c index 3bc85e211..f296a734b 100644 --- a/applications/plugins/totp/totp_app.c +++ b/applications/plugins/totp/totp_app.c @@ -24,7 +24,7 @@ static void render_callback(Canvas* const canvas, void* ctx) { PluginState* plugin_state = acquire_mutex((ValueMutex*)ctx, 25); - if (plugin_state != NULL && !plugin_state->changing_scene) { + if(plugin_state != NULL && !plugin_state->changing_scene) { totp_scene_director_render(canvas, plugin_state); } @@ -49,29 +49,43 @@ static bool totp_plugin_state_init(PluginState* const plugin_state) { totp_scene_director_init_scenes(plugin_state); - if (plugin_state->crypto_verify_data == NULL) { + if(plugin_state->crypto_verify_data == NULL) { DialogMessage* message = dialog_message_alloc(); dialog_message_set_buttons(message, "No", NULL, "Yes"); - dialog_message_set_text(message, "Would you like to setup PIN?", SCREEN_WIDTH_CENTER, SCREEN_HEIGHT_CENTER, AlignCenter, AlignCenter); + dialog_message_set_text( + message, + "Would you like to setup PIN?", + SCREEN_WIDTH_CENTER, + SCREEN_HEIGHT_CENTER, + AlignCenter, + AlignCenter); DialogMessageButton dialog_result = dialog_message_show(plugin_state->dialogs, message); dialog_message_free(message); - if (dialog_result == DialogMessageButtonRight) { + if(dialog_result == DialogMessageButtonRight) { totp_scene_director_activate_scene(plugin_state, TotpSceneAuthentication, NULL); } else { totp_crypto_seed_iv(plugin_state, NULL, 0); totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL); } - } else if (plugin_state->pin_set) { + } else if(plugin_state->pin_set) { totp_scene_director_activate_scene(plugin_state, TotpSceneAuthentication, NULL); } else { totp_crypto_seed_iv(plugin_state, NULL, 0); - if (totp_crypto_verify_key(plugin_state)) { + if(totp_crypto_verify_key(plugin_state)) { totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL); } else { - FURI_LOG_E(LOGGING_TAG, "Digital signature verification failed. Looks like conf file was created on another flipper and can't be used on any other"); + FURI_LOG_E( + LOGGING_TAG, + "Digital signature verification failed. Looks like conf file was created on another flipper and can't be used on any other"); DialogMessage* message = dialog_message_alloc(); dialog_message_set_buttons(message, "Exit", NULL, NULL); - dialog_message_set_text(message, "Digital signature verification failed", SCREEN_WIDTH_CENTER, SCREEN_HEIGHT_CENTER, AlignCenter, AlignCenter); + dialog_message_set_text( + message, + "Digital signature verification failed", + SCREEN_WIDTH_CENTER, + SCREEN_HEIGHT_CENTER, + AlignCenter, + AlignCenter); dialog_message_show(plugin_state->dialogs, message); dialog_message_free(message); return false; @@ -94,7 +108,7 @@ static void totp_plugin_state_free(PluginState* plugin_state) { ListNode* node = plugin_state->tokens_list; ListNode* tmp; - while (node != NULL) { + while(node != NULL) { tmp = node->next; TokenInfo* tokenInfo = node->data; token_info_free(tokenInfo); @@ -102,7 +116,7 @@ static void totp_plugin_state_free(PluginState* plugin_state) { node = tmp; } - if (plugin_state->crypto_verify_data != NULL) { + if(plugin_state->crypto_verify_data != NULL) { free(plugin_state->crypto_verify_data); } free(plugin_state); @@ -112,7 +126,7 @@ int32_t totp_app() { FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(PluginEvent)); PluginState* plugin_state = malloc(sizeof(PluginState)); - if (!totp_plugin_state_init(plugin_state)) { + if(!totp_plugin_state_init(plugin_state)) { FURI_LOG_E(LOGGING_TAG, "App state initialization failed\r\n"); totp_plugin_state_free(plugin_state); return 254; @@ -137,18 +151,20 @@ int32_t totp_app() { bool processing = true; uint32_t last_user_interaction_time = furi_get_tick(); while(processing) { - if (plugin_state->changing_scene) continue; + if(plugin_state->changing_scene) continue; FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); PluginState* plugin_state_m = acquire_mutex_block(&state_mutex); if(event_status == FuriStatusOk) { - if (event.type == EventTypeKey) { + if(event.type == EventTypeKey) { last_user_interaction_time = furi_get_tick(); } processing = totp_scene_director_handle_event(&event, plugin_state_m); - } else if (plugin_state_m->pin_set && plugin_state_m->current_scene != TotpSceneAuthentication && furi_get_tick() - last_user_interaction_time > IDLE_TIMEOUT) { + } else if( + plugin_state_m->pin_set && plugin_state_m->current_scene != TotpSceneAuthentication && + furi_get_tick() - last_user_interaction_time > IDLE_TIMEOUT) { totp_scene_director_activate_scene(plugin_state_m, TotpSceneAuthentication, NULL); } From 356389ace9dd7afdcb9913681d27f23ea9b0ad3c Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Wed, 2 Nov 2022 23:51:47 +0300 Subject: [PATCH 19/23] Disable halloween theme New xmas theme is coming in december :) --- assets/dolphin/external/manifest.txt | 7 ------- assets/icons/StatusBar/Background_128x11.png | Bin 447 -> 410 bytes 2 files changed, 7 deletions(-) diff --git a/assets/dolphin/external/manifest.txt b/assets/dolphin/external/manifest.txt index 60b8fc25f..ecf7c1806 100644 --- a/assets/dolphin/external/manifest.txt +++ b/assets/dolphin/external/manifest.txt @@ -15,13 +15,6 @@ Min level: 1 Max level: 1 Weight: 3 -Name: L1_Halloween_128x64 -Min butthurt: 0 -Max butthurt: 13 -Min level: 1 -Max level: 3 -Weight: 8 - Name: L1_Sleep_128x64 Min butthurt: 0 Max butthurt: 10 diff --git a/assets/icons/StatusBar/Background_128x11.png b/assets/icons/StatusBar/Background_128x11.png index e43b32d16f04675311263d032e5d4018223febb6..78ef029ae737fe82080bd709545aff7ccdae948e 100644 GIT binary patch delta 372 zcmdnbJd1gPgd`I)0|Ub;^;~Bl#ggvm>&U>cv7h@-BI`s&>3RbOhF1v;3|2E37{m+a z>_V@sW8a-VcLnJPT1~~E^P~d1jayNa^|HRIFrW60yr@Gu>&}-W^MJYtB zAT+Z6v_R8C*5!_~U#+%~>#RI`?Zh$;{j%1sd-qqd*0%7hJfoBHOSf@SSMj~~6YY;D zq&+w;&G5)<-`RzI`L)@x8onh{n|&LEWVUS8RxPn`a>}_=b*kk#s;cm>5Dd_?7)q0cv3IboFyt=akR{0J)cb{{R30 delta 410 zcmbQmyq|f31SbbG0|P_D^wLKY4W;Y#85my0GcZ_9XJ8O7s1e=82$U-d@Ck7R(m?Qk zZE~|A!~g&PzaLpz{ojD0nIUz_YzBsZ|65z8SXn&-DtLbM+?>{yY|UuH=%v|)DNFx% z_uLB(>RGyUX;4tmlqpmGO_?%z%D?~rm;MLp0%8V+T2G*XR#qBJf&Urm|2r`-CLd#H zY5RYV;rN3rbD*7SB|(0{AUg>Ii+aD|RUo1|K zkMC2O<9>dBwdm#Zf9vX|Pt;!> X#+y>O#s3s2bUj_!{9M*KB{Ts53`57q From af1647c84bb9c9c7ffbace2b89b4c84322cb9695 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Wed, 2 Nov 2022 23:52:03 +0300 Subject: [PATCH 20/23] Update DHT montior plugin --- .../plugins/dht_temp_sensor/scenes/DHTMon_sensorEdit_scene.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/applications/plugins/dht_temp_sensor/scenes/DHTMon_sensorEdit_scene.c b/applications/plugins/dht_temp_sensor/scenes/DHTMon_sensorEdit_scene.c index b9c5a1134..c44fc2528 100644 --- a/applications/plugins/dht_temp_sensor/scenes/DHTMon_sensorEdit_scene.c +++ b/applications/plugins/dht_temp_sensor/scenes/DHTMon_sensorEdit_scene.c @@ -93,6 +93,9 @@ void sensorEdit_scene(PluginData* app) { app->item, DHTMon_GPIO_getName(app->currentSensorEdit->GPIO)); variable_item_list_add(variable_item_list, "Save", 1, NULL, app); + //Сброс выбранного пункта в ноль + variable_item_list_set_selected_item(variable_item_list, 0); + view_dispatcher_switch_to_view(app->view_dispatcher, ADDSENSOR_MENU_VIEW); } void sensorEdit_sceneRemove(void) { From 5ac2431cd1723f4bb5d8d5f7bfcf958d4e00cc7b Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Thu, 3 Nov 2022 00:26:19 +0300 Subject: [PATCH 21/23] update readme and changelog --- CHANGELOG.md | 21 +++++++++++++++++++-- ReadMe.md | 18 +++++++++++------- firmware/targets/f7/api_symbols.csv | 2 +- 3 files changed, 31 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 717abe826..a4f2d002c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,23 @@ ### New changes -* Fix crash when furi_halt is called (was found when you try to power off flipper with usb cable connected) -* Fix bug when NFC keys was removed during scan +* Plugins: New AM2320 Sensor plugin (@xMasterX) +* Plugins -> PR: Added DHT Temperature sensor Monitor (by @quen0n | PR #147) [(plugin repo)](https://github.com/quen0n/FipperZero-DHT-Monitor) +* Plugins -> PR: USB Keyboard - added additional row for function keys (by @huuck | PR #145) +* Plugins -> PR: Added Morse Code plugin (by @wh00hw | PR #144) [(plugin repo)](https://github.com/wh00hw/MorseCodeFAP) +* Plugins -> PR: FlappyBird - Fix animation (by @msvsergey | PR #148) +* Plugins: Added Game15 [(by x27)](https://github.com/x27/flipperzero-game15) +* Plugins: Update and fix TOTP +* Plugins: Update Wifi Marauder +* Plugins: fix proper deinit of gpio and spi bus in NRF24 driver +* Snake game: Fix food spawn bug +* Replaced furi check hotfix with proper fix from OFW +* Disable halloween theme +* SubGHz: BFT Mitto fix, other small fixes +* OFW: WS -> add protocol Ambient_Weather +* OFW: Handle storage full error +* OFW: fbt fixes for mfbt pt2 +* OFW: Gui: refactor buttons remapping +* OFW: Furi: raise bkpt only if debug session initiated, add debug support for release builds +* OFW PR: BadUSB scrolllock typo fix (OFW PR 1968 by nminaylov) #### [🎲 Download latest extra apps pack](https://download-directory.github.io/?url=https://github.com/xMasterX/unleashed-extra-pack/tree/main/apps) diff --git a/ReadMe.md b/ReadMe.md index 946afe3bf..9665b8c91 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -56,8 +56,8 @@ Also check changelog in releases for latest updates! - Keeloq: Normstahl - CAME Atomo - Nice Flor S -- FAAC SLH (Spa) [External seed calculation required (For info conatct me in Discord: Nano#8998)] -- BFT Mitto [External seed calculation required (For info conatct me in Discord: Nano#8998)] +- FAAC SLH (Spa) [External seed calculation required (For info contact me in Discord: Nano#8998)] +- BFT Mitto [External seed calculation required (For info contact me in Discord: Nano#8998)] - Security+ v1 & v2 - Star Line (saving only) @@ -91,21 +91,24 @@ Also check changelog in releases for latest updates! - Metronome [(by panki27)](https://github.com/panki27/Metronome) - DTMF Dolphin [(by litui)](https://github.com/litui/dtmf_dolphin) - **TOTP (Authenticator)** [(by akopachov)](https://github.com/akopachov/flipper-zero_authenticator) -- GPS [(By ezod)](https://github.com/ezod/flipperzero-gps) works with module `NMEA 0183` via UART (13TX, 14RX, GND pins on Flipper) -- i2c Tools [(By NaejEL)](https://github.com/NaejEL/flipperzero-i2ctools) - C0 -> SCL / C1 -> SDA / GND -> GND | 3v3 logic levels only! -- Temperature Sensor Plugin - HTU21D / SI7021 [(By Mywk)](https://github.com/Mywk/FlipperTemperatureSensor) - [How to Connect](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/applications/plugins/temperature_sensor/Readme.md) +- GPS [(by ezod)](https://github.com/ezod/flipperzero-gps) works with module `NMEA 0183` via UART (13TX, 14RX, GND pins on Flipper) +- i2c Tools [(by NaejEL)](https://github.com/NaejEL/flipperzero-i2ctools) - C0 -> SCL / C1 -> SDA / GND -> GND | 3v3 logic levels only! +- Temperature Sensor Plugin - HTU21D / SI7021 [(by Mywk)](https://github.com/Mywk/FlipperTemperatureSensor) - [How to Connect](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/applications/plugins/temperature_sensor/Readme.md) - HC-SR04 Distance sensor - Ported and modified by @xMasterX [(original by Sanqui)](https://github.com/Sanqui/flipperzero-firmware/tree/hc_sr04) - How to connect -> (5V -> VCC) / (GND -> GND) / (13|TX -> Trig) / (14|RX -> Echo) - Morse Code [(by wh00hw)](https://github.com/wh00hw/MorseCodeFAP) +- AM2320/AM2321 Temp. Sensor plugin [(by xMasterX)](https://github.com/xMasterX/AM2320_Flipper_Plugin) - [How to Connect](https://github.com/xMasterX/AM2320_Flipper_Plugin) +- DHT11/22 Temp. Sensor Monitor [(by quen0n)](https://github.com/quen0n/FipperZero-DHT-Monitor) - How to connect -> (5V -> VCC) / (GND -> GND) / (Selected Pin -> out) Games: -- DOOM (fixed) [(By p4nic4ttack)](https://github.com/p4nic4ttack/doom-flipper-zero/) +- DOOM (fixed) [(by p4nic4ttack)](https://github.com/p4nic4ttack/doom-flipper-zero/) - Zombiez [(Reworked By DevMilanIan)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/240) [(Original By Dooskington)](https://github.com/Dooskington/flipperzero-zombiez) -- Flappy Bird [(By DroomOne)](https://github.com/DroomOne/flipperzero-firmware/tree/dev/applications/flappy_bird) +- Flappy Bird [(by DroomOne)](https://github.com/DroomOne/flipperzero-firmware/tree/dev/applications/flappy_bird) - Arkanoid (refactored by xMasterX) [(by gotnull)](https://github.com/gotnull/flipperzero-firmware-wPlugins) - Tic Tac Toe (refactored by xMasterX) [(by gotnull)](https://github.com/gotnull/flipperzero-firmware-wPlugins) - Tetris (with fixes) [(by jeffplang)](https://github.com/jeffplang/flipperzero-firmware/tree/tetris_game/applications/tetris_game) - Minesweeper [(by panki27)](https://github.com/panki27/minesweeper) - Heap Defence (aka Stack Attack) - Ported to latest firmware by @xMasterX - [(original by wquinoa & Vedmein)](https://github.com/Vedmein/flipperzero-firmware/tree/hd/svisto-perdelki) +- Game15 [(by x27)](https://github.com/x27/flipperzero-game15) ### Other changes @@ -115,6 +118,7 @@ Games: - SubGHz -> Save last used frequency and modulation [(by derskythe)](https://github.com/DarkFlippers/unleashed-firmware/pull/77) - SubGHz -> Press OK in frequency analyzer to use detected frequency in Read modes [(by derskythe)](https://github.com/DarkFlippers/unleashed-firmware/pull/77) - SubGHz -> Long press OK button in SubGHz Frequency analyzer to switch to Read menu [(by derskythe)](https://github.com/DarkFlippers/unleashed-firmware/pull/79) +- Lock device with pin(or regular lock if pin not set) by holding UP button on main screen [(by an4tur0r)](https://github.com/DarkFlippers/unleashed-firmware/pull/107) # Instructions ## [- How to install firmware](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/HowToInstall.md) diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 05c643dcc..af04720fc 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,8.3,, +Version,+,8.4,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, From 677de3202665f213858baab2147fdb1816089242 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Thu, 3 Nov 2022 00:41:17 +0300 Subject: [PATCH 22/23] Revert TOTP changes "Preload failed, invalid file" --- .../totp/images/totp_arrow_left_8x9.png | Bin 149 -> 0 bytes .../totp/images/totp_arrow_right_8x9.png | Bin 149 -> 0 bytes .../scenes/add_new_token/totp_input_text.c | 18 +- .../scenes/add_new_token/totp_input_text.h | 2 +- .../add_new_token/totp_scene_add_new_token.c | 289 +++++++++--------- .../add_new_token/totp_scene_add_new_token.h | 6 +- .../scenes/app_settings/totp_app_settings.c | 153 +++++----- .../scenes/app_settings/totp_app_settings.h | 10 +- .../authenticate/totp_scene_authenticate.c | 150 +++++---- .../authenticate/totp_scene_authenticate.h | 6 +- .../totp_scene_generate_token.c | 123 ++++---- .../totp_scene_generate_token.h | 10 +- .../plugins/totp/scenes/scene_director.c | 2 +- .../plugins/totp/scenes/scene_director.h | 2 +- .../scenes/token_menu/totp_scene_token_menu.c | 205 ++++++------- .../scenes/token_menu/totp_scene_token_menu.h | 8 +- applications/plugins/totp/services/cli/cli.c | 2 +- .../plugins/totp/services/cli/cli_helpers.c | 3 +- .../plugins/totp/services/cli/cli_helpers.h | 28 +- .../totp/services/cli/commands/add/add.c | 117 ++++--- .../plugins/totp/services/config/config.c | 36 +-- .../plugins/totp/services/config/config.h | 4 +- .../plugins/totp/services/crypto/crypto.c | 19 +- .../plugins/totp/services/crypto/crypto.h | 10 +- .../plugins/totp/services/crypto/memset_s.c | 22 -- .../plugins/totp/services/crypto/memset_s.h | 16 - .../plugins/totp/services/list/list.c | 5 +- .../plugins/totp/services/list/list.h | 11 +- .../plugins/totp/services/nullable/nullable.h | 17 -- .../totp/services/roll_value/roll_value.c | 28 -- .../totp/services/roll_value/roll_value.h | 17 -- .../plugins/totp/services/totp/totp.c | 18 +- .../plugins/totp/services/totp/totp.h | 6 +- applications/plugins/totp/services/ui/icons.h | 13 + .../plugins/totp/services/ui/ui_controls.c | 30 +- .../plugins/totp/services/ui/ui_controls.h | 10 +- applications/plugins/totp/totp_app.c | 10 +- .../plugins/totp/types/plugin_state.h | 4 +- applications/plugins/totp/types/token_info.c | 11 +- applications/plugins/totp/types/token_info.h | 8 +- 40 files changed, 640 insertions(+), 789 deletions(-) delete mode 100644 applications/plugins/totp/images/totp_arrow_left_8x9.png delete mode 100644 applications/plugins/totp/images/totp_arrow_right_8x9.png delete mode 100644 applications/plugins/totp/services/crypto/memset_s.c delete mode 100644 applications/plugins/totp/services/crypto/memset_s.h delete mode 100644 applications/plugins/totp/services/nullable/nullable.h delete mode 100644 applications/plugins/totp/services/roll_value/roll_value.c delete mode 100644 applications/plugins/totp/services/roll_value/roll_value.h create mode 100644 applications/plugins/totp/services/ui/icons.h diff --git a/applications/plugins/totp/images/totp_arrow_left_8x9.png b/applications/plugins/totp/images/totp_arrow_left_8x9.png deleted file mode 100644 index 3bf9121c0b3eb1d3a7e05bc069f9b23827adb381..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 149 zcmeAS@N?(olHy`uVBq!ia0vp^96-#;$P6S+=l;(HQjEnx?oJHr&dIz4a#+$GeH|GX zHuiJ>Nn{1`*#dk*T>t<74`hZOx?BgOI14-?iy0XB4ude`@%$AjKtTyl7sn8Z%gG5T o3F#BkSET>oKk|v^4Nnh)$W|twRlcWOfod2$UHx3vIVCg!0A-gcZvX%Q diff --git a/applications/plugins/totp/images/totp_arrow_right_8x9.png b/applications/plugins/totp/images/totp_arrow_right_8x9.png deleted file mode 100644 index 8c6a8bfeb91385715c668ae573f6e609cf43ad72..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 149 zcmeAS@N?(olHy`uVBq!ia0vp^96-#;$P6S+=l;(HQjEnx?oJHr&dIz4a#+$GeH|GX zHuiJ>Nn{1`*#dk*T!Hle|NocXoPQU{;w #include "../../types/common.h" -size_t strnlen(const char* s, size_t maxlen) { - size_t len; - - for(len = 0; len < maxlen; len++, s++) { - if(!*s) break; - } - - return len; -} - void view_draw(View* view, Canvas* canvas) { furi_assert(view); if(view->draw_callback) { @@ -42,14 +32,10 @@ static void commit_text_input_callback(void* context) { InputTextSceneState* text_input_state = (InputTextSceneState*)context; if(text_input_state->callback != 0) { InputTextSceneCallbackResult* result = malloc(sizeof(InputTextSceneCallbackResult)); - result->user_input_length = - strnlen(text_input_state->text_input_buffer, INPUT_BUFFER_SIZE); + result->user_input_length = strlen(text_input_state->text_input_buffer); result->user_input = malloc(result->user_input_length + 1); result->callback_data = text_input_state->callback_data; - strlcpy( - result->user_input, - text_input_state->text_input_buffer, - result->user_input_length + 1); + strcpy(result->user_input, text_input_state->text_input_buffer); text_input_state->callback(result); } } diff --git a/applications/plugins/totp/scenes/add_new_token/totp_input_text.h b/applications/plugins/totp/scenes/add_new_token/totp_input_text.h index dda0dc301..a73a227b5 100644 --- a/applications/plugins/totp/scenes/add_new_token/totp_input_text.h +++ b/applications/plugins/totp/scenes/add_new_token/totp_input_text.h @@ -10,7 +10,7 @@ typedef struct { char* user_input; - size_t user_input_length; + uint8_t user_input_length; void* callback_data; } InputTextSceneCallbackResult; diff --git a/applications/plugins/totp/scenes/add_new_token/totp_scene_add_new_token.c b/applications/plugins/totp/scenes/add_new_token/totp_scene_add_new_token.c index ff8cc5f38..04b73595b 100644 --- a/applications/plugins/totp/scenes/add_new_token/totp_scene_add_new_token.c +++ b/applications/plugins/totp/scenes/add_new_token/totp_scene_add_new_token.c @@ -8,8 +8,6 @@ #include "../../services/base32/base32.h" #include "../../services/config/config.h" #include "../../services/ui/ui_controls.h" -#include "../../services/roll_value/roll_value.h" -#include "../../services/nullable/nullable.h" #include "../generate_token/totp_scene_generate_token.h" #define TOKEN_ALGO_LIST_LENGTH 3 @@ -27,22 +25,22 @@ typedef enum { typedef struct { char* token_name; - size_t token_name_length; + uint8_t token_name_length; char* token_secret; - size_t token_secret_length; + uint8_t token_secret_length; bool saved; Control selected_control; InputTextSceneContext* token_name_input_context; InputTextSceneContext* token_secret_input_context; InputTextSceneState* input_state; uint32_t input_started_at; - TotpNullable_uint16_t current_token_index; - int16_t screen_y_offset; + int16_t current_token_index; + int32_t screen_y_offset; TokenHashAlgo algo; TokenDigitsCount digits_count; } SceneState; -void totp_scene_add_new_token_init(const PluginState* plugin_state) { +void totp_scene_add_new_token_init(PluginState* plugin_state) { UNUSED(plugin_state); } @@ -89,9 +87,9 @@ void totp_scene_add_new_token_activate( scene_state->input_state = NULL; if(context == NULL) { - TOTP_NULLABLE_NULL(scene_state->current_token_index); + scene_state->current_token_index = -1; } else { - TOTP_NULLABLE_VALUE(scene_state->current_token_index, context->current_token_index); + scene_state->current_token_index = context->current_token_index; } } @@ -152,148 +150,143 @@ void update_screen_y_offset(SceneState* scene_state) { } bool totp_scene_add_new_token_handle_event(PluginEvent* const event, PluginState* plugin_state) { - if(event->type != EventTypeKey) { - return true; - } - - SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; - if(scene_state->input_started_at > 0 && - furi_get_tick() - scene_state->input_started_at > 300) { - return totp_input_text_handle_event(event, scene_state->input_state); - } - - if(event->input.type == InputTypeLong && event->input.key == InputKeyBack) { - return false; - } - - if(event->input.type != InputTypePress) { - return true; - } - - switch(event->input.key) { - case InputKeyUp: - totp_roll_value_uint8_t( - &scene_state->selected_control, - -1, - TokenNameTextBox, - ConfirmButton, - RollOverflowBehaviorStop); - update_screen_y_offset(scene_state); - break; - case InputKeyDown: - totp_roll_value_uint8_t( - &scene_state->selected_control, - 1, - TokenNameTextBox, - ConfirmButton, - RollOverflowBehaviorStop); - update_screen_y_offset(scene_state); - break; - case InputKeyRight: - if(scene_state->selected_control == TokenAlgoSelect) { - totp_roll_value_uint8_t(&scene_state->algo, 1, SHA1, SHA512, RollOverflowBehaviorRoll); - } else if(scene_state->selected_control == TokenLengthSelect) { - totp_roll_value_uint8_t( - &scene_state->digits_count, - 1, - TOTP_6_DIGITS, - TOTP_8_DIGITS, - RollOverflowBehaviorRoll); + if(event->type == EventTypeKey) { + SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; + if(scene_state->input_started_at > 0 && + furi_get_tick() - scene_state->input_started_at > 300) { + return totp_input_text_handle_event(event, scene_state->input_state); } - break; - case InputKeyLeft: - if(scene_state->selected_control == TokenAlgoSelect) { - totp_roll_value_uint8_t( - &scene_state->algo, -1, SHA1, SHA512, RollOverflowBehaviorRoll); - } else if(scene_state->selected_control == TokenLengthSelect) { - totp_roll_value_uint8_t( - &scene_state->digits_count, - -1, - TOTP_6_DIGITS, - TOTP_8_DIGITS, - RollOverflowBehaviorRoll); - } - break; - case InputKeyOk: - switch(scene_state->selected_control) { - case TokenNameTextBox: - if(scene_state->input_state != NULL) { - totp_input_text_free(scene_state->input_state); + + if(event->input.type == InputTypeLong && event->input.key == InputKeyBack) { + return false; + } else if(event->input.type == InputTypePress) { + switch(event->input.key) { + case InputKeyUp: + if(scene_state->selected_control > TokenNameTextBox) { + scene_state->selected_control--; + update_screen_y_offset(scene_state); + } + break; + case InputKeyDown: + if(scene_state->selected_control < ConfirmButton) { + scene_state->selected_control++; + update_screen_y_offset(scene_state); + } + break; + case InputKeyRight: + if(scene_state->selected_control == TokenAlgoSelect) { + if(scene_state->algo < SHA512) { + scene_state->algo++; + } else { + scene_state->algo = SHA1; + } + } else if(scene_state->selected_control == TokenLengthSelect) { + if(scene_state->digits_count < TOTP_8_DIGITS) { + scene_state->digits_count++; + } else { + scene_state->digits_count = TOTP_6_DIGITS; + } + } + break; + case InputKeyLeft: + if(scene_state->selected_control == TokenAlgoSelect) { + if(scene_state->algo > SHA1) { + scene_state->algo--; + } else { + scene_state->algo = SHA512; + } + } else if(scene_state->selected_control == TokenLengthSelect) { + if(scene_state->digits_count > TOTP_6_DIGITS) { + scene_state->digits_count--; + } else { + scene_state->digits_count = TOTP_8_DIGITS; + } + } + break; + case InputKeyOk: + switch(scene_state->selected_control) { + case TokenNameTextBox: + if(scene_state->input_state != NULL) { + totp_input_text_free(scene_state->input_state); + } + scene_state->input_state = + totp_input_text_activate(scene_state->token_name_input_context); + scene_state->input_started_at = furi_get_tick(); + break; + case TokenSecretTextBox: + if(scene_state->input_state != NULL) { + totp_input_text_free(scene_state->input_state); + } + scene_state->input_state = + totp_input_text_activate(scene_state->token_secret_input_context); + scene_state->input_started_at = furi_get_tick(); + break; + case TokenAlgoSelect: + break; + case TokenLengthSelect: + break; + case ConfirmButton: { + TokenInfo* tokenInfo = token_info_alloc(); + bool token_secret_set = token_info_set_secret( + tokenInfo, + scene_state->token_secret, + scene_state->token_secret_length, + &plugin_state->iv[0]); + + if(token_secret_set) { + tokenInfo->name = malloc(scene_state->token_name_length + 1); + strcpy(tokenInfo->name, scene_state->token_name); + tokenInfo->algo = scene_state->algo; + tokenInfo->digits = scene_state->digits_count; + + if(plugin_state->tokens_list == NULL) { + plugin_state->tokens_list = list_init_head(tokenInfo); + } else { + list_add(plugin_state->tokens_list, tokenInfo); + } + plugin_state->tokens_count++; + + totp_config_file_save_new_token(tokenInfo); + + GenerateTokenSceneContext generate_scene_context = { + .current_token_index = plugin_state->tokens_count - 1}; + totp_scene_director_activate_scene( + plugin_state, TotpSceneGenerateToken, &generate_scene_context); + } else { + token_info_free(tokenInfo); + DialogMessage* message = dialog_message_alloc(); + dialog_message_set_buttons(message, "Back", NULL, NULL); + dialog_message_set_text( + message, + "Token secret is invalid", + SCREEN_WIDTH_CENTER, + SCREEN_HEIGHT_CENTER, + AlignCenter, + AlignCenter); + dialog_message_show(plugin_state->dialogs, message); + dialog_message_free(message); + scene_state->selected_control = TokenSecretTextBox; + update_screen_y_offset(scene_state); + } + break; + } + } + break; + case InputKeyBack: + if(scene_state->current_token_index >= 0) { + GenerateTokenSceneContext generate_scene_context = { + .current_token_index = scene_state->current_token_index}; + totp_scene_director_activate_scene( + plugin_state, TotpSceneGenerateToken, &generate_scene_context); + } else { + totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL); + } + break; + default: + break; } - scene_state->input_state = - totp_input_text_activate(scene_state->token_name_input_context); - scene_state->input_started_at = furi_get_tick(); - break; - case TokenSecretTextBox: - if(scene_state->input_state != NULL) { - totp_input_text_free(scene_state->input_state); - } - scene_state->input_state = - totp_input_text_activate(scene_state->token_secret_input_context); - scene_state->input_started_at = furi_get_tick(); - break; - case TokenAlgoSelect: - break; - case TokenLengthSelect: - break; - case ConfirmButton: { - TokenInfo* tokenInfo = token_info_alloc(); - bool token_secret_set = token_info_set_secret( - tokenInfo, - scene_state->token_secret, - scene_state->token_secret_length, - &plugin_state->iv[0]); - - if(token_secret_set) { - tokenInfo->name = malloc(scene_state->token_name_length + 1); - strlcpy( - tokenInfo->name, scene_state->token_name, scene_state->token_name_length + 1); - tokenInfo->algo = scene_state->algo; - tokenInfo->digits = scene_state->digits_count; - - TOTP_LIST_INIT_OR_ADD(plugin_state->tokens_list, tokenInfo); - plugin_state->tokens_count++; - - totp_config_file_save_new_token(tokenInfo); - - GenerateTokenSceneContext generate_scene_context = { - .current_token_index = plugin_state->tokens_count - 1}; - totp_scene_director_activate_scene( - plugin_state, TotpSceneGenerateToken, &generate_scene_context); - } else { - token_info_free(tokenInfo); - DialogMessage* message = dialog_message_alloc(); - dialog_message_set_buttons(message, "Back", NULL, NULL); - dialog_message_set_text( - message, - "Token secret is invalid", - SCREEN_WIDTH_CENTER, - SCREEN_HEIGHT_CENTER, - AlignCenter, - AlignCenter); - dialog_message_show(plugin_state->dialogs, message); - dialog_message_free(message); - scene_state->selected_control = TokenSecretTextBox; - update_screen_y_offset(scene_state); - } - break; } - } - break; - case InputKeyBack: - if(!scene_state->current_token_index.is_null) { - GenerateTokenSceneContext generate_scene_context = { - .current_token_index = scene_state->current_token_index.value}; - totp_scene_director_activate_scene( - plugin_state, TotpSceneGenerateToken, &generate_scene_context); - } else { - totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL); - } - break; - default: - break; } - return true; } @@ -317,6 +310,6 @@ void totp_scene_add_new_token_deactivate(PluginState* plugin_state) { plugin_state->current_scene_state = NULL; } -void totp_scene_add_new_token_free(const PluginState* plugin_state) { +void totp_scene_add_new_token_free(PluginState* plugin_state) { UNUSED(plugin_state); } diff --git a/applications/plugins/totp/scenes/add_new_token/totp_scene_add_new_token.h b/applications/plugins/totp/scenes/add_new_token/totp_scene_add_new_token.h index 9f53fe799..b65c567a2 100644 --- a/applications/plugins/totp/scenes/add_new_token/totp_scene_add_new_token.h +++ b/applications/plugins/totp/scenes/add_new_token/totp_scene_add_new_token.h @@ -7,14 +7,14 @@ #include "../../types/plugin_event.h" typedef struct { - uint16_t current_token_index; + uint8_t current_token_index; } TokenAddEditSceneContext; -void totp_scene_add_new_token_init(const PluginState* plugin_state); +void totp_scene_add_new_token_init(PluginState* plugin_state); void totp_scene_add_new_token_activate( PluginState* plugin_state, const TokenAddEditSceneContext* context); void totp_scene_add_new_token_render(Canvas* const canvas, PluginState* plugin_state); bool totp_scene_add_new_token_handle_event(PluginEvent* const event, PluginState* plugin_state); void totp_scene_add_new_token_deactivate(PluginState* plugin_state); -void totp_scene_add_new_token_free(const PluginState* plugin_state); +void totp_scene_add_new_token_free(PluginState* plugin_state); diff --git a/applications/plugins/totp/scenes/app_settings/totp_app_settings.c b/applications/plugins/totp/scenes/app_settings/totp_app_settings.c index b5b75db71..b3e6ab847 100644 --- a/applications/plugins/totp/scenes/app_settings/totp_app_settings.c +++ b/applications/plugins/totp/scenes/app_settings/totp_app_settings.c @@ -4,8 +4,6 @@ #include "../token_menu/totp_scene_token_menu.h" #include "../../services/ui/constants.h" #include "../../services/config/config.h" -#include "../../services/roll_value/roll_value.h" -#include "../../services/nullable/nullable.h" #define DIGIT_TO_CHAR(digit) ((digit) + '0') @@ -14,11 +12,11 @@ typedef enum { HoursInput, MinutesInput, ConfirmButton } Control; typedef struct { int8_t tz_offset_hours; uint8_t tz_offset_minutes; - TotpNullable_uint16_t current_token_index; + int16_t current_token_index; Control selected_control; } SceneState; -void totp_scene_app_settings_init(const PluginState* plugin_state) { +void totp_scene_app_settings_init(PluginState* plugin_state) { UNUSED(plugin_state); } @@ -28,9 +26,9 @@ void totp_scene_app_settings_activate( SceneState* scene_state = malloc(sizeof(SceneState)); plugin_state->current_scene_state = scene_state; if(context != NULL) { - TOTP_NULLABLE_VALUE(scene_state->current_token_index, context->current_token_index); + scene_state->current_token_index = context->current_token_index; } else { - TOTP_NULLABLE_NULL(scene_state->current_token_index); + scene_state->current_token_index = -1; } float off_int; @@ -55,7 +53,7 @@ static void two_digit_to_str(int8_t num, char* str) { } void totp_scene_app_settings_render(Canvas* const canvas, PluginState* plugin_state) { - const SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; + SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; canvas_set_font(canvas, FontPrimary); canvas_draw_str_aligned(canvas, 0, 0, AlignLeft, AlignTop, "Timezone offset"); @@ -92,80 +90,79 @@ void totp_scene_app_settings_render(Canvas* const canvas, PluginState* plugin_st scene_state->selected_control == ConfirmButton); } -bool totp_scene_app_settings_handle_event( - const PluginEvent* const event, - PluginState* plugin_state) { - if(event->type != EventTypeKey) { - return true; - } +bool totp_scene_app_settings_handle_event(PluginEvent* const event, PluginState* plugin_state) { + if(event->type == EventTypeKey) { + SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; + if(event->input.type == InputTypePress) { + switch(event->input.key) { + case InputKeyUp: + if(scene_state->selected_control > HoursInput) { + scene_state->selected_control--; + } + break; + case InputKeyDown: + if(scene_state->selected_control < ConfirmButton) { + scene_state->selected_control++; + } + break; + case InputKeyRight: + if(scene_state->selected_control == HoursInput) { + if(scene_state->tz_offset_hours < 12) { + scene_state->tz_offset_hours++; + } + } else if(scene_state->selected_control == MinutesInput) { + if(scene_state->tz_offset_minutes < 45) { + scene_state->tz_offset_minutes += 15; + } else { + scene_state->tz_offset_minutes = 0; + } + } + break; + case InputKeyLeft: + if(scene_state->selected_control == HoursInput) { + if(scene_state->tz_offset_hours > -12) { + scene_state->tz_offset_hours--; + } + } else if(scene_state->selected_control == MinutesInput) { + if(scene_state->tz_offset_minutes >= 15) { + scene_state->tz_offset_minutes -= 15; + } else { + scene_state->tz_offset_minutes = 45; + } + } + break; + case InputKeyOk: + if(scene_state->selected_control == ConfirmButton) { + plugin_state->timezone_offset = (float)scene_state->tz_offset_hours + + (float)scene_state->tz_offset_minutes / 60.0f; + totp_config_file_update_timezone_offset(plugin_state->timezone_offset); - SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; - if(event->input.type != InputTypePress) { - return true; - } - - switch(event->input.key) { - case InputKeyUp: - totp_roll_value_uint8_t( - &scene_state->selected_control, - -1, - HoursInput, - ConfirmButton, - RollOverflowBehaviorStop); - break; - case InputKeyDown: - totp_roll_value_uint8_t( - &scene_state->selected_control, 1, HoursInput, ConfirmButton, RollOverflowBehaviorStop); - break; - case InputKeyRight: - if(scene_state->selected_control == HoursInput) { - totp_roll_value_int8_t( - &scene_state->tz_offset_hours, 1, -12, 12, RollOverflowBehaviorStop); - } else if(scene_state->selected_control == MinutesInput) { - totp_roll_value_uint8_t( - &scene_state->tz_offset_minutes, 15, 0, 45, RollOverflowBehaviorRoll); - } - break; - case InputKeyLeft: - if(scene_state->selected_control == HoursInput) { - totp_roll_value_int8_t( - &scene_state->tz_offset_hours, -1, -12, 12, RollOverflowBehaviorStop); - } else if(scene_state->selected_control == MinutesInput) { - totp_roll_value_uint8_t( - &scene_state->tz_offset_minutes, -15, 0, 45, RollOverflowBehaviorRoll); - } - break; - case InputKeyOk: - if(scene_state->selected_control == ConfirmButton) { - plugin_state->timezone_offset = (float)scene_state->tz_offset_hours + - (float)scene_state->tz_offset_minutes / 60.0f; - totp_config_file_update_timezone_offset(plugin_state->timezone_offset); - - if(!scene_state->current_token_index.is_null) { - TokenMenuSceneContext generate_scene_context = { - .current_token_index = scene_state->current_token_index.value}; - totp_scene_director_activate_scene( - plugin_state, TotpSceneTokenMenu, &generate_scene_context); - } else { - totp_scene_director_activate_scene(plugin_state, TotpSceneTokenMenu, NULL); + if(scene_state->current_token_index >= 0) { + TokenMenuSceneContext generate_scene_context = { + .current_token_index = scene_state->current_token_index}; + totp_scene_director_activate_scene( + plugin_state, TotpSceneTokenMenu, &generate_scene_context); + } else { + totp_scene_director_activate_scene(plugin_state, TotpSceneTokenMenu, NULL); + } + } + break; + case InputKeyBack: { + if(scene_state->current_token_index >= 0) { + TokenMenuSceneContext generate_scene_context = { + .current_token_index = scene_state->current_token_index}; + totp_scene_director_activate_scene( + plugin_state, TotpSceneTokenMenu, &generate_scene_context); + } else { + totp_scene_director_activate_scene(plugin_state, TotpSceneTokenMenu, NULL); + } + break; + } + default: + break; } } - break; - case InputKeyBack: { - if(!scene_state->current_token_index.is_null) { - TokenMenuSceneContext generate_scene_context = { - .current_token_index = scene_state->current_token_index.value}; - totp_scene_director_activate_scene( - plugin_state, TotpSceneTokenMenu, &generate_scene_context); - } else { - totp_scene_director_activate_scene(plugin_state, TotpSceneTokenMenu, NULL); - } - break; } - default: - break; - } - return true; } @@ -176,6 +173,6 @@ void totp_scene_app_settings_deactivate(PluginState* plugin_state) { plugin_state->current_scene_state = NULL; } -void totp_scene_app_settings_free(const PluginState* plugin_state) { +void totp_scene_app_settings_free(PluginState* plugin_state) { UNUSED(plugin_state); } \ No newline at end of file diff --git a/applications/plugins/totp/scenes/app_settings/totp_app_settings.h b/applications/plugins/totp/scenes/app_settings/totp_app_settings.h index bcf930839..b97de3390 100644 --- a/applications/plugins/totp/scenes/app_settings/totp_app_settings.h +++ b/applications/plugins/totp/scenes/app_settings/totp_app_settings.h @@ -7,16 +7,14 @@ #include "../../types/plugin_event.h" typedef struct { - uint16_t current_token_index; + uint8_t current_token_index; } AppSettingsSceneContext; -void totp_scene_app_settings_init(const PluginState* plugin_state); +void totp_scene_app_settings_init(PluginState* plugin_state); void totp_scene_app_settings_activate( PluginState* plugin_state, const AppSettingsSceneContext* context); void totp_scene_app_settings_render(Canvas* const canvas, PluginState* plugin_state); -bool totp_scene_app_settings_handle_event( - const PluginEvent* const event, - PluginState* plugin_state); +bool totp_scene_app_settings_handle_event(PluginEvent* const event, PluginState* plugin_state); void totp_scene_app_settings_deactivate(PluginState* plugin_state); -void totp_scene_app_settings_free(const PluginState* plugin_state); \ No newline at end of file +void totp_scene_app_settings_free(PluginState* plugin_state); \ No newline at end of file diff --git a/applications/plugins/totp/scenes/authenticate/totp_scene_authenticate.c b/applications/plugins/totp/scenes/authenticate/totp_scene_authenticate.c index 8f44653ec..cdb77f5e2 100644 --- a/applications/plugins/totp/scenes/authenticate/totp_scene_authenticate.c +++ b/applications/plugins/totp/scenes/authenticate/totp_scene_authenticate.c @@ -1,7 +1,7 @@ #include "totp_scene_authenticate.h" #include -#include #include "../../types/common.h" +#include "../../services/ui/icons.h" #include "../../services/ui/constants.h" #include "../../services/config/config.h" #include "../scene_director.h" @@ -9,10 +9,6 @@ #include "../../services/crypto/crypto.h" #define MAX_CODE_LENGTH TOTP_IV_SIZE -#define ARROW_UP_CODE 2 -#define ARROW_RIGHT_CODE 8 -#define ARROW_DOWN_CODE 11 -#define ARROW_LEFT_CODE 5 typedef struct { uint8_t code_input[MAX_CODE_LENGTH]; @@ -32,7 +28,7 @@ void totp_scene_authenticate_activate(PluginState* plugin_state) { } void totp_scene_authenticate_render(Canvas* const canvas, PluginState* plugin_state) { - const SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; + SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; int v_shift = 0; if(scene_state->code_length > 0) { @@ -77,82 +73,80 @@ void totp_scene_authenticate_render(Canvas* const canvas, PluginState* plugin_st } } -bool totp_scene_authenticate_handle_event( - const PluginEvent* const event, - PluginState* plugin_state) { - if(event->type != EventTypeKey) { - return true; - } +bool totp_scene_authenticate_handle_event(PluginEvent* const event, PluginState* plugin_state) { + if(event->type == EventTypeKey) { + if(event->input.type == InputTypeLong && event->input.key == InputKeyBack) { + return false; + } else if(event->input.type == InputTypePress) { + SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; - if(event->input.type == InputTypeLong && event->input.key == InputKeyBack) { - return false; - } + const uint8_t ARROW_UP_CODE = 2; + const uint8_t ARROW_RIGHT_CODE = 8; + const uint8_t ARROW_DOWN_CODE = 11; + const uint8_t ARROW_LEFT_CODE = 5; - if(event->input.type != InputTypePress) { - return true; - } + switch(event->input.key) { + case InputKeyUp: + if(scene_state->code_length < MAX_CODE_LENGTH) { + scene_state->code_input[scene_state->code_length] = ARROW_UP_CODE; + scene_state->code_length++; + } + break; + case InputKeyDown: + if(scene_state->code_length < MAX_CODE_LENGTH) { + scene_state->code_input[scene_state->code_length] = ARROW_DOWN_CODE; + scene_state->code_length++; + } + break; + case InputKeyRight: + if(scene_state->code_length < MAX_CODE_LENGTH) { + scene_state->code_input[scene_state->code_length] = ARROW_RIGHT_CODE; + scene_state->code_length++; + } + break; + case InputKeyLeft: + if(scene_state->code_length < MAX_CODE_LENGTH) { + scene_state->code_input[scene_state->code_length] = ARROW_LEFT_CODE; + scene_state->code_length++; + } + break; + case InputKeyOk: + totp_crypto_seed_iv( + plugin_state, &scene_state->code_input[0], scene_state->code_length); - SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; + if(totp_crypto_verify_key(plugin_state)) { + FURI_LOG_D(LOGGING_TAG, "PIN is valid"); + totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL); + } else { + FURI_LOG_D(LOGGING_TAG, "PIN is NOT valid"); + memset(&scene_state->code_input[0], 0, MAX_CODE_LENGTH); + memset(&plugin_state->iv[0], 0, TOTP_IV_SIZE); + scene_state->code_length = 0; - switch(event->input.key) { - case InputKeyUp: - if(scene_state->code_length < MAX_CODE_LENGTH) { - scene_state->code_input[scene_state->code_length] = ARROW_UP_CODE; - scene_state->code_length++; + DialogMessage* message = dialog_message_alloc(); + dialog_message_set_buttons(message, "Try again", NULL, NULL); + dialog_message_set_header( + message, + "You entered\ninvalid PIN", + SCREEN_WIDTH_CENTER - 25, + SCREEN_HEIGHT_CENTER - 5, + AlignCenter, + AlignCenter); + dialog_message_set_icon(message, &I_DolphinCommon_56x48, 72, 17); + dialog_message_show(plugin_state->dialogs, message); + dialog_message_free(message); + } + break; + case InputKeyBack: + if(scene_state->code_length > 0) { + scene_state->code_input[scene_state->code_length - 1] = 0; + scene_state->code_length--; + } + break; + default: + break; + } } - break; - case InputKeyDown: - if(scene_state->code_length < MAX_CODE_LENGTH) { - scene_state->code_input[scene_state->code_length] = ARROW_DOWN_CODE; - scene_state->code_length++; - } - break; - case InputKeyRight: - if(scene_state->code_length < MAX_CODE_LENGTH) { - scene_state->code_input[scene_state->code_length] = ARROW_RIGHT_CODE; - scene_state->code_length++; - } - break; - case InputKeyLeft: - if(scene_state->code_length < MAX_CODE_LENGTH) { - scene_state->code_input[scene_state->code_length] = ARROW_LEFT_CODE; - scene_state->code_length++; - } - break; - case InputKeyOk: - totp_crypto_seed_iv(plugin_state, &scene_state->code_input[0], scene_state->code_length); - - if(totp_crypto_verify_key(plugin_state)) { - FURI_LOG_D(LOGGING_TAG, "PIN is valid"); - totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL); - } else { - FURI_LOG_D(LOGGING_TAG, "PIN is NOT valid"); - memset(&scene_state->code_input[0], 0, MAX_CODE_LENGTH); - memset(&plugin_state->iv[0], 0, TOTP_IV_SIZE); - scene_state->code_length = 0; - - DialogMessage* message = dialog_message_alloc(); - dialog_message_set_buttons(message, "Try again", NULL, NULL); - dialog_message_set_header( - message, - "You entered\ninvalid PIN", - SCREEN_WIDTH_CENTER - 25, - SCREEN_HEIGHT_CENTER - 5, - AlignCenter, - AlignCenter); - dialog_message_set_icon(message, &I_DolphinCommon_56x48, 72, 17); - dialog_message_show(plugin_state->dialogs, message); - dialog_message_free(message); - } - break; - case InputKeyBack: - if(scene_state->code_length > 0) { - scene_state->code_input[scene_state->code_length - 1] = 0; - scene_state->code_length--; - } - break; - default: - break; } return true; @@ -164,6 +158,6 @@ void totp_scene_authenticate_deactivate(PluginState* plugin_state) { plugin_state->current_scene_state = NULL; } -void totp_scene_authenticate_free(const PluginState* plugin_state) { +void totp_scene_authenticate_free(PluginState* plugin_state) { UNUSED(plugin_state); } diff --git a/applications/plugins/totp/scenes/authenticate/totp_scene_authenticate.h b/applications/plugins/totp/scenes/authenticate/totp_scene_authenticate.h index c54152f62..f1199a425 100644 --- a/applications/plugins/totp/scenes/authenticate/totp_scene_authenticate.h +++ b/applications/plugins/totp/scenes/authenticate/totp_scene_authenticate.h @@ -9,8 +9,6 @@ void totp_scene_authenticate_init(PluginState* plugin_state); void totp_scene_authenticate_activate(PluginState* plugin_state); void totp_scene_authenticate_render(Canvas* const canvas, PluginState* plugin_state); -bool totp_scene_authenticate_handle_event( - const PluginEvent* const event, - PluginState* plugin_state); +bool totp_scene_authenticate_handle_event(PluginEvent* const event, PluginState* plugin_state); void totp_scene_authenticate_deactivate(PluginState* plugin_state); -void totp_scene_authenticate_free(const PluginState* plugin_state); +void totp_scene_authenticate_free(PluginState* plugin_state); diff --git a/applications/plugins/totp/scenes/generate_token/totp_scene_generate_token.c b/applications/plugins/totp/scenes/generate_token/totp_scene_generate_token.c index c95e2c4e7..c9547a1ab 100644 --- a/applications/plugins/totp/scenes/generate_token/totp_scene_generate_token.c +++ b/applications/plugins/totp/scenes/generate_token/totp_scene_generate_token.c @@ -1,16 +1,14 @@ #include #include #include -#include #include "totp_scene_generate_token.h" #include "../../types/token_info.h" #include "../../types/common.h" +#include "../../services/ui/icons.h" #include "../../services/ui/constants.h" #include "../../services/totp/totp.h" #include "../../services/config/config.h" #include "../../services/crypto/crypto.h" -#include "../../services/crypto/memset_s.h" -#include "../../services/roll_value/roll_value.h" #include "../scene_director.h" #include "../token_menu/totp_scene_token_menu.h" @@ -18,7 +16,7 @@ #define DIGIT_TO_CHAR(digit) ((digit) + '0') typedef struct { - uint16_t current_token_index; + uint8_t current_token_index; char last_code[9]; char* last_code_name; bool need_token_update; @@ -97,7 +95,7 @@ void update_totp_params(PluginState* const plugin_state) { } } -void totp_scene_generate_token_init(const PluginState* plugin_state) { +void totp_scene_generate_token_init(PluginState* plugin_state) { UNUSED(plugin_state); } @@ -182,7 +180,7 @@ void totp_scene_generate_token_render(Canvas* const canvas, PluginState* plugin_ ->data); if(tokenInfo->token != NULL && tokenInfo->token_length > 0) { - size_t key_length; + uint8_t key_length; uint8_t* key = totp_crypto_decrypt( tokenInfo->token, tokenInfo->token_length, &plugin_state->iv[0], &key_length); @@ -197,7 +195,7 @@ void totp_scene_generate_token_render(Canvas* const canvas, PluginState* plugin_ TOKEN_LIFETIME), scene_state->last_code, tokenInfo->digits); - memset_s(key, sizeof(key), 0, key_length); + memset(key, 0, key_length); free(key); } else { i_token_to_str(0, scene_state->last_code, tokenInfo->digits); @@ -250,63 +248,65 @@ void totp_scene_generate_token_render(Canvas* const canvas, PluginState* plugin_ canvas_draw_box(canvas, barX, SCREEN_HEIGHT - BAR_MARGIN - BAR_HEIGHT, barWidth, BAR_HEIGHT); if(plugin_state->tokens_count > 1) { - canvas_draw_icon(canvas, 0, SCREEN_HEIGHT_CENTER - 24, &I_totp_arrow_left_8x9); - canvas_draw_icon( - canvas, SCREEN_WIDTH - 9, SCREEN_HEIGHT_CENTER - 24, &I_totp_arrow_right_8x9); + canvas_draw_xbm( + canvas, + 0, + SCREEN_HEIGHT_CENTER - 24, + ICON_ARROW_LEFT_8x9_WIDTH, + ICON_ARROW_LEFT_8x9_HEIGHT, + &ICON_ARROW_LEFT_8x9[0]); + canvas_draw_xbm( + canvas, + SCREEN_WIDTH - 9, + SCREEN_HEIGHT_CENTER - 24, + ICON_ARROW_RIGHT_8x9_WIDTH, + ICON_ARROW_RIGHT_8x9_HEIGHT, + &ICON_ARROW_RIGHT_8x9[0]); } } -bool totp_scene_generate_token_handle_event( - const PluginEvent* const event, - PluginState* plugin_state) { - if(event->type != EventTypeKey) { - return true; - } - - if(event->input.type == InputTypeLong && event->input.key == InputKeyBack) { - return false; - } - - if(event->input.type != InputTypePress) { - return true; - } - - SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; - switch(event->input.key) { - case InputKeyUp: - break; - case InputKeyDown: - break; - case InputKeyRight: - totp_roll_value_uint16_t( - &scene_state->current_token_index, - 1, - 0, - plugin_state->tokens_count - 1, - RollOverflowBehaviorRoll); - update_totp_params(plugin_state); - break; - case InputKeyLeft: - totp_roll_value_uint16_t( - &scene_state->current_token_index, - -1, - 0, - plugin_state->tokens_count - 1, - RollOverflowBehaviorRoll); - update_totp_params(plugin_state); - break; - case InputKeyOk: - if(plugin_state->tokens_count == 0) { - totp_scene_director_activate_scene(plugin_state, TotpSceneTokenMenu, NULL); - } else { - TokenMenuSceneContext ctx = {.current_token_index = scene_state->current_token_index}; - totp_scene_director_activate_scene(plugin_state, TotpSceneTokenMenu, &ctx); +bool totp_scene_generate_token_handle_event(PluginEvent* const event, PluginState* plugin_state) { + if(event->type == EventTypeKey) { + if(event->input.type == InputTypeLong && event->input.key == InputKeyBack) { + return false; + } else if(event->input.type == InputTypePress) { + SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; + switch(event->input.key) { + case InputKeyUp: + break; + case InputKeyDown: + break; + case InputKeyRight: + if(scene_state->current_token_index < plugin_state->tokens_count - 1) { + scene_state->current_token_index++; + } else { + scene_state->current_token_index = 0; + } + update_totp_params(plugin_state); + break; + case InputKeyLeft: + if(scene_state->current_token_index > 0) { + scene_state->current_token_index--; + } else { + scene_state->current_token_index = plugin_state->tokens_count - 1; + } + update_totp_params(plugin_state); + break; + case InputKeyOk: + if(plugin_state->tokens_count == 0) { + totp_scene_director_activate_scene(plugin_state, TotpSceneTokenMenu, NULL); + } else { + TokenMenuSceneContext ctx = { + .current_token_index = scene_state->current_token_index}; + totp_scene_director_activate_scene(plugin_state, TotpSceneTokenMenu, &ctx); + } + break; + case InputKeyBack: + break; + default: + break; + } } - break; - case InputKeyBack: - break; - default: - break; } return true; @@ -316,10 +316,11 @@ void totp_scene_generate_token_deactivate(PluginState* plugin_state) { if(plugin_state->current_scene_state == NULL) return; SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; + free(scene_state->last_code); free(scene_state); plugin_state->current_scene_state = NULL; } -void totp_scene_generate_token_free(const PluginState* plugin_state) { +void totp_scene_generate_token_free(PluginState* plugin_state) { UNUSED(plugin_state); } diff --git a/applications/plugins/totp/scenes/generate_token/totp_scene_generate_token.h b/applications/plugins/totp/scenes/generate_token/totp_scene_generate_token.h index 65f9b84e0..1284c7b41 100644 --- a/applications/plugins/totp/scenes/generate_token/totp_scene_generate_token.h +++ b/applications/plugins/totp/scenes/generate_token/totp_scene_generate_token.h @@ -7,16 +7,14 @@ #include "../../types/plugin_event.h" typedef struct { - uint16_t current_token_index; + uint8_t current_token_index; } GenerateTokenSceneContext; -void totp_scene_generate_token_init(const PluginState* plugin_state); +void totp_scene_generate_token_init(PluginState* plugin_state); void totp_scene_generate_token_activate( PluginState* plugin_state, const GenerateTokenSceneContext* context); void totp_scene_generate_token_render(Canvas* const canvas, PluginState* plugin_state); -bool totp_scene_generate_token_handle_event( - const PluginEvent* const event, - PluginState* plugin_state); +bool totp_scene_generate_token_handle_event(PluginEvent* const event, PluginState* plugin_state); void totp_scene_generate_token_deactivate(PluginState* plugin_state); -void totp_scene_generate_token_free(const PluginState* plugin_state); +void totp_scene_generate_token_free(PluginState* plugin_state); diff --git a/applications/plugins/totp/scenes/scene_director.c b/applications/plugins/totp/scenes/scene_director.c index 5265123f5..d4ddd1768 100644 --- a/applications/plugins/totp/scenes/scene_director.c +++ b/applications/plugins/totp/scenes/scene_director.c @@ -88,7 +88,7 @@ void totp_scene_director_render(Canvas* const canvas, PluginState* const plugin_ } } -void totp_scene_director_dispose(const PluginState* const plugin_state) { +void totp_scene_director_dispose(PluginState* const plugin_state) { totp_scene_generate_token_free(plugin_state); totp_scene_authenticate_free(plugin_state); totp_scene_add_new_token_free(plugin_state); diff --git a/applications/plugins/totp/scenes/scene_director.h b/applications/plugins/totp/scenes/scene_director.h index cc06029d3..3c25afff6 100644 --- a/applications/plugins/totp/scenes/scene_director.h +++ b/applications/plugins/totp/scenes/scene_director.h @@ -12,5 +12,5 @@ void totp_scene_director_activate_scene( void totp_scene_director_deactivate_active_scene(PluginState* const plugin_state); void totp_scene_director_init_scenes(PluginState* const plugin_state); void totp_scene_director_render(Canvas* const canvas, PluginState* const plugin_state); -void totp_scene_director_dispose(const PluginState* const plugin_state); +void totp_scene_director_dispose(PluginState* const plugin_state); bool totp_scene_director_handle_event(PluginEvent* const event, PluginState* const plugin_state); diff --git a/applications/plugins/totp/scenes/token_menu/totp_scene_token_menu.c b/applications/plugins/totp/scenes/token_menu/totp_scene_token_menu.c index fecf4f21e..717cb64bc 100644 --- a/applications/plugins/totp/scenes/token_menu/totp_scene_token_menu.c +++ b/applications/plugins/totp/scenes/token_menu/totp_scene_token_menu.c @@ -10,8 +10,6 @@ #include "../generate_token/totp_scene_generate_token.h" #include "../add_new_token/totp_scene_add_new_token.h" #include "../app_settings/totp_app_settings.h" -#include "../../services/nullable/nullable.h" -#include "../../services/roll_value/roll_value.h" #define SCREEN_HEIGHT_THIRD (SCREEN_HEIGHT / 3) #define SCREEN_HEIGHT_THIRD_CENTER (SCREEN_HEIGHT_THIRD >> 1) @@ -20,10 +18,10 @@ typedef enum { AddNewToken, DeleteToken, AppSettings } Control; typedef struct { Control selected_control; - TotpNullable_uint16_t current_token_index; + int16_t current_token_index; } SceneState; -void totp_scene_token_menu_init(const PluginState* plugin_state) { +void totp_scene_token_menu_init(PluginState* plugin_state) { UNUSED(plugin_state); } @@ -33,15 +31,15 @@ void totp_scene_token_menu_activate( SceneState* scene_state = malloc(sizeof(SceneState)); plugin_state->current_scene_state = scene_state; if(context != NULL) { - TOTP_NULLABLE_VALUE(scene_state->current_token_index, context->current_token_index); + scene_state->current_token_index = context->current_token_index; } else { - TOTP_NULLABLE_NULL(scene_state->current_token_index); + scene_state->current_token_index = -1; } } void totp_scene_token_menu_render(Canvas* const canvas, PluginState* plugin_state) { - const SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; - if(scene_state->current_token_index.is_null) { + SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; + if(scene_state->current_token_index < 0) { ui_control_button_render( canvas, SCREEN_WIDTH_CENTER - 36, @@ -86,107 +84,106 @@ void totp_scene_token_menu_render(Canvas* const canvas, PluginState* plugin_stat } } -bool totp_scene_token_menu_handle_event(const PluginEvent* const event, PluginState* plugin_state) { - if(event->type != EventTypeKey) { - return true; - } +bool totp_scene_token_menu_handle_event(PluginEvent* const event, PluginState* plugin_state) { + if(event->type == EventTypeKey) { + SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; + if(event->input.type == InputTypePress) { + switch(event->input.key) { + case InputKeyUp: + if(scene_state->selected_control > AddNewToken) { + scene_state->selected_control--; + if(scene_state->selected_control == DeleteToken && + scene_state->current_token_index < 0) { + scene_state->selected_control--; + } + } else { + scene_state->selected_control = AppSettings; + } + break; + case InputKeyDown: + if(scene_state->selected_control < AppSettings) { + scene_state->selected_control++; + if(scene_state->selected_control == DeleteToken && + scene_state->current_token_index < 0) { + scene_state->selected_control++; + } + } else { + scene_state->selected_control = AddNewToken; + } + break; + case InputKeyRight: + break; + case InputKeyLeft: + break; + case InputKeyOk: + switch(scene_state->selected_control) { + case AddNewToken: { + TokenAddEditSceneContext add_new_token_scene_context = { + .current_token_index = scene_state->current_token_index}; + totp_scene_director_activate_scene( + plugin_state, TotpSceneAddNewToken, &add_new_token_scene_context); + break; + } + case DeleteToken: { + DialogMessage* message = dialog_message_alloc(); + dialog_message_set_buttons(message, "No", NULL, "Yes"); + dialog_message_set_header(message, "Confirmation", 0, 0, AlignLeft, AlignTop); + dialog_message_set_text( + message, + "Are you sure want to delete?", + SCREEN_WIDTH_CENTER, + SCREEN_HEIGHT_CENTER, + AlignCenter, + AlignCenter); + DialogMessageButton dialog_result = + dialog_message_show(plugin_state->dialogs, message); + dialog_message_free(message); + if(dialog_result == DialogMessageButtonRight) { + ListNode* list_node = list_element_at( + plugin_state->tokens_list, scene_state->current_token_index); - SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; - if(event->input.type != InputTypePress) { - return true; - } + TokenInfo* tokenInfo = list_node->data; + token_info_free(tokenInfo); + plugin_state->tokens_list = + list_remove(plugin_state->tokens_list, list_node); + plugin_state->tokens_count--; - switch(event->input.key) { - case InputKeyUp: - totp_roll_value_uint8_t( - &scene_state->selected_control, -1, AddNewToken, AppSettings, RollOverflowBehaviorRoll); - if(scene_state->selected_control == DeleteToken && - scene_state->current_token_index.is_null) { - scene_state->selected_control--; - } - break; - case InputKeyDown: - totp_roll_value_uint8_t( - &scene_state->selected_control, 1, AddNewToken, AppSettings, RollOverflowBehaviorRoll); - if(scene_state->selected_control == DeleteToken && - scene_state->current_token_index.is_null) { - scene_state->selected_control++; - } - break; - case InputKeyRight: - break; - case InputKeyLeft: - break; - case InputKeyOk: - switch(scene_state->selected_control) { - case AddNewToken: { - if(scene_state->current_token_index.is_null) { - totp_scene_director_activate_scene(plugin_state, TotpSceneAddNewToken, NULL); - } else { - TokenAddEditSceneContext add_new_token_scene_context = { - .current_token_index = scene_state->current_token_index.value}; - totp_scene_director_activate_scene( - plugin_state, TotpSceneAddNewToken, &add_new_token_scene_context); + totp_full_save_config_file(plugin_state); + totp_scene_director_activate_scene( + plugin_state, TotpSceneGenerateToken, NULL); + } + break; + } + case AppSettings: { + if(scene_state->current_token_index >= 0) { + AppSettingsSceneContext app_settings_context = { + .current_token_index = scene_state->current_token_index}; + totp_scene_director_activate_scene( + plugin_state, TotpSceneAppSettings, &app_settings_context); + } else { + totp_scene_director_activate_scene( + plugin_state, TotpSceneAppSettings, NULL); + } + break; + } + } + break; + case InputKeyBack: { + if(scene_state->current_token_index >= 0) { + GenerateTokenSceneContext generate_scene_context = { + .current_token_index = scene_state->current_token_index}; + totp_scene_director_activate_scene( + plugin_state, TotpSceneGenerateToken, &generate_scene_context); + } else { + totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL); + } + break; } - break; - } - case DeleteToken: { - DialogMessage* message = dialog_message_alloc(); - dialog_message_set_buttons(message, "No", NULL, "Yes"); - dialog_message_set_header(message, "Confirmation", 0, 0, AlignLeft, AlignTop); - dialog_message_set_text( - message, - "Are you sure want to delete?", - SCREEN_WIDTH_CENTER, - SCREEN_HEIGHT_CENTER, - AlignCenter, - AlignCenter); - DialogMessageButton dialog_result = - dialog_message_show(plugin_state->dialogs, message); - dialog_message_free(message); - if(dialog_result == DialogMessageButtonRight && - !scene_state->current_token_index.is_null) { - ListNode* list_node = list_element_at( - plugin_state->tokens_list, scene_state->current_token_index.value); - - TokenInfo* tokenInfo = list_node->data; - token_info_free(tokenInfo); - plugin_state->tokens_list = list_remove(plugin_state->tokens_list, list_node); - plugin_state->tokens_count--; - - totp_full_save_config_file(plugin_state); - totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL); + default: + break; } - break; } - case AppSettings: { - if(!scene_state->current_token_index.is_null) { - AppSettingsSceneContext app_settings_context = { - .current_token_index = scene_state->current_token_index.value}; - totp_scene_director_activate_scene( - plugin_state, TotpSceneAppSettings, &app_settings_context); - } else { - totp_scene_director_activate_scene(plugin_state, TotpSceneAppSettings, NULL); - } - break; - } - } - break; - case InputKeyBack: { - if(!scene_state->current_token_index.is_null) { - GenerateTokenSceneContext generate_scene_context = { - .current_token_index = scene_state->current_token_index.value}; - totp_scene_director_activate_scene( - plugin_state, TotpSceneGenerateToken, &generate_scene_context); - } else { - totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL); - } - break; } - default: - break; - } - return true; } @@ -197,6 +194,6 @@ void totp_scene_token_menu_deactivate(PluginState* plugin_state) { plugin_state->current_scene_state = NULL; } -void totp_scene_token_menu_free(const PluginState* plugin_state) { +void totp_scene_token_menu_free(PluginState* plugin_state) { UNUSED(plugin_state); } diff --git a/applications/plugins/totp/scenes/token_menu/totp_scene_token_menu.h b/applications/plugins/totp/scenes/token_menu/totp_scene_token_menu.h index acb499be8..0b117cb25 100644 --- a/applications/plugins/totp/scenes/token_menu/totp_scene_token_menu.h +++ b/applications/plugins/totp/scenes/token_menu/totp_scene_token_menu.h @@ -7,14 +7,14 @@ #include "../../types/plugin_event.h" typedef struct { - uint16_t current_token_index; + uint8_t current_token_index; } TokenMenuSceneContext; -void totp_scene_token_menu_init(const PluginState* plugin_state); +void totp_scene_token_menu_init(PluginState* plugin_state); void totp_scene_token_menu_activate( PluginState* plugin_state, const TokenMenuSceneContext* context); void totp_scene_token_menu_render(Canvas* const canvas, PluginState* plugin_state); -bool totp_scene_token_menu_handle_event(const PluginEvent* const event, PluginState* plugin_state); +bool totp_scene_token_menu_handle_event(PluginEvent* const event, PluginState* plugin_state); void totp_scene_token_menu_deactivate(PluginState* plugin_state); -void totp_scene_token_menu_free(const PluginState* plugin_state); +void totp_scene_token_menu_free(PluginState* plugin_state); diff --git a/applications/plugins/totp/services/cli/cli.c b/applications/plugins/totp/services/cli/cli.c index 76e58a02d..3a7afdd96 100644 --- a/applications/plugins/totp/services/cli/cli.c +++ b/applications/plugins/totp/services/cli/cli.c @@ -9,7 +9,7 @@ #include "commands/timezone/timezone.h" #include "commands/help/help.h" -static void totp_cli_print_unknown_command(const FuriString* unknown_command) { +static void totp_cli_print_unknown_command(FuriString* unknown_command) { TOTP_CLI_PRINTF( "Command \"%s\" is unknown. Use \"" TOTP_CLI_COMMAND_HELP "\" command to get list of available commands.", diff --git a/applications/plugins/totp/services/cli/cli_helpers.c b/applications/plugins/totp/services/cli/cli_helpers.c index 4a0b8b352..81a1e4b77 100644 --- a/applications/plugins/totp/services/cli/cli_helpers.c +++ b/applications/plugins/totp/services/cli/cli_helpers.c @@ -1,7 +1,7 @@ #include "cli_helpers.h" #include -bool totp_cli_ensure_authenticated(const PluginState* plugin_state, Cli* cli) { +bool totp_cli_ensure_authenticated(PluginState* plugin_state, Cli* cli) { if(plugin_state->current_scene == TotpSceneAuthentication) { TOTP_CLI_PRINTF("Pleases enter PIN on your flipper device\r\n"); @@ -11,6 +11,7 @@ bool totp_cli_ensure_authenticated(const PluginState* plugin_state, Cli* cli) { } TOTP_CLI_DELETE_LAST_LINE(); + fflush(stdout); if(plugin_state->current_scene == TotpSceneAuthentication) { return false; diff --git a/applications/plugins/totp/services/cli/cli_helpers.h b/applications/plugins/totp/services/cli/cli_helpers.h index 9b19f926b..216925e50 100644 --- a/applications/plugins/totp/services/cli/cli_helpers.h +++ b/applications/plugins/totp/services/cli/cli_helpers.h @@ -13,28 +13,16 @@ #define DOCOPT_OPTIONS "[options]" #define DOCOPT_DEFAULT(val) "[default: " val "]" -#define TOTP_CLI_PRINTF(format, ...) \ - do { \ - _Pragma(STRINGIFY(GCC diagnostic push)) \ - _Pragma(STRINGIFY(GCC diagnostic ignored "-Wdouble-promotion")) \ - printf(format, ##__VA_ARGS__); \ - _Pragma(STRINGIFY(GCC diagnostic pop)) \ - } while(false) - -#define TOTP_CLI_DELETE_LAST_LINE() \ - TOTP_CLI_PRINTF("\033[A\33[2K\r"); \ - fflush(stdout) - -#define TOTP_CLI_DELETE_CURRENT_LINE() \ - TOTP_CLI_PRINTF("\33[2K\r"); \ - fflush(stdout) - -#define TOTP_CLI_DELETE_LAST_CHAR() \ - TOTP_CLI_PRINTF("\b \b"); \ - fflush(stdout) +#define TOTP_CLI_PRINTF(format, ...) \ + _Pragma(STRINGIFY(GCC diagnostic push)); \ + _Pragma(STRINGIFY(GCC diagnostic ignored "-Wdouble-promotion")); \ + printf(format, ##__VA_ARGS__); \ + _Pragma(STRINGIFY(GCC diagnostic pop)); +#define TOTP_CLI_DELETE_LAST_LINE() TOTP_CLI_PRINTF("\033[A\33[2K\r") +#define TOTP_CLI_DELETE_CURRENT_LINE() TOTP_CLI_PRINTF("\33[2K\r") #define TOTP_CLI_PRINT_INVALID_ARGUMENTS() \ TOTP_CLI_PRINTF( \ "Invalid command arguments. use \"help\" command to get list of available commands") -bool totp_cli_ensure_authenticated(const PluginState* plugin_state, Cli* cli); +bool totp_cli_ensure_authenticated(PluginState* plugin_state, Cli* cli); diff --git a/applications/plugins/totp/services/cli/commands/add/add.c b/applications/plugins/totp/services/cli/commands/add/add.c index 31548c59e..41ff5b860 100644 --- a/applications/plugins/totp/services/cli/commands/add/add.c +++ b/applications/plugins/totp/services/cli/commands/add/add.c @@ -14,7 +14,7 @@ #define TOTP_CLI_COMMAND_ADD_ARG_DIGITS_PREFIX "-d" #define TOTP_CLI_COMMAND_ADD_ARG_UNSECURE_PREFIX "-u" -static bool token_info_set_digits_from_str(TokenInfo* token_info, const FuriString* str) { +static bool token_info_set_digits_from_str(TokenInfo* token_info, FuriString* str) { switch(furi_string_get_char(str, 0)) { case '6': token_info->digits = TOTP_6_DIGITS; @@ -27,7 +27,7 @@ static bool token_info_set_digits_from_str(TokenInfo* token_info, const FuriStri return false; } -static bool token_info_set_algo_from_str(TokenInfo* token_info, const FuriString* str) { +static bool token_info_set_algo_from_str(TokenInfo* token_info, FuriString* str) { if(furi_string_cmpi_str(str, TOTP_CONFIG_TOKEN_ALGO_SHA1_NAME) == 0) { token_info->algo = SHA1; return true; @@ -79,53 +79,10 @@ void totp_cli_command_add_docopt_options() { TOTP_CLI_COMMAND_ADD_ARG_UNSECURE_PREFIX) " Show console user input as-is without masking\r\n"); } -static void furi_string_secure_free(FuriString* str) { - for(long i = furi_string_size(str) - 1; i >= 0; i--) { - furi_string_set_char(str, i, '\0'); - } - - furi_string_free(str); -} - -static bool totp_cli_read_secret(Cli* cli, FuriString* out_str, bool mask_user_input) { - uint8_t c; - while(cli_read(cli, &c, 1) == 1) { - if(c == CliSymbolAsciiEsc) { - // Some keys generating escape-sequences - // We need to ignore them as we case about alpha-numerics only - uint8_t c2; - cli_read_timeout(cli, &c2, 1, 0); - cli_read_timeout(cli, &c2, 1, 0); - } else if(c == CliSymbolAsciiETX) { - TOTP_CLI_DELETE_CURRENT_LINE(); - TOTP_CLI_PRINTF("Cancelled by user\r\n"); - return false; - } else if((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { - if(mask_user_input) { - putc('*', stdout); - } else { - putc(c, stdout); - } - fflush(stdout); - furi_string_push_back(out_str, c); - } else if(c == CliSymbolAsciiBackspace || c == CliSymbolAsciiDel) { - size_t out_str_size = furi_string_size(out_str); - if(out_str_size > 0) { - TOTP_CLI_DELETE_LAST_CHAR(); - furi_string_left(out_str, out_str_size - 1); - } - } else if(c == CliSymbolAsciiCR) { - cli_nl(); - break; - } - } - - TOTP_CLI_DELETE_LAST_LINE(); - return true; -} - void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args, Cli* cli) { FuriString* temp_str = furi_string_alloc(); + const char* temp_cstr; + TokenInfo* token_info = token_info_alloc(); // Reading token name @@ -136,9 +93,9 @@ void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args, Cl return; } - size_t temp_cstr_len = furi_string_size(temp_str); - token_info->name = malloc(temp_cstr_len + 1); - strlcpy(token_info->name, furi_string_get_cstr(temp_str), temp_cstr_len + 1); + temp_cstr = furi_string_get_cstr(temp_str); + token_info->name = malloc(strlen(temp_cstr) + 1); + strcpy(token_info->name, temp_cstr); // Read optional arguments bool mask_user_input = true; @@ -185,25 +142,59 @@ void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args, Cl // Reading token secret furi_string_reset(temp_str); TOTP_CLI_PRINTF("Enter token secret and confirm with [ENTER]\r\n"); - if(!totp_cli_read_secret(cli, temp_str, mask_user_input) || - !totp_cli_ensure_authenticated(plugin_state, cli)) { - furi_string_secure_free(temp_str); + + uint8_t c; + while(cli_read(cli, &c, 1) == 1) { + if(c == CliSymbolAsciiEsc) { + uint8_t c2; + cli_read_timeout(cli, &c2, 1, 0); + cli_read_timeout(cli, &c2, 1, 0); + } else if(c == CliSymbolAsciiETX) { + TOTP_CLI_DELETE_CURRENT_LINE(); + TOTP_CLI_PRINTF("Cancelled by user"); + furi_string_free(temp_str); + token_info_free(token_info); + return; + } else if((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { + if(mask_user_input) { + putc('*', stdout); + } else { + putc(c, stdout); + } + fflush(stdout); + furi_string_push_back(temp_str, c); + } else if(c == CliSymbolAsciiBackspace || c == CliSymbolAsciiDel) { + size_t temp_str_size = furi_string_size(temp_str); + if(temp_str_size > 0) { + TOTP_CLI_PRINTF("\b \b"); + fflush(stdout); + furi_string_left(temp_str, temp_str_size - 1); + } + } else if(c == CliSymbolAsciiCR) { + cli_nl(); + break; + } + } + + temp_cstr = furi_string_get_cstr(temp_str); + + TOTP_CLI_DELETE_LAST_LINE(); + + if(!totp_cli_ensure_authenticated(plugin_state, cli)) { + furi_string_free(temp_str); token_info_free(token_info); return; } - if(!token_info_set_secret( - token_info, - furi_string_get_cstr(temp_str), - furi_string_size(temp_str), - plugin_state->iv)) { + if(!token_info_set_secret(token_info, temp_cstr, strlen(temp_cstr), plugin_state->iv)) { TOTP_CLI_PRINTF("Token secret seems to be invalid and can not be parsed\r\n"); - furi_string_secure_free(temp_str); + furi_string_free(temp_str); token_info_free(token_info); return; } - furi_string_secure_free(temp_str); + furi_string_reset(temp_str); + furi_string_free(temp_str); bool load_generate_token_scene = false; if(plugin_state->current_scene == TotpSceneGenerateToken) { @@ -211,7 +202,11 @@ void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args, Cl load_generate_token_scene = true; } - TOTP_LIST_INIT_OR_ADD(plugin_state->tokens_list, token_info); + if(plugin_state->tokens_list == NULL) { + plugin_state->tokens_list = list_init_head(token_info); + } else { + list_add(plugin_state->tokens_list, token_info); + } plugin_state->tokens_count++; totp_config_file_save_new_token(token_info); diff --git a/applications/plugins/totp/services/config/config.c b/applications/plugins/totp/services/config/config.c index e751f7990..0854d79ad 100644 --- a/applications/plugins/totp/services/config/config.c +++ b/applications/plugins/totp/services/config/config.c @@ -10,7 +10,7 @@ #define CONFIG_FILE_PATH CONFIG_FILE_DIRECTORY_PATH "/totp.conf" #define CONFIG_FILE_BACKUP_PATH CONFIG_FILE_PATH ".backup" -static uint8_t token_info_get_digits_as_int(const TokenInfo* token_info) { +static uint8_t token_info_get_digits_as_int(TokenInfo* token_info) { switch(token_info->digits) { case TOTP_6_DIGITS: return 6; @@ -32,7 +32,7 @@ static void token_info_set_digits_from_int(TokenInfo* token_info, uint8_t digits } } -static char* token_info_get_algo_as_cstr(const TokenInfo* token_info) { +static char* token_info_get_algo_as_cstr(TokenInfo* token_info) { switch(token_info->algo) { case SHA1: return TOTP_CONFIG_TOKEN_ALGO_SHA1_NAME; @@ -45,7 +45,7 @@ static char* token_info_get_algo_as_cstr(const TokenInfo* token_info) { return NULL; } -static void token_info_set_algo_from_str(TokenInfo* token_info, const FuriString* str) { +static void token_info_set_algo_from_str(TokenInfo* token_info, FuriString* str) { if(furi_string_cmpi_str(str, TOTP_CONFIG_TOKEN_ALGO_SHA1_NAME) == 0) { token_info->algo = SHA1; } else if(furi_string_cmpi_str(str, TOTP_CONFIG_TOKEN_ALGO_SHA256_NAME) == 0) { @@ -152,7 +152,7 @@ FlipperFormat* totp_open_config_file(Storage* storage) { return fff_data_file; } -void totp_config_file_save_new_token_i(FlipperFormat* file, const TokenInfo* token_info) { +void totp_config_file_save_new_token_i(FlipperFormat* file, TokenInfo* token_info) { flipper_format_seek_to_end(file); flipper_format_write_string_cstr(file, TOTP_CONFIG_KEY_TOKEN_NAME, token_info->name); bool token_is_valid = token_info->token != NULL && token_info->token_length > 0; @@ -170,7 +170,7 @@ void totp_config_file_save_new_token_i(FlipperFormat* file, const TokenInfo* tok flipper_format_write_uint32(file, TOTP_CONFIG_KEY_TOKEN_DIGITS, &digits_count_as_uint32, 1); } -void totp_config_file_save_new_token(const TokenInfo* token_info) { +void totp_config_file_save_new_token(TokenInfo* token_info) { Storage* cfg_storage = totp_open_storage(); FlipperFormat* file = totp_open_config_file(cfg_storage); @@ -190,7 +190,7 @@ void totp_config_file_update_timezone_offset(float new_timezone_offset) { totp_close_storage(); } -void totp_full_save_config_file(const PluginState* const plugin_state) { +void totp_full_save_config_file(PluginState* const plugin_state) { Storage* storage = totp_open_storage(); FlipperFormat* fff_data_file = flipper_format_file_alloc(storage); @@ -209,7 +209,7 @@ void totp_full_save_config_file(const PluginState* const plugin_state) { flipper_format_write_bool(fff_data_file, TOTP_CONFIG_KEY_PINSET, &plugin_state->pin_set, 1); ListNode* node = plugin_state->tokens_list; while(node != NULL) { - const TokenInfo* token_info = node->data; + TokenInfo* token_info = node->data; totp_config_file_save_new_token_i(fff_data_file, token_info); node = node->next; } @@ -333,7 +333,7 @@ TokenLoadingResult totp_config_file_load_tokens(PluginState* const plugin_state) } TokenLoadingResult result = TokenLoadingResultSuccess; - uint16_t index = 0; + uint8_t index = 0; bool has_any_plain_secret = false; while(true) { @@ -343,9 +343,9 @@ TokenLoadingResult totp_config_file_load_tokens(PluginState* const plugin_state) TokenInfo* tokenInfo = token_info_alloc(); - size_t temp_cstr_len = furi_string_size(temp_str); - tokenInfo->name = (char*)malloc(temp_cstr_len + 1); - strlcpy(tokenInfo->name, furi_string_get_cstr(temp_str), temp_cstr_len + 1); + const char* temp_cstr = furi_string_get_cstr(temp_str); + tokenInfo->name = (char*)malloc(strlen(temp_cstr) + 1); + strcpy(tokenInfo->name, temp_cstr); uint32_t secret_bytes_count; if(!flipper_format_get_value_count( @@ -355,11 +355,9 @@ TokenLoadingResult totp_config_file_load_tokens(PluginState* const plugin_state) if(secret_bytes_count == 1) { // Plain secret key if(flipper_format_read_string(fff_data_file, TOTP_CONFIG_KEY_TOKEN_SECRET, temp_str)) { + temp_cstr = furi_string_get_cstr(temp_str); if(token_info_set_secret( - tokenInfo, - furi_string_get_cstr(temp_str), - furi_string_size(temp_str), - &plugin_state->iv[0])) { + tokenInfo, temp_cstr, strlen(temp_cstr), &plugin_state->iv[0])) { FURI_LOG_W(LOGGING_TAG, "Token \"%s\" has plain secret", tokenInfo->name); } else { tokenInfo->token = NULL; @@ -409,7 +407,11 @@ TokenLoadingResult totp_config_file_load_tokens(PluginState* const plugin_state) FURI_LOG_D(LOGGING_TAG, "Found token \"%s\"", tokenInfo->name); - TOTP_LIST_INIT_OR_ADD(plugin_state->tokens_list, tokenInfo); + if(plugin_state->tokens_list == NULL) { + plugin_state->tokens_list = list_init_head(tokenInfo); + } else { + list_add(plugin_state->tokens_list, tokenInfo); + } index++; } @@ -417,7 +419,7 @@ TokenLoadingResult totp_config_file_load_tokens(PluginState* const plugin_state) plugin_state->tokens_count = index; plugin_state->token_list_loaded = true; - FURI_LOG_D(LOGGING_TAG, "Found %" PRIu16 " tokens", index); + FURI_LOG_D(LOGGING_TAG, "Found %" PRIu8 " tokens", index); furi_string_free(temp_str); totp_close_config_file(fff_data_file); diff --git a/applications/plugins/totp/services/config/config.h b/applications/plugins/totp/services/config/config.h index d452ad4b3..76cb40b2c 100644 --- a/applications/plugins/totp/services/config/config.h +++ b/applications/plugins/totp/services/config/config.h @@ -16,8 +16,8 @@ Storage* totp_open_storage(); void totp_close_storage(); FlipperFormat* totp_open_config_file(Storage* storage); void totp_close_config_file(FlipperFormat* file); -void totp_full_save_config_file(const PluginState* const plugin_state); +void totp_full_save_config_file(PluginState* const plugin_state); void totp_config_file_load_base(PluginState* const plugin_state); TokenLoadingResult totp_config_file_load_tokens(PluginState* const plugin_state); -void totp_config_file_save_new_token(const TokenInfo* token_info); +void totp_config_file_save_new_token(TokenInfo* token_info); void totp_config_file_update_timezone_offset(float new_timezone_offset); diff --git a/applications/plugins/totp/services/crypto/crypto.c b/applications/plugins/totp/services/crypto/crypto.c index 79e41e6fd..ade2f9f49 100644 --- a/applications/plugins/totp/services/crypto/crypto.c +++ b/applications/plugins/totp/services/crypto/crypto.c @@ -3,7 +3,6 @@ #include #include "../config/config.h" #include "../../types/common.h" -#include "memset_s.h" #define CRYPTO_KEY_SLOT 2 #define CRYPTO_VERIFY_KEY "FFF_Crypto_pass" @@ -12,13 +11,13 @@ uint8_t* totp_crypto_encrypt( const uint8_t* plain_data, - const size_t plain_data_length, + const uint8_t plain_data_length, const uint8_t* iv, - size_t* encrypted_data_length) { + uint8_t* encrypted_data_length) { uint8_t* encrypted_data; size_t remain = plain_data_length % CRYPTO_ALIGNMENT_FACTOR; if(remain) { - size_t plain_data_aligned_length = plain_data_length - remain + CRYPTO_ALIGNMENT_FACTOR; + uint8_t plain_data_aligned_length = plain_data_length - remain + CRYPTO_ALIGNMENT_FACTOR; uint8_t* plain_data_aligned = malloc(plain_data_aligned_length); memset(plain_data_aligned, 0, plain_data_aligned_length); memcpy(plain_data_aligned, plain_data, plain_data_length); @@ -30,7 +29,7 @@ uint8_t* totp_crypto_encrypt( furi_hal_crypto_encrypt(plain_data_aligned, encrypted_data, plain_data_aligned_length); furi_hal_crypto_store_unload_key(CRYPTO_KEY_SLOT); - memset_s(plain_data_aligned, sizeof(plain_data_aligned), 0, plain_data_aligned_length); + memset(plain_data_aligned, 0, plain_data_aligned_length); free(plain_data_aligned); } else { encrypted_data = malloc(plain_data_length); @@ -46,9 +45,9 @@ uint8_t* totp_crypto_encrypt( uint8_t* totp_crypto_decrypt( const uint8_t* encrypted_data, - const size_t encrypted_data_length, + const uint8_t encrypted_data_length, const uint8_t* iv, - size_t* decrypted_data_length) { + uint8_t* decrypted_data_length) { *decrypted_data_length = encrypted_data_length; uint8_t* decrypted_data = malloc(*decrypted_data_length); furi_hal_crypto_store_load_key(CRYPTO_KEY_SLOT, iv); @@ -57,7 +56,7 @@ uint8_t* totp_crypto_decrypt( return decrypted_data; } -void totp_crypto_seed_iv(PluginState* plugin_state, const uint8_t* pin, uint8_t pin_length) { +void totp_crypto_seed_iv(PluginState* plugin_state, uint8_t* pin, uint8_t pin_length) { if(plugin_state->crypto_verify_data == NULL) { FURI_LOG_D(LOGGING_TAG, "Generating new IV"); furi_hal_random_fill_buf(&plugin_state->base_iv[0], TOTP_IV_SIZE); @@ -119,8 +118,8 @@ void totp_crypto_seed_iv(PluginState* plugin_state, const uint8_t* pin, uint8_t } bool totp_crypto_verify_key(const PluginState* plugin_state) { - size_t decrypted_key_length; - const uint8_t* decrypted_key = totp_crypto_decrypt( + uint8_t decrypted_key_length; + uint8_t* decrypted_key = totp_crypto_decrypt( plugin_state->crypto_verify_data, plugin_state->crypto_verify_data_length, &plugin_state->iv[0], diff --git a/applications/plugins/totp/services/crypto/crypto.h b/applications/plugins/totp/services/crypto/crypto.h index f0a28f798..9fc319659 100644 --- a/applications/plugins/totp/services/crypto/crypto.h +++ b/applications/plugins/totp/services/crypto/crypto.h @@ -4,13 +4,13 @@ uint8_t* totp_crypto_encrypt( const uint8_t* plain_data, - const size_t plain_data_length, + const uint8_t plain_data_length, const uint8_t* iv, - size_t* encrypted_data_length); + uint8_t* encrypted_data_length); uint8_t* totp_crypto_decrypt( const uint8_t* encrypted_data, - const size_t encrypted_data_length, + const uint8_t encrypted_data_length, const uint8_t* iv, - size_t* decrypted_data_length); -void totp_crypto_seed_iv(PluginState* plugin_state, const uint8_t* pin, uint8_t pin_length); + uint8_t* decrypted_data_length); +void totp_crypto_seed_iv(PluginState* plugin_state, uint8_t* pin, uint8_t pin_length); bool totp_crypto_verify_key(const PluginState* plugin_state); \ No newline at end of file diff --git a/applications/plugins/totp/services/crypto/memset_s.c b/applications/plugins/totp/services/crypto/memset_s.c deleted file mode 100644 index 81c285c0d..000000000 --- a/applications/plugins/totp/services/crypto/memset_s.c +++ /dev/null @@ -1,22 +0,0 @@ -#include "memset_s.h" - -#define RSIZE_MAX 0x7fffffffffffffffUL - -errno_t memset_s(void* s, rsize_t smax, int c, rsize_t n) { - if(!s || smax > RSIZE_MAX) { - return EINVAL; - } - - errno_t violation_present = 0; - if(n > smax) { - n = smax; - violation_present = EINVAL; - } - - volatile unsigned char* v = s; - for(rsize_t i = 0u; i < n; ++i) { - *v++ = (unsigned char)c; - } - - return violation_present; -} \ No newline at end of file diff --git a/applications/plugins/totp/services/crypto/memset_s.h b/applications/plugins/totp/services/crypto/memset_s.h deleted file mode 100644 index 2889e23b2..000000000 --- a/applications/plugins/totp/services/crypto/memset_s.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include -#include -#include - -#ifndef _RSIZE_T_DECLARED -typedef uint64_t rsize_t; -#define _RSIZE_T_DECLARED -#endif -#ifndef _ERRNOT_DECLARED -typedef int16_t errno_t; -#define _ERRNOT_DECLARED -#endif - -errno_t memset_s(void* s, rsize_t smax, int c, rsize_t n); \ No newline at end of file diff --git a/applications/plugins/totp/services/list/list.c b/applications/plugins/totp/services/list/list.c index 20d92e71b..3a3317980 100644 --- a/applications/plugins/totp/services/list/list.c +++ b/applications/plugins/totp/services/list/list.c @@ -26,7 +26,7 @@ ListNode* list_add(ListNode* head, void* data) { return head; } -ListNode* list_find(ListNode* head, const void* data) { +ListNode* list_find(ListNode* head, void* data) { ListNode* it; for(it = head; it != NULL; it = it->next) @@ -66,8 +66,7 @@ ListNode* list_remove(ListNode* head, ListNode* ep) { } void list_free(ListNode* head) { - ListNode* it = head; - ListNode* tmp; + ListNode *it = head, *tmp; while(it != NULL) { tmp = it; diff --git a/applications/plugins/totp/services/list/list.h b/applications/plugins/totp/services/list/list.h index 93acb0f34..771eac565 100644 --- a/applications/plugins/totp/services/list/list.h +++ b/applications/plugins/totp/services/list/list.h @@ -14,7 +14,7 @@ ListNode* list_add( void* data); /* adds element with specified data to the end of the list and returns new head node. */ ListNode* list_find( ListNode* head, - const void* data); /* returns pointer of element with specified data in list. */ + void* data); /* returns pointer of element with specified data in list. */ ListNode* list_element_at( ListNode* head, uint16_t index); /* returns pointer of element with specified index in list. */ @@ -22,12 +22,3 @@ ListNode* list_remove( ListNode* head, ListNode* ep); /* removes element from the list and returns new head node. */ void list_free(ListNode* head); /* deletes all elements of the list. */ - -#define TOTP_LIST_INIT_OR_ADD(head, item) \ - do { \ - if(head == NULL) { \ - head = list_init_head(item); \ - } else { \ - list_add(head, item); \ - } \ - } while(false) diff --git a/applications/plugins/totp/services/nullable/nullable.h b/applications/plugins/totp/services/nullable/nullable.h deleted file mode 100644 index 4f9b7bc01..000000000 --- a/applications/plugins/totp/services/nullable/nullable.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include -#include - -#define TOTP_NULLABLE_STRUCT(value_type) \ - typedef struct TotpNullable_##value_type { \ - bool is_null; \ - value_type value; \ - } TotpNullable_##value_type - -#define TOTP_NULLABLE_NULL(s) s.is_null = true -#define TOTP_NULLABLE_VALUE(s, v) \ - s.is_null = false; \ - s.value = v - -TOTP_NULLABLE_STRUCT(uint16_t); diff --git a/applications/plugins/totp/services/roll_value/roll_value.c b/applications/plugins/totp/services/roll_value/roll_value.c deleted file mode 100644 index b8f30e078..000000000 --- a/applications/plugins/totp/services/roll_value/roll_value.c +++ /dev/null @@ -1,28 +0,0 @@ -#include "roll_value.h" - -#define TOTP_ROLL_VALUE_FN(type, step_type) \ - TOTP_ROLL_VALUE_FN_HEADER(type, step_type) { \ - type v = *value; \ - if(step > 0 && v > max - step) { \ - if(overflow_behavior == RollOverflowBehaviorRoll) { \ - v = min; \ - } else if(overflow_behavior == RollOverflowBehaviorStop) { \ - v = max; \ - } \ - } else if(step < 0 && v < min - step) { \ - if(overflow_behavior == RollOverflowBehaviorRoll) { \ - v = max; \ - } else if(overflow_behavior == RollOverflowBehaviorStop) { \ - v = min; \ - } \ - } else { \ - v += step; \ - } \ - *value = v; \ - } - -TOTP_ROLL_VALUE_FN(int8_t, int8_t) - -TOTP_ROLL_VALUE_FN(uint8_t, int8_t) - -TOTP_ROLL_VALUE_FN(uint16_t, int16_t); \ No newline at end of file diff --git a/applications/plugins/totp/services/roll_value/roll_value.h b/applications/plugins/totp/services/roll_value/roll_value.h deleted file mode 100644 index 87337597f..000000000 --- a/applications/plugins/totp/services/roll_value/roll_value.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include - -typedef enum { RollOverflowBehaviorStop, RollOverflowBehaviorRoll } TotpRollValueOverflowBehavior; - -#define TOTP_ROLL_VALUE_FN_HEADER(type, step_type) \ - void totp_roll_value_##type( \ - type* value, \ - step_type step, \ - type min, \ - type max, \ - TotpRollValueOverflowBehavior overflow_behavior) - -TOTP_ROLL_VALUE_FN_HEADER(int8_t, int8_t); -TOTP_ROLL_VALUE_FN_HEADER(uint8_t, int8_t); -TOTP_ROLL_VALUE_FN_HEADER(uint16_t, int16_t); \ No newline at end of file diff --git a/applications/plugins/totp/services/totp/totp.c b/applications/plugins/totp/services/totp/totp.c index 68531e171..90e49367d 100644 --- a/applications/plugins/totp/services/totp/totp.c +++ b/applications/plugins/totp/services/totp/totp.c @@ -42,14 +42,14 @@ uint32_t otp_generate( TOTP_ALGO algo, uint8_t digits, const uint8_t* plain_secret, - size_t plain_secret_length, + uint8_t plain_secret_length, uint64_t input) { uint8_t* hmac = malloc(64); memset(hmac, 0, 64); uint64_t input_swapped = swap_uint64(input); - int hmac_len = (*algo)(plain_secret, plain_secret_length, (uint8_t*)&input_swapped, 8, hmac); + int hmac_len = (*(algo))(plain_secret, plain_secret_length, (uint8_t*)&input_swapped, 8, hmac); if(hmac_len == 0) { free(hmac); return OTP_ERROR; @@ -80,7 +80,7 @@ uint32_t totp_at( TOTP_ALGO algo, uint8_t digits, const uint8_t* plain_secret, - size_t plain_secret_length, + uint8_t plain_secret_length, uint64_t for_time, float timezone, uint8_t interval) { @@ -96,9 +96,9 @@ uint32_t totp_at( static int totp_algo_sha1( const uint8_t* key, - size_t key_length, + uint8_t key_length, const uint8_t* input, - size_t input_length, + uint8_t input_length, uint8_t* output) { hmac_sha1(key, key_length, input, input_length, output); return HMAC_SHA1_RESULT_SIZE; @@ -106,9 +106,9 @@ static int totp_algo_sha1( static int totp_algo_sha256( const uint8_t* key, - size_t key_length, + uint8_t key_length, const uint8_t* input, - size_t input_length, + uint8_t input_length, uint8_t* output) { hmac_sha256(key, key_length, input, input_length, output); return HMAC_SHA256_RESULT_SIZE; @@ -116,9 +116,9 @@ static int totp_algo_sha256( static int totp_algo_sha512( const uint8_t* key, - size_t key_length, + uint8_t key_length, const uint8_t* input, - size_t input_length, + uint8_t input_length, uint8_t* output) { hmac_sha512(key, key_length, input, input_length, output); return HMAC_SHA512_RESULT_SIZE; diff --git a/applications/plugins/totp/services/totp/totp.h b/applications/plugins/totp/services/totp/totp.h index 431ca11aa..31e70e01b 100644 --- a/applications/plugins/totp/services/totp/totp.h +++ b/applications/plugins/totp/services/totp/totp.h @@ -17,9 +17,9 @@ */ typedef int (*TOTP_ALGO)( const uint8_t* key, - size_t key_length, + uint8_t key_length, const uint8_t* input, - size_t input_length, + uint8_t input_length, uint8_t* output); /* @@ -47,7 +47,7 @@ uint32_t totp_at( TOTP_ALGO algo, uint8_t digits, const uint8_t* plain_secret, - size_t plain_secret_length, + uint8_t plain_secret_length, uint64_t for_time, float timezone, uint8_t interval); diff --git a/applications/plugins/totp/services/ui/icons.h b/applications/plugins/totp/services/ui/icons.h new file mode 100644 index 000000000..2ce25a898 --- /dev/null +++ b/applications/plugins/totp/services/ui/icons.h @@ -0,0 +1,13 @@ +#pragma once + +#include +#include + +#define ICON_ARROW_LEFT_8x9_WIDTH 8 +#define ICON_ARROW_LEFT_8x9_HEIGHT 9 +static const uint8_t ICON_ARROW_LEFT_8x9[] = {0x80, 0xe0, 0xf8, 0xfe, 0xff, 0xfe, 0xf8, 0xe0, 0x80}; + +#define ICON_ARROW_RIGHT_8x9_WIDTH 8 +#define ICON_ARROW_RIGHT_8x9_HEIGHT 9 +static const uint8_t ICON_ARROW_RIGHT_8x9[] = + {0x01, 0x07, 0x1f, 0x7f, 0xff, 0x7f, 0x1f, 0x07, 0x01}; diff --git a/applications/plugins/totp/services/ui/ui_controls.c b/applications/plugins/totp/services/ui/ui_controls.c index af029dd9f..7f6a4dd4d 100644 --- a/applications/plugins/totp/services/ui/ui_controls.c +++ b/applications/plugins/totp/services/ui/ui_controls.c @@ -1,15 +1,11 @@ #include "ui_controls.h" -#include #include "constants.h" +#include "icons.h" #define TEXT_BOX_HEIGHT 13 #define TEXT_BOX_MARGIN 4 -void ui_control_text_box_render( - Canvas* const canvas, - int16_t y, - const char* text, - bool is_selected) { +void ui_control_text_box_render(Canvas* const canvas, int8_t y, char* text, bool is_selected) { if(y < -TEXT_BOX_HEIGHT) { return; } @@ -48,7 +44,7 @@ void ui_control_select_render( int16_t x, int16_t y, uint8_t width, - const char* text, + char* text, bool is_selected) { if(y < -TEXT_BOX_HEIGHT) { return; @@ -81,10 +77,20 @@ void ui_control_select_render( canvas_draw_str_aligned( canvas, x + (width >> 1), TEXT_BOX_MARGIN + 3 + y, AlignCenter, AlignTop, text); - canvas_draw_icon( - canvas, x + TEXT_BOX_MARGIN + 2, TEXT_BOX_MARGIN + 2 + y, &I_totp_arrow_left_8x9); - canvas_draw_icon( - canvas, x + width - TEXT_BOX_MARGIN - 10, TEXT_BOX_MARGIN + 2 + y, &I_totp_arrow_right_8x9); + canvas_draw_xbm( + canvas, + x + TEXT_BOX_MARGIN + 2, + TEXT_BOX_MARGIN + 2 + y, + ICON_ARROW_LEFT_8x9_WIDTH, + ICON_ARROW_LEFT_8x9_HEIGHT, + &ICON_ARROW_LEFT_8x9[0]); + canvas_draw_xbm( + canvas, + x + width - TEXT_BOX_MARGIN - 10, + TEXT_BOX_MARGIN + 2 + y, + ICON_ARROW_RIGHT_8x9_WIDTH, + ICON_ARROW_RIGHT_8x9_HEIGHT, + &ICON_ARROW_RIGHT_8x9[0]); } void ui_control_button_render( @@ -93,7 +99,7 @@ void ui_control_button_render( int16_t y, uint8_t width, uint8_t height, - const char* text, + char* text, bool is_selected) { if(y < -height) { return; diff --git a/applications/plugins/totp/services/ui/ui_controls.h b/applications/plugins/totp/services/ui/ui_controls.h index ef3af5f55..e86b3e5d9 100644 --- a/applications/plugins/totp/services/ui/ui_controls.h +++ b/applications/plugins/totp/services/ui/ui_controls.h @@ -3,23 +3,19 @@ #include #include -void ui_control_text_box_render( - Canvas* const canvas, - int16_t y, - const char* text, - bool is_selected); +void ui_control_text_box_render(Canvas* const canvas, int8_t y, char* text, bool is_selected); void ui_control_button_render( Canvas* const canvas, int16_t x, int16_t y, uint8_t width, uint8_t height, - const char* text, + char* text, bool is_selected); void ui_control_select_render( Canvas* const canvas, int16_t x, int16_t y, uint8_t width, - const char* text, + char* text, bool is_selected); diff --git a/applications/plugins/totp/totp_app.c b/applications/plugins/totp/totp_app.c index f296a734b..ede8416b6 100644 --- a/applications/plugins/totp/totp_app.c +++ b/applications/plugins/totp/totp_app.c @@ -154,22 +154,22 @@ int32_t totp_app() { if(plugin_state->changing_scene) continue; FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); - PluginState* plugin_state_m = acquire_mutex_block(&state_mutex); + PluginState* plugin_state = acquire_mutex_block(&state_mutex); if(event_status == FuriStatusOk) { if(event.type == EventTypeKey) { last_user_interaction_time = furi_get_tick(); } - processing = totp_scene_director_handle_event(&event, plugin_state_m); + processing = totp_scene_director_handle_event(&event, plugin_state); } else if( - plugin_state_m->pin_set && plugin_state_m->current_scene != TotpSceneAuthentication && + plugin_state->pin_set && plugin_state->current_scene != TotpSceneAuthentication && furi_get_tick() - last_user_interaction_time > IDLE_TIMEOUT) { - totp_scene_director_activate_scene(plugin_state_m, TotpSceneAuthentication, NULL); + totp_scene_director_activate_scene(plugin_state, TotpSceneAuthentication, NULL); } view_port_update(view_port); - release_mutex(&state_mutex, plugin_state_m); + release_mutex(&state_mutex, plugin_state); } view_port_enabled_set(view_port, false); diff --git a/applications/plugins/totp/types/plugin_state.h b/applications/plugins/totp/types/plugin_state.h index 9b16d7d57..98afe53cf 100644 --- a/applications/plugins/totp/types/plugin_state.h +++ b/applications/plugins/totp/types/plugin_state.h @@ -19,10 +19,10 @@ typedef struct { float timezone_offset; ListNode* tokens_list; bool token_list_loaded; - uint16_t tokens_count; + uint8_t tokens_count; uint8_t* crypto_verify_data; - size_t crypto_verify_data_length; + uint8_t crypto_verify_data_length; bool pin_set; uint8_t iv[TOTP_IV_SIZE]; uint8_t base_iv[TOTP_IV_SIZE]; diff --git a/applications/plugins/totp/types/token_info.c b/applications/plugins/totp/types/token_info.c index 17b2af9aa..09ad1230a 100644 --- a/applications/plugins/totp/types/token_info.c +++ b/applications/plugins/totp/types/token_info.c @@ -5,7 +5,6 @@ #include "common.h" #include "../services/base32/base32.h" #include "../services/crypto/crypto.h" -#include "../services/crypto/memset_s.h" TokenInfo* token_info_alloc() { TokenInfo* tokenInfo = malloc(sizeof(TokenInfo)); @@ -24,11 +23,11 @@ void token_info_free(TokenInfo* token_info) { bool token_info_set_secret( TokenInfo* token_info, const char* base32_token_secret, - size_t token_secret_length, - const uint8_t* iv) { + uint8_t token_secret_length, + uint8_t* iv) { uint8_t* plain_secret = malloc(token_secret_length); int plain_secret_length = - base32_decode((const uint8_t*)base32_token_secret, plain_secret, token_secret_length); + base32_decode((uint8_t*)base32_token_secret, plain_secret, token_secret_length); bool result; if(plain_secret_length >= 0) { token_info->token = @@ -38,12 +37,12 @@ bool token_info_set_secret( result = false; } - memset_s(plain_secret, sizeof(plain_secret), 0, token_secret_length); + memset(plain_secret, 0, token_secret_length); free(plain_secret); return result; } -uint8_t token_info_get_digits_count(const TokenInfo* token_info) { +uint8_t token_info_get_digits_count(TokenInfo* token_info) { switch(token_info->digits) { case TOTP_6_DIGITS: return 6; diff --git a/applications/plugins/totp/types/token_info.h b/applications/plugins/totp/types/token_info.h index 4f1223367..e40c6e9bf 100644 --- a/applications/plugins/totp/types/token_info.h +++ b/applications/plugins/totp/types/token_info.h @@ -8,7 +8,7 @@ typedef enum { TOTP_6_DIGITS, TOTP_8_DIGITS } TokenDigitsCount; typedef struct { uint8_t* token; - size_t token_length; + uint8_t token_length; char* name; TokenHashAlgo algo; TokenDigitsCount digits; @@ -19,6 +19,6 @@ void token_info_free(TokenInfo* token_info); bool token_info_set_secret( TokenInfo* token_info, const char* base32_token_secret, - size_t token_secret_length, - const uint8_t* iv); -uint8_t token_info_get_digits_count(const TokenInfo* token_info); + uint8_t token_secret_length, + uint8_t* iv); +uint8_t token_info_get_digits_count(TokenInfo* token_info); From 0b1f573a726d4043d51ce5f9549dd0c8bb6b1d96 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Thu, 3 Nov 2022 00:53:28 +0300 Subject: [PATCH 23/23] update naming --- applications/plugins/am2320_temp_sensor/application.fam | 4 ++-- applications/plugins/am2320_temp_sensor/temperature_sensor.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/applications/plugins/am2320_temp_sensor/application.fam b/applications/plugins/am2320_temp_sensor/application.fam index cd4afdc4a..9a17539dd 100644 --- a/applications/plugins/am2320_temp_sensor/application.fam +++ b/applications/plugins/am2320_temp_sensor/application.fam @@ -2,8 +2,8 @@ App( appid="am2320_temp_sensor", name="[AM2320] Temp. Sensor", apptype=FlipperAppType.EXTERNAL, - entry_point="temperature_sensor_app", - cdefines=["APP_TEMPERATURE_SENSOR"], + entry_point="am_temperature_sensor_app", + cdefines=["APP_AM_TEMPERATURE_SENSOR"], requires=[ "gui", ], diff --git a/applications/plugins/am2320_temp_sensor/temperature_sensor.c b/applications/plugins/am2320_temp_sensor/temperature_sensor.c index 236c5e2d2..212014e22 100644 --- a/applications/plugins/am2320_temp_sensor/temperature_sensor.c +++ b/applications/plugins/am2320_temp_sensor/temperature_sensor.c @@ -234,7 +234,7 @@ static void temperature_sensor_timer_callback(FuriMessageQueue* event_queue) { // App entry point -int32_t temperature_sensor_app(void* p) { +int32_t am_temperature_sensor_app(void* p) { UNUSED(p); furi_hal_power_suppress_charge_enter();