diff --git a/.vscode/example/tasks.json b/.vscode/example/tasks.json index e36a1fe47a..1bc6d9ee75 100644 --- a/.vscode/example/tasks.json +++ b/.vscode/example/tasks.json @@ -79,7 +79,7 @@ "label": "[Debug:unit_tests] Flash (USB)", "group": "build", "type": "shell", - "command": "./fbt FIRMWARE_APP_SET=unit_tests FORCE=1 flash_usb" + "command": "./fbt FIRMWARE_APP_SET=unit_tests FORCE=1 flash_usb_full" }, { "label": "[Debug] Flash (USB, with resources)", diff --git a/applications/debug/unit_tests/application.fam b/applications/debug/unit_tests/application.fam index aa25dab279..f5f84ead79 100644 --- a/applications/debug/unit_tests/application.fam +++ b/applications/debug/unit_tests/application.fam @@ -2,8 +2,9 @@ App( appid="unit_tests", apptype=FlipperAppType.STARTUP, entry_point="unit_tests_on_system_start", + sources=["unit_tests.c", "test_runner.c", "unit_test_api_table.cpp"], cdefines=["APP_UNIT_TESTS"], - requires=["system_settings"], + requires=["system_settings", "subghz_start"], provides=["delay_test"], resources="resources", order=100, @@ -12,9 +13,210 @@ App( App( appid="delay_test", name="Delay Test", + sources=["tests/common/*.c", "tests/rpc/*.c"], apptype=FlipperAppType.SYSTEM, entry_point="delay_test_app", stack_size=1 * 1024, requires=["unit_tests"], order=110, ) + +App( + appid="test_varint", + sources=["tests/common/*.c", "tests/varint/*.c"], + apptype=FlipperAppType.PLUGIN, + entry_point="get_api", + requires=["unit_tests"], +) + +App( + appid="test_furi", + sources=["tests/common/*.c", "tests/furi/*.c"], + apptype=FlipperAppType.PLUGIN, + entry_point="get_api", + requires=["unit_tests"], +) + +App( + appid="test_furi_hal", + sources=["tests/common/*.c", "tests/furi_hal/*.c"], + apptype=FlipperAppType.PLUGIN, + entry_point="get_api", + requires=["unit_tests"], +) + +App( + appid="test_furi_hal_crypto", + sources=["tests/common/*.c", "tests/furi_hal_crypto/*.c"], + apptype=FlipperAppType.PLUGIN, + entry_point="get_api", + requires=["unit_tests"], +) + +App( + appid="test_furi_string", + sources=["tests/common/*.c", "tests/furi_string/*.c"], + apptype=FlipperAppType.PLUGIN, + entry_point="get_api", + requires=["unit_tests"], +) + +App( + appid="test_storage", + sources=["tests/common/*.c", "tests/storage/*.c"], + apptype=FlipperAppType.PLUGIN, + entry_point="get_api", + requires=["unit_tests"], +) + +App( + appid="test_stream", + sources=["tests/common/*.c", "tests/stream/*.c"], + apptype=FlipperAppType.PLUGIN, + entry_point="get_api", + requires=["unit_tests"], +) + +App( + appid="test_dirwalk", + sources=["tests/common/*.c", "tests/dirwalk/*.c"], + apptype=FlipperAppType.PLUGIN, + entry_point="get_api", + requires=["unit_tests"], +) + +App( + appid="test_manifest", + sources=["tests/common/*.c", "tests/manifest/*.c"], + apptype=FlipperAppType.PLUGIN, + entry_point="get_api", + requires=["unit_tests"], +) + +App( + appid="test_flipper_format", + sources=["tests/common/*.c", "tests/flipper_format/*.c"], + apptype=FlipperAppType.PLUGIN, + entry_point="get_api", + requires=["unit_tests"], +) + +App( + appid="test_flipper_format_string", + sources=["tests/common/*.c", "tests/flipper_format_string/*.c"], + apptype=FlipperAppType.PLUGIN, + entry_point="get_api", + requires=["unit_tests"], +) + +App( + appid="test_rpc", + sources=["tests/common/*.c", "tests/rpc/*.c"], + apptype=FlipperAppType.PLUGIN, + entry_point="get_api", + requires=["unit_tests"], +) + +App( + appid="test_subghz", + sources=["tests/common/*.c", "tests/subghz/*.c"], + apptype=FlipperAppType.PLUGIN, + entry_point="get_api", + requires=["unit_tests"], +) + +App( + appid="test_infrared", + sources=["tests/common/*.c", "tests/infrared/*.c"], + apptype=FlipperAppType.PLUGIN, + entry_point="get_api", + requires=["unit_tests"], +) + +App( + appid="test_nfc", + sources=["tests/common/*.c", "tests/nfc/*.c"], + apptype=FlipperAppType.PLUGIN, + entry_point="get_api", + requires=["unit_tests"], +) + +App( + appid="test_power", + sources=["tests/common/*.c", "tests/power/*.c"], + apptype=FlipperAppType.PLUGIN, + entry_point="get_api", + requires=["unit_tests"], +) + +App( + appid="test_protocol_dict", + sources=["tests/common/*.c", "tests/protocol_dict/*.c"], + apptype=FlipperAppType.PLUGIN, + entry_point="get_api", + requires=["unit_tests"], +) + +App( + appid="test_lfrfid", + sources=["tests/common/*.c", "tests/lfrfid/*.c"], + apptype=FlipperAppType.PLUGIN, + entry_point="get_api", + requires=["unit_tests"], +) + +App( + appid="test_bit_lib", + sources=["tests/common/*.c", "tests/bit_lib/*.c"], + apptype=FlipperAppType.PLUGIN, + entry_point="get_api", + requires=["unit_tests"], +) + +App( + appid="test_datetime", + sources=["tests/common/*.c", "tests/datetime/*.c"], + apptype=FlipperAppType.PLUGIN, + entry_point="get_api", + requires=["unit_tests"], +) + +App( + appid="test_float_tools", + sources=["tests/common/*.c", "tests/float_tools/*.c"], + apptype=FlipperAppType.PLUGIN, + entry_point="get_api", + requires=["unit_tests"], +) + +App( + appid="test_bt", + sources=["tests/common/*.c", "tests/bt/*.c"], + apptype=FlipperAppType.PLUGIN, + entry_point="get_api", + requires=["unit_tests"], +) + +App( + appid="test_dialogs_file_browser_options", + sources=["tests/common/*.c", "tests/dialogs_file_browser_options/*.c"], + apptype=FlipperAppType.PLUGIN, + entry_point="get_api", + requires=["unit_tests"], +) + +App( + appid="test_expansion", + sources=["tests/common/*.c", "tests/expansion/*.c"], + apptype=FlipperAppType.PLUGIN, + entry_point="get_api", + requires=["unit_tests"], +) + +App( + appid="test_compress", + sources=["tests/common/*.c", "tests/compress/*.c"], + apptype=FlipperAppType.PLUGIN, + entry_point="get_api", + requires=["unit_tests"], +) diff --git a/applications/debug/unit_tests/resources/unit_tests/compress/compressed.bin b/applications/debug/unit_tests/resources/unit_tests/compress/compressed.bin new file mode 100644 index 0000000000..95d729295a Binary files /dev/null and b/applications/debug/unit_tests/resources/unit_tests/compress/compressed.bin differ diff --git a/applications/debug/unit_tests/resources/unit_tests/compress/uncompressed.bin b/applications/debug/unit_tests/resources/unit_tests/compress/uncompressed.bin new file mode 100644 index 0000000000..c4d02a5d20 Binary files /dev/null and b/applications/debug/unit_tests/resources/unit_tests/compress/uncompressed.bin differ diff --git a/applications/debug/unit_tests/test_index.c b/applications/debug/unit_tests/test_index.c deleted file mode 100644 index 5d0282bd77..0000000000 --- a/applications/debug/unit_tests/test_index.c +++ /dev/null @@ -1,168 +0,0 @@ -#include -#include -#include -#include "minunit_vars.h" -#include -#include -#include - -#define TAG "UnitTests" - -int run_minunit_test_furi(void); -int run_minunit_test_furi_hal(void); -int run_minunit_test_furi_hal_crypto(void); -int run_minunit_test_furi_string(void); -int run_minunit_test_infrared(void); -int run_minunit_test_rpc(void); -int run_minunit_test_manifest(void); -int run_minunit_test_flipper_format(void); -int run_minunit_test_flipper_format_string(void); -int run_minunit_test_stream(void); -int run_minunit_test_storage(void); -int run_minunit_test_subghz(void); -int run_minunit_test_dirwalk(void); -int run_minunit_test_power(void); -int run_minunit_test_protocol_dict(void); -int run_minunit_test_lfrfid_protocols(void); -int run_minunit_test_nfc(void); -int run_minunit_test_bit_lib(void); -int run_minunit_test_datetime(void); -int run_minunit_test_float_tools(void); -int run_minunit_test_bt(void); -int run_minunit_test_dialogs_file_browser_options(void); -int run_minunit_test_expansion(void); - -typedef int (*UnitTestEntry)(void); - -typedef struct { - const char* name; - const UnitTestEntry entry; -} UnitTest; - -const UnitTest unit_tests[] = { - {.name = "furi", .entry = run_minunit_test_furi}, - {.name = "furi_hal", .entry = run_minunit_test_furi_hal}, - {.name = "furi_hal_crypto", .entry = run_minunit_test_furi_hal_crypto}, - {.name = "furi_string", .entry = run_minunit_test_furi_string}, - {.name = "storage", .entry = run_minunit_test_storage}, - {.name = "stream", .entry = run_minunit_test_stream}, - {.name = "dirwalk", .entry = run_minunit_test_dirwalk}, - {.name = "manifest", .entry = run_minunit_test_manifest}, - {.name = "flipper_format", .entry = run_minunit_test_flipper_format}, - {.name = "flipper_format_string", .entry = run_minunit_test_flipper_format_string}, - {.name = "rpc", .entry = run_minunit_test_rpc}, - {.name = "subghz", .entry = run_minunit_test_subghz}, - {.name = "infrared", .entry = run_minunit_test_infrared}, - {.name = "nfc", .entry = run_minunit_test_nfc}, - {.name = "power", .entry = run_minunit_test_power}, - {.name = "protocol_dict", .entry = run_minunit_test_protocol_dict}, - {.name = "lfrfid", .entry = run_minunit_test_lfrfid_protocols}, - {.name = "bit_lib", .entry = run_minunit_test_bit_lib}, - {.name = "datetime", .entry = run_minunit_test_datetime}, - {.name = "float_tools", .entry = run_minunit_test_float_tools}, - {.name = "bt", .entry = run_minunit_test_bt}, - {.name = "dialogs_file_browser_options", - .entry = run_minunit_test_dialogs_file_browser_options}, - {.name = "expansion", .entry = run_minunit_test_expansion}, -}; - -void minunit_print_progress(void) { - static const char progress[] = {'\\', '|', '/', '-'}; - static uint8_t progress_counter = 0; - static uint32_t last_tick = 0; - uint32_t current_tick = furi_get_tick(); - if(current_tick - last_tick > 20) { - last_tick = current_tick; - printf("[%c]\033[3D", progress[++progress_counter % COUNT_OF(progress)]); - fflush(stdout); - } -} - -void minunit_print_fail(const char* str) { - printf(_FURI_LOG_CLR_E "%s\r\n" _FURI_LOG_CLR_RESET, str); -} - -void minunit_printf_warning(const char* format, ...) { - FuriString* str = furi_string_alloc(); - va_list args; - va_start(args, format); - furi_string_vprintf(str, format, args); - va_end(args); - printf(_FURI_LOG_CLR_W "%s\r\n" _FURI_LOG_CLR_RESET, furi_string_get_cstr(str)); - furi_string_free(str); -} - -void unit_tests_cli(Cli* cli, FuriString* args, void* context) { - UNUSED(cli); - UNUSED(args); - UNUSED(context); - minunit_run = 0; - minunit_assert = 0; - minunit_fail = 0; - minunit_status = 0; - - Loader* loader = furi_record_open(RECORD_LOADER); - NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION); - - // TODO FL-3491: lock device while test running - if(loader_is_locked(loader)) { - printf("RPC: stop all applications to run tests\r\n"); - notification_message(notification, &sequence_blink_magenta_100); - } else { - notification_message_block(notification, &sequence_set_only_blue_255); - - uint32_t heap_before = memmgr_get_free_heap(); - uint32_t cycle_counter = furi_get_tick(); - - for(size_t i = 0; i < COUNT_OF(unit_tests); i++) { - if(cli_cmd_interrupt_received(cli)) { - break; - } - - if(furi_string_size(args)) { - if(furi_string_cmp_str(args, unit_tests[i].name) == 0) { - unit_tests[i].entry(); - } else { - printf("Skipping %s\r\n", unit_tests[i].name); - } - } else { - unit_tests[i].entry(); - } - } - - if(minunit_run != 0) { - printf("\r\nFailed tests: %u\r\n", minunit_fail); - - // Time report - cycle_counter = (furi_get_tick() - cycle_counter); - printf("Consumed: %lu ms\r\n", cycle_counter); - - // Wait for tested services and apps to deallocate memory - furi_delay_ms(200); - uint32_t heap_after = memmgr_get_free_heap(); - printf("Leaked: %ld\r\n", heap_before - heap_after); - - // Final Report - if(minunit_fail == 0) { - notification_message(notification, &sequence_success); - printf("Status: PASSED\r\n"); - } else { - notification_message(notification, &sequence_error); - printf("Status: FAILED\r\n"); - } - } - } - - furi_record_close(RECORD_NOTIFICATION); - furi_record_close(RECORD_LOADER); -} - -void unit_tests_on_system_start(void) { -#ifdef SRV_CLI - Cli* cli = furi_record_open(RECORD_CLI); - - // We need to launch apps from tests, so we cannot lock loader - cli_add_command(cli, "unit_tests", CliCommandFlagParallelSafe, unit_tests_cli, NULL); - furi_record_close(RECORD_CLI); -#endif -} diff --git a/applications/debug/unit_tests/test_runner.c b/applications/debug/unit_tests/test_runner.c new file mode 100644 index 0000000000..6af807086e --- /dev/null +++ b/applications/debug/unit_tests/test_runner.c @@ -0,0 +1,216 @@ +#include "test_runner.h" + +#include "tests/test_api.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +extern const ElfApiInterface* const unit_tests_api_interface; + +#define TAG "TestRunner" + +#define PLUGINS_PATH "/ext/apps_data/unit_tests/plugins" + +struct TestRunner { + Storage* storage; + Loader* loader; + NotificationApp* notification; + + // Temporary used things + Cli* cli; + FuriString* args; + + // ELF related stuff + CompositeApiResolver* composite_resolver; + + // Report data + int minunit_run; + int minunit_assert; + int minunit_fail; + int minunit_status; +}; + +TestRunner* test_runner_alloc(Cli* cli, FuriString* args) { + TestRunner* instance = malloc(sizeof(TestRunner)); + + instance->storage = furi_record_open(RECORD_STORAGE); + instance->loader = furi_record_open(RECORD_LOADER); + instance->notification = furi_record_open(RECORD_NOTIFICATION); + + instance->cli = cli; + instance->args = args; + + instance->composite_resolver = composite_api_resolver_alloc(); + composite_api_resolver_add(instance->composite_resolver, firmware_api_interface); + composite_api_resolver_add(instance->composite_resolver, unit_tests_api_interface); + + return instance; +} + +void test_runner_free(TestRunner* instance) { + furi_assert(instance); + + composite_api_resolver_free(instance->composite_resolver); + + furi_record_close(RECORD_NOTIFICATION); + instance->notification = NULL; + + furi_record_close(RECORD_LOADER); + instance->loader = NULL; + + furi_record_close(RECORD_STORAGE); + instance->storage = NULL; + + free(instance); +} + +static bool test_runner_run_plugin(TestRunner* instance, const char* path) { + furi_assert(instance); + + FURI_LOG_D(TAG, "Loading %s", path); + FlipperApplication* lib = flipper_application_alloc( + instance->storage, composite_api_resolver_get(instance->composite_resolver)); + + bool result = false; + instance->minunit_fail = -1; + do { + FlipperApplicationPreloadStatus preload_res = flipper_application_preload(lib, path); + + if(preload_res != FlipperApplicationPreloadStatusSuccess) { + FURI_LOG_E(TAG, "Failed to preload %s, %d", path, preload_res); + break; + } + + if(!flipper_application_is_plugin(lib)) { + FURI_LOG_E(TAG, "Not a plugin %s", path); + break; + } + + FlipperApplicationLoadStatus load_status = flipper_application_map_to_memory(lib); + if(load_status != FlipperApplicationLoadStatusSuccess) { + FURI_LOG_E(TAG, "Failed to load %s", path); + break; + } + + const FlipperAppPluginDescriptor* app_descriptor = + flipper_application_plugin_get_descriptor(lib); + + const TestApi* test = app_descriptor->entry_point; + + instance->minunit_fail = test->run(); + + instance->minunit_run += test->get_minunit_run(); + instance->minunit_assert += test->get_minunit_assert(); + instance->minunit_status += test->get_minunit_status(); + + result = (instance->minunit_fail == 0); + } while(false); + + flipper_application_free(lib); + + return result; +} + +static void test_runner_run_internal(TestRunner* instance) { + furi_assert(instance); + + char file_name_buffer[256]; + FuriString* file_name = furi_string_alloc(); + FuriString* file_basename = furi_string_alloc(); + File* directory = storage_file_alloc(instance->storage); + + do { + if(!storage_dir_open(directory, PLUGINS_PATH)) { + FURI_LOG_E(TAG, "Failed to open directory %s", PLUGINS_PATH); + break; + } + + while(true) { + if(cli_cmd_interrupt_received(instance->cli)) { + break; + } + + if(!storage_dir_read(directory, NULL, file_name_buffer, sizeof(file_name_buffer))) { + break; + } + + furi_string_set(file_name, file_name_buffer); + if(!furi_string_end_with_str(file_name, ".fal")) { + continue; + } + + path_concat(PLUGINS_PATH, file_name_buffer, file_name); + + path_extract_filename(file_name, file_basename, true); + const char* file_basename_cstr = furi_string_get_cstr(file_basename); + + bool result = true; + if(furi_string_size(instance->args)) { + if(furi_string_cmp_str(instance->args, file_basename_cstr) == 0) { + result = test_runner_run_plugin(instance, furi_string_get_cstr(file_name)); + } else { + printf("Skipping %s\r\n", file_basename_cstr); + } + } else { + result = test_runner_run_plugin(instance, furi_string_get_cstr(file_name)); + } + + if(!result) { + printf("Failed to execute test: %s\r\n", file_basename_cstr); + break; + } + } + } while(false); + + storage_dir_close(directory); + storage_file_free(directory); + furi_string_free(file_name); + furi_string_free(file_basename); +} + +void test_runner_run(TestRunner* instance) { + furi_assert(instance); + + // TODO FL-3491: lock device while test running + if(loader_is_locked(instance->loader)) { + printf("RPC: stop all applications to run tests\r\n"); + notification_message(instance->notification, &sequence_blink_magenta_100); + } else { + notification_message_block(instance->notification, &sequence_set_only_blue_255); + + uint32_t heap_before = memmgr_get_free_heap(); + uint32_t cycle_counter = furi_get_tick(); + + test_runner_run_internal(instance); + + if(instance->minunit_run != 0) { + printf("\r\nFailed tests: %d\r\n", instance->minunit_fail); + + // Time report + cycle_counter = (furi_get_tick() - cycle_counter); + printf("Consumed: %lu ms\r\n", cycle_counter); + + // Wait for tested services and apps to deallocate memory + furi_delay_ms(200); + uint32_t heap_after = memmgr_get_free_heap(); + printf("Leaked: %ld\r\n", heap_before - heap_after); + + // Final Report + if(instance->minunit_fail == 0) { + notification_message(instance->notification, &sequence_success); + printf("Status: PASSED\r\n"); + } else { + notification_message(instance->notification, &sequence_error); + printf("Status: FAILED\r\n"); + } + } + } +} diff --git a/applications/debug/unit_tests/test_runner.h b/applications/debug/unit_tests/test_runner.h new file mode 100644 index 0000000000..024799ebe5 --- /dev/null +++ b/applications/debug/unit_tests/test_runner.h @@ -0,0 +1,12 @@ +#pragma once + +#include + +typedef struct TestRunner TestRunner; +typedef struct Cli Cli; + +TestRunner* test_runner_alloc(Cli* cli, FuriString* args); + +void test_runner_free(TestRunner* isntance); + +void test_runner_run(TestRunner* isntance); \ No newline at end of file diff --git a/applications/debug/unit_tests/bit_lib/bit_lib_test.c b/applications/debug/unit_tests/tests/bit_lib/bit_lib_test.c similarity index 99% rename from applications/debug/unit_tests/bit_lib/bit_lib_test.c rename to applications/debug/unit_tests/tests/bit_lib/bit_lib_test.c index 239a3b562a..d12aeb2aa1 100644 --- a/applications/debug/unit_tests/bit_lib/bit_lib_test.c +++ b/applications/debug/unit_tests/tests/bit_lib/bit_lib_test.c @@ -1,5 +1,5 @@ #include -#include "../minunit.h" +#include "../test.h" #include MU_TEST(test_bit_lib_increment_index) { @@ -737,4 +737,6 @@ MU_TEST_SUITE(test_bit_lib) { int run_minunit_test_bit_lib(void) { MU_RUN_SUITE(test_bit_lib); return MU_EXIT_CODE; -} \ No newline at end of file +} + +TEST_API_DEFINE(run_minunit_test_bit_lib) diff --git a/applications/debug/unit_tests/bt/bt_test.c b/applications/debug/unit_tests/tests/bt/bt_test.c similarity index 98% rename from applications/debug/unit_tests/bt/bt_test.c rename to applications/debug/unit_tests/tests/bt/bt_test.c index a09b9894ba..e7704381d0 100644 --- a/applications/debug/unit_tests/bt/bt_test.c +++ b/applications/debug/unit_tests/tests/bt/bt_test.c @@ -1,6 +1,6 @@ #include #include -#include "../minunit.h" +#include "../test.h" #include #include @@ -108,3 +108,5 @@ int run_minunit_test_bt(void) { MU_RUN_SUITE(test_bt); return MU_EXIT_CODE; } + +TEST_API_DEFINE(run_minunit_test_bt) diff --git a/applications/debug/unit_tests/tests/common/common.c b/applications/debug/unit_tests/tests/common/common.c new file mode 100644 index 0000000000..aef6aa1a4b --- /dev/null +++ b/applications/debug/unit_tests/tests/common/common.c @@ -0,0 +1,42 @@ +#include "../test.h" +#include "../minunit_vars.h" + +#include + +void minunit_print_progress(void) { + static const char progress[] = {'\\', '|', '/', '-'}; + static uint8_t progress_counter = 0; + static uint32_t last_tick = 0; + uint32_t current_tick = furi_get_tick(); + if(current_tick - last_tick > 20) { + last_tick = current_tick; + printf("[%c]\033[3D", progress[++progress_counter % COUNT_OF(progress)]); + fflush(stdout); + } +} + +void minunit_print_fail(const char* str) { + printf(_FURI_LOG_CLR_E "%s\r\n" _FURI_LOG_CLR_RESET, str); +} + +void minunit_printf_warning(const char* format, ...) { + FuriString* str = furi_string_alloc(); + va_list args; + va_start(args, format); + furi_string_vprintf(str, format, args); + va_end(args); + printf(_FURI_LOG_CLR_W "%s\r\n" _FURI_LOG_CLR_RESET, furi_string_get_cstr(str)); + furi_string_free(str); +} + +int get_minunit_run(void) { + return minunit_run; +} + +int get_minunit_assert(void) { + return minunit_assert; +} + +int get_minunit_status(void) { + return minunit_status; +} diff --git a/applications/debug/unit_tests/tests/compress/compress_test.c b/applications/debug/unit_tests/tests/compress/compress_test.c new file mode 100644 index 0000000000..8f61532971 --- /dev/null +++ b/applications/debug/unit_tests/tests/compress/compress_test.c @@ -0,0 +1,159 @@ +#include "../test.h" + +#include + +#include +#include +#include + +#include + +#include + +#define COMPRESS_UNIT_TESTS_PATH(path) EXT_PATH("unit_tests/compress/" path) + +static void compress_test_reference_comp_decomp() { + Storage* storage = furi_record_open(RECORD_STORAGE); + + File* compressed_file = storage_file_alloc(storage); + File* decompressed_file = storage_file_alloc(storage); + + mu_assert( + storage_file_open( + compressed_file, + COMPRESS_UNIT_TESTS_PATH("compressed.bin"), + FSAM_READ, + FSOM_OPEN_EXISTING), + "Failed to open compressed file"); + mu_assert( + storage_file_open( + decompressed_file, + COMPRESS_UNIT_TESTS_PATH("uncompressed.bin"), + FSAM_READ, + FSOM_OPEN_EXISTING), + "Failed to open decompressed file"); + + uint64_t compressed_ref_size = storage_file_size(compressed_file); + uint64_t decompressed_ref_size = storage_file_size(decompressed_file); + + mu_assert(compressed_ref_size > 0 && decompressed_ref_size > 0, "Invalid file sizes"); + + uint8_t* compressed_ref_buff = malloc(compressed_ref_size); + uint8_t* decompressed_ref_buff = malloc(decompressed_ref_size); + + mu_assert( + storage_file_read(compressed_file, compressed_ref_buff, compressed_ref_size) == + compressed_ref_size, + "Failed to read compressed file"); + + mu_assert( + storage_file_read(decompressed_file, decompressed_ref_buff, decompressed_ref_size) == + decompressed_ref_size, + "Failed to read decompressed file"); + + storage_file_free(compressed_file); + storage_file_free(decompressed_file); + furi_record_close(RECORD_STORAGE); + + uint8_t* temp_buffer = malloc(1024); + Compress* comp = compress_alloc(1024); + + size_t encoded_size = 0; + mu_assert( + compress_encode( + comp, decompressed_ref_buff, decompressed_ref_size, temp_buffer, 1024, &encoded_size), + "Compress failed"); + + mu_assert(encoded_size == compressed_ref_size, "Encoded size is not equal to reference size"); + + mu_assert( + memcmp(temp_buffer, compressed_ref_buff, compressed_ref_size) == 0, + "Encoded buffer is not equal to reference"); + + size_t decoded_size = 0; + mu_assert( + compress_decode( + comp, compressed_ref_buff, compressed_ref_size, temp_buffer, 1024, &decoded_size), + "Decompress failed"); + + mu_assert( + decoded_size == decompressed_ref_size, "Decoded size is not equal to reference size"); + + mu_assert( + memcmp(temp_buffer, decompressed_ref_buff, decompressed_ref_size) == 0, + "Decoded buffer is not equal to reference"); + + compress_free(comp); + + free(temp_buffer); + free(compressed_ref_buff); + free(decompressed_ref_buff); +} + +static void compress_test_random_comp_decomp() { + static const size_t src_buffer_size = 1024; + static const size_t encoded_buffer_size = 1024; + static const size_t small_buffer_size = src_buffer_size / 32; + + // We only fill half of the buffer with random data, so if anything goes wrong, there's no overflow + static const size_t src_data_size = src_buffer_size / 2; + + Compress* comp = compress_alloc(src_buffer_size); + uint8_t* src_buff = malloc(src_buffer_size); + uint8_t* encoded_buff = malloc(encoded_buffer_size); + uint8_t* decoded_buff = malloc(src_buffer_size); + uint8_t* small_buff = malloc(small_buffer_size); + + furi_hal_random_fill_buf(src_buff, src_data_size); + + size_t encoded_size = 0; + + mu_assert( + compress_encode( + comp, src_buff, src_data_size, encoded_buff, encoded_buffer_size, &encoded_size), + "Compress failed"); + + mu_assert(encoded_size > 0, "Encoded size is zero"); + + size_t small_enc_dec_size = 0; + mu_assert( + compress_encode( + comp, src_buff, src_data_size, small_buff, small_buffer_size, &small_enc_dec_size) == + false, + "Compress to small buffer failed"); + + size_t decoded_size = 0; + mu_assert( + compress_decode( + comp, encoded_buff, encoded_size, decoded_buff, src_buffer_size, &decoded_size), + "Decompress failed"); + mu_assert(decoded_size == src_data_size, "Decoded size is not equal to source size"); + + mu_assert( + memcmp(src_buff, decoded_buff, src_data_size) == 0, + "Decoded buffer is not equal to source"); + + mu_assert( + compress_decode( + comp, encoded_buff, encoded_size, small_buff, small_buffer_size, &small_enc_dec_size) == + false, + "Decompress to small buffer failed"); + + free(small_buff); + free(src_buff); + free(encoded_buff); + free(decoded_buff); + compress_free(comp); +} + +MU_TEST_SUITE(test_compress) { + MU_RUN_TEST(compress_test_random_comp_decomp); + MU_RUN_TEST(compress_test_reference_comp_decomp); +} + +int run_minunit_test_compress(void) { + MU_RUN_SUITE(test_compress); + return MU_EXIT_CODE; +} + +TEST_API_DEFINE(run_minunit_test_compress) diff --git a/applications/debug/unit_tests/datetimelib/datetimelib_test.c b/applications/debug/unit_tests/tests/datetime/datetimelib_test.c similarity index 98% rename from applications/debug/unit_tests/datetimelib/datetimelib_test.c rename to applications/debug/unit_tests/tests/datetime/datetimelib_test.c index c171a4413b..7d90f18de1 100644 --- a/applications/debug/unit_tests/datetimelib/datetimelib_test.c +++ b/applications/debug/unit_tests/tests/datetime/datetimelib_test.c @@ -1,5 +1,5 @@ #include -#include "../minunit.h" +#include "../test.h" #include @@ -188,4 +188,6 @@ int run_minunit_test_datetime(void) { MU_RUN_SUITE(test_datetime_validate_datetime); return MU_EXIT_CODE; -} \ No newline at end of file +} + +TEST_API_DEFINE(run_minunit_test_datetime) diff --git a/applications/debug/unit_tests/dialogs/dialogs_file_browser_options.c b/applications/debug/unit_tests/tests/dialogs_file_browser_options/dialogs_file_browser_options.c similarity index 93% rename from applications/debug/unit_tests/dialogs/dialogs_file_browser_options.c rename to applications/debug/unit_tests/tests/dialogs_file_browser_options/dialogs_file_browser_options.c index 657b933dfc..e42e00f9a7 100644 --- a/applications/debug/unit_tests/dialogs/dialogs_file_browser_options.c +++ b/applications/debug/unit_tests/tests/dialogs_file_browser_options/dialogs_file_browser_options.c @@ -1,6 +1,6 @@ #include -#include "../minunit.h" +#include "../test.h" MU_TEST(test_dialog_file_browser_set_basic_options_should_init_all_fields) { mu_assert( @@ -30,3 +30,5 @@ int run_minunit_test_dialogs_file_browser_options(void) { return MU_EXIT_CODE; } + +TEST_API_DEFINE(run_minunit_test_dialogs_file_browser_options) diff --git a/applications/debug/unit_tests/storage/dirwalk_test.c b/applications/debug/unit_tests/tests/dirwalk/dirwalk_test.c similarity index 99% rename from applications/debug/unit_tests/storage/dirwalk_test.c rename to applications/debug/unit_tests/tests/dirwalk/dirwalk_test.c index 415ec7dd43..c2474e7554 100644 --- a/applications/debug/unit_tests/storage/dirwalk_test.c +++ b/applications/debug/unit_tests/tests/dirwalk/dirwalk_test.c @@ -1,4 +1,4 @@ -#include "../minunit.h" +#include "../test.h" #include #include #include @@ -269,4 +269,6 @@ MU_TEST_SUITE(test_dirwalk_suite) { int run_minunit_test_dirwalk(void) { MU_RUN_SUITE(test_dirwalk_suite); return MU_EXIT_CODE; -} \ No newline at end of file +} + +TEST_API_DEFINE(run_minunit_test_dirwalk) diff --git a/applications/debug/unit_tests/expansion/expansion_test.c b/applications/debug/unit_tests/tests/expansion/expansion_test.c similarity index 99% rename from applications/debug/unit_tests/expansion/expansion_test.c rename to applications/debug/unit_tests/tests/expansion/expansion_test.c index c6a143ed34..79d9b0a57c 100644 --- a/applications/debug/unit_tests/expansion/expansion_test.c +++ b/applications/debug/unit_tests/tests/expansion/expansion_test.c @@ -1,4 +1,4 @@ -#include "../minunit.h" +#include "../test.h" #include #include @@ -198,3 +198,5 @@ int run_minunit_test_expansion(void) { MU_RUN_SUITE(test_expansion_suite); return MU_EXIT_CODE; } + +TEST_API_DEFINE(run_minunit_test_expansion) diff --git a/applications/debug/unit_tests/flipper_format/flipper_format_test.c b/applications/debug/unit_tests/tests/flipper_format/flipper_format_test.c similarity index 99% rename from applications/debug/unit_tests/flipper_format/flipper_format_test.c rename to applications/debug/unit_tests/tests/flipper_format/flipper_format_test.c index 471055fb0c..1a2eaf222d 100644 --- a/applications/debug/unit_tests/flipper_format/flipper_format_test.c +++ b/applications/debug/unit_tests/tests/flipper_format/flipper_format_test.c @@ -2,7 +2,7 @@ #include #include #include -#include "../minunit.h" +#include "../test.h" #define TEST_DIR TEST_DIR_NAME "/" #define TEST_DIR_NAME EXT_PATH("unit_tests_tmp") @@ -549,3 +549,5 @@ int run_minunit_test_flipper_format(void) { MU_RUN_SUITE(flipper_format); return MU_EXIT_CODE; } + +TEST_API_DEFINE(run_minunit_test_flipper_format) diff --git a/applications/debug/unit_tests/flipper_format/flipper_format_string_test.c b/applications/debug/unit_tests/tests/flipper_format_string/flipper_format_string_test.c similarity index 99% rename from applications/debug/unit_tests/flipper_format/flipper_format_string_test.c rename to applications/debug/unit_tests/tests/flipper_format_string/flipper_format_string_test.c index 99bb5dda59..821b1ba22a 100644 --- a/applications/debug/unit_tests/flipper_format/flipper_format_string_test.c +++ b/applications/debug/unit_tests/tests/flipper_format_string/flipper_format_string_test.c @@ -3,7 +3,7 @@ #include #include #include -#include "../minunit.h" +#include "../test.h" static const char* test_filetype = "Flipper Format test"; static const uint32_t test_version = 666; @@ -335,3 +335,5 @@ int run_minunit_test_flipper_format_string(void) { MU_RUN_SUITE(flipper_format_string_suite); return MU_EXIT_CODE; } + +TEST_API_DEFINE(run_minunit_test_flipper_format_string) diff --git a/applications/debug/unit_tests/float_tools/float_tools_test.c b/applications/debug/unit_tests/tests/float_tools/float_tools_test.c similarity index 97% rename from applications/debug/unit_tests/float_tools/float_tools_test.c rename to applications/debug/unit_tests/tests/float_tools/float_tools_test.c index 91ac469378..d016ca4a2d 100644 --- a/applications/debug/unit_tests/float_tools/float_tools_test.c +++ b/applications/debug/unit_tests/tests/float_tools/float_tools_test.c @@ -1,7 +1,7 @@ #include #include -#include "../minunit.h" +#include "../test.h" MU_TEST(float_tools_equal_test) { mu_check(float_is_equal(FLT_MAX, FLT_MAX)); @@ -58,3 +58,5 @@ int run_minunit_test_float_tools(void) { MU_RUN_SUITE(float_tools_suite); return MU_EXIT_CODE; } + +TEST_API_DEFINE(run_minunit_test_float_tools) diff --git a/applications/debug/unit_tests/furi/furi_memmgr_test.c b/applications/debug/unit_tests/tests/furi/furi_memmgr_test.c similarity index 97% rename from applications/debug/unit_tests/furi/furi_memmgr_test.c rename to applications/debug/unit_tests/tests/furi/furi_memmgr_test.c index 01e2c17f66..837fd60859 100644 --- a/applications/debug/unit_tests/furi/furi_memmgr_test.c +++ b/applications/debug/unit_tests/tests/furi/furi_memmgr_test.c @@ -1,4 +1,4 @@ -#include "../minunit.h" +#include "../test.h" #include #include #include diff --git a/applications/debug/unit_tests/furi/furi_pubsub_test.c b/applications/debug/unit_tests/tests/furi/furi_pubsub_test.c similarity index 98% rename from applications/debug/unit_tests/furi/furi_pubsub_test.c rename to applications/debug/unit_tests/tests/furi/furi_pubsub_test.c index 8925ff42ec..fdf15e6f58 100644 --- a/applications/debug/unit_tests/furi/furi_pubsub_test.c +++ b/applications/debug/unit_tests/tests/furi/furi_pubsub_test.c @@ -1,7 +1,7 @@ #include #include #include -#include "../minunit.h" +#include "../test.h" const uint32_t context_value = 0xdeadbeef; const uint32_t notify_value_0 = 0x12345678; diff --git a/applications/debug/unit_tests/furi/furi_record_test.c b/applications/debug/unit_tests/tests/furi/furi_record_test.c similarity index 96% rename from applications/debug/unit_tests/furi/furi_record_test.c rename to applications/debug/unit_tests/tests/furi/furi_record_test.c index 10a5a83933..6a2b5a3d26 100644 --- a/applications/debug/unit_tests/furi/furi_record_test.c +++ b/applications/debug/unit_tests/tests/furi/furi_record_test.c @@ -1,7 +1,7 @@ #include #include #include -#include "../minunit.h" +#include "../test.h" #define TEST_RECORD_NAME "test/holding" diff --git a/applications/debug/unit_tests/furi/furi_test.c b/applications/debug/unit_tests/tests/furi/furi_test.c similarity index 94% rename from applications/debug/unit_tests/furi/furi_test.c rename to applications/debug/unit_tests/tests/furi/furi_test.c index e287f9927f..eab9a917d8 100644 --- a/applications/debug/unit_tests/furi/furi_test.c +++ b/applications/debug/unit_tests/tests/furi/furi_test.c @@ -1,7 +1,7 @@ #include #include #include -#include "../minunit.h" +#include "../test.h" // v2 tests void test_furi_create_open(void); @@ -55,3 +55,5 @@ int run_minunit_test_furi(void) { return MU_EXIT_CODE; } + +TEST_API_DEFINE(run_minunit_test_furi) diff --git a/applications/debug/unit_tests/furi_hal/furi_hal_tests.c b/applications/debug/unit_tests/tests/furi_hal/furi_hal_tests.c similarity index 99% rename from applications/debug/unit_tests/furi_hal/furi_hal_tests.c rename to applications/debug/unit_tests/tests/furi_hal/furi_hal_tests.c index 0c5cec8a61..985daa03d7 100644 --- a/applications/debug/unit_tests/furi_hal/furi_hal_tests.c +++ b/applications/debug/unit_tests/tests/furi_hal/furi_hal_tests.c @@ -4,7 +4,7 @@ #include #include #include -#include "../minunit.h" +#include "../test.h" #include #define DATA_SIZE 4 @@ -232,3 +232,5 @@ int run_minunit_test_furi_hal(void) { MU_RUN_SUITE(furi_hal_i2c_ext_suite); return MU_EXIT_CODE; } + +TEST_API_DEFINE(run_minunit_test_furi_hal) diff --git a/applications/debug/unit_tests/furi_hal/furi_hal_crypto_tests.c b/applications/debug/unit_tests/tests/furi_hal_crypto/furi_hal_crypto_tests.c similarity index 99% rename from applications/debug/unit_tests/furi_hal/furi_hal_crypto_tests.c rename to applications/debug/unit_tests/tests/furi_hal_crypto/furi_hal_crypto_tests.c index c2bd6c5f81..0a264a18aa 100644 --- a/applications/debug/unit_tests/furi_hal/furi_hal_crypto_tests.c +++ b/applications/debug/unit_tests/tests/furi_hal_crypto/furi_hal_crypto_tests.c @@ -1,7 +1,7 @@ #include #include #include -#include "../minunit.h" +#include "../test.h" static const uint8_t key_ctr_1[32] = { 0x77, 0x6B, 0xEF, 0xF2, 0x85, 0x1D, 0xB0, 0x6F, 0x4C, 0x8A, 0x05, 0x42, 0xC8, 0x69, 0x6F, 0x6C, @@ -600,3 +600,5 @@ int run_minunit_test_furi_hal_crypto(void) { MU_RUN_SUITE(furi_hal_crypto_gcm_test); return MU_EXIT_CODE; } + +TEST_API_DEFINE(run_minunit_test_furi_hal_crypto) diff --git a/applications/debug/unit_tests/furi/furi_string_test.c b/applications/debug/unit_tests/tests/furi_string/furi_string_test.c similarity index 99% rename from applications/debug/unit_tests/furi/furi_string_test.c rename to applications/debug/unit_tests/tests/furi_string/furi_string_test.c index 853076b67b..949d8c0488 100644 --- a/applications/debug/unit_tests/furi/furi_string_test.c +++ b/applications/debug/unit_tests/tests/furi_string/furi_string_test.c @@ -1,5 +1,5 @@ #include -#include "../minunit.h" +#include "../test.h" static void test_setup(void) { } @@ -466,4 +466,6 @@ int run_minunit_test_furi_string(void) { MU_RUN_SUITE(test_suite); return MU_EXIT_CODE; -} \ No newline at end of file +} + +TEST_API_DEFINE(run_minunit_test_furi_string) diff --git a/applications/debug/unit_tests/infrared/infrared_test.c b/applications/debug/unit_tests/tests/infrared/infrared_test.c similarity index 99% rename from applications/debug/unit_tests/infrared/infrared_test.c rename to applications/debug/unit_tests/tests/infrared/infrared_test.c index 4442fedb30..922577aa86 100644 --- a/applications/debug/unit_tests/infrared/infrared_test.c +++ b/applications/debug/unit_tests/tests/infrared/infrared_test.c @@ -2,7 +2,7 @@ #include #include #include -#include "../minunit.h" +#include "../test.h" #define IR_TEST_FILES_DIR EXT_PATH("unit_tests/infrared/") #define IR_TEST_FILE_PREFIX "test_" @@ -549,3 +549,5 @@ int run_minunit_test_infrared(void) { MU_RUN_SUITE(infrared_test); return MU_EXIT_CODE; } + +TEST_API_DEFINE(run_minunit_test_infrared) diff --git a/applications/debug/unit_tests/lfrfid/lfrfid_protocols.c b/applications/debug/unit_tests/tests/lfrfid/lfrfid_protocols.c similarity index 99% rename from applications/debug/unit_tests/lfrfid/lfrfid_protocols.c rename to applications/debug/unit_tests/tests/lfrfid/lfrfid_protocols.c index 6a7dbab9cb..fc380ecc49 100644 --- a/applications/debug/unit_tests/lfrfid/lfrfid_protocols.c +++ b/applications/debug/unit_tests/tests/lfrfid/lfrfid_protocols.c @@ -1,5 +1,5 @@ #include -#include "../minunit.h" +#include "../test.h" #include #include #include @@ -550,4 +550,6 @@ MU_TEST_SUITE(test_lfrfid_protocols_suite) { int run_minunit_test_lfrfid_protocols(void) { MU_RUN_SUITE(test_lfrfid_protocols_suite); return MU_EXIT_CODE; -} \ No newline at end of file +} + +TEST_API_DEFINE(run_minunit_test_lfrfid_protocols) diff --git a/applications/debug/unit_tests/manifest/manifest.c b/applications/debug/unit_tests/tests/manifest/manifest.c similarity index 97% rename from applications/debug/unit_tests/manifest/manifest.c rename to applications/debug/unit_tests/tests/manifest/manifest.c index e8ac93d7c0..fcbab0ae8a 100644 --- a/applications/debug/unit_tests/manifest/manifest.c +++ b/applications/debug/unit_tests/tests/manifest/manifest.c @@ -1,5 +1,5 @@ #include -#include "../minunit.h" +#include "../test.h" #include #define TAG "Manifest" @@ -72,4 +72,6 @@ MU_TEST_SUITE(manifest_suite) { int run_minunit_test_manifest(void) { MU_RUN_SUITE(manifest_suite); return MU_EXIT_CODE; -} \ No newline at end of file +} + +TEST_API_DEFINE(run_minunit_test_manifest) diff --git a/applications/debug/unit_tests/minunit.h b/applications/debug/unit_tests/tests/minunit.h similarity index 100% rename from applications/debug/unit_tests/minunit.h rename to applications/debug/unit_tests/tests/minunit.h diff --git a/applications/debug/unit_tests/minunit_vars.h b/applications/debug/unit_tests/tests/minunit_vars.h similarity index 100% rename from applications/debug/unit_tests/minunit_vars.h rename to applications/debug/unit_tests/tests/minunit_vars.h diff --git a/applications/debug/unit_tests/minunit_vars_ex.h b/applications/debug/unit_tests/tests/minunit_vars_ex.h similarity index 100% rename from applications/debug/unit_tests/minunit_vars_ex.h rename to applications/debug/unit_tests/tests/minunit_vars_ex.h diff --git a/applications/debug/unit_tests/nfc/nfc_test.c b/applications/debug/unit_tests/tests/nfc/nfc_test.c similarity index 99% rename from applications/debug/unit_tests/nfc/nfc_test.c rename to applications/debug/unit_tests/tests/nfc/nfc_test.c index 8bb88df9ab..4de364a09d 100644 --- a/applications/debug/unit_tests/nfc/nfc_test.c +++ b/applications/debug/unit_tests/tests/nfc/nfc_test.c @@ -24,7 +24,7 @@ #include #include -#include "../minunit.h" +#include "../test.h" #define TAG "NfcTest" @@ -820,3 +820,5 @@ int run_minunit_test_nfc(void) { MU_RUN_SUITE(nfc); return MU_EXIT_CODE; } + +TEST_API_DEFINE(run_minunit_test_nfc) diff --git a/applications/debug/unit_tests/power/power_test.c b/applications/debug/unit_tests/tests/power/power_test.c similarity index 98% rename from applications/debug/unit_tests/power/power_test.c rename to applications/debug/unit_tests/tests/power/power_test.c index 03e0ad269f..d121acba64 100644 --- a/applications/debug/unit_tests/power/power_test.c +++ b/applications/debug/unit_tests/tests/power/power_test.c @@ -1,6 +1,6 @@ #include #include -#include "../minunit.h" +#include "../test.h" static void power_test_deinit(void) { // Try to reset to default charge voltage limit @@ -67,3 +67,5 @@ int run_minunit_test_power(void) { MU_RUN_SUITE(test_power_suite); return MU_EXIT_CODE; } + +TEST_API_DEFINE(run_minunit_test_power) diff --git a/applications/debug/unit_tests/protocol_dict/protocol_dict_test.c b/applications/debug/unit_tests/tests/protocol_dict/protocol_dict_test.c similarity index 98% rename from applications/debug/unit_tests/protocol_dict/protocol_dict_test.c rename to applications/debug/unit_tests/tests/protocol_dict/protocol_dict_test.c index 6ecaa1a52f..9ced106abd 100644 --- a/applications/debug/unit_tests/protocol_dict/protocol_dict_test.c +++ b/applications/debug/unit_tests/tests/protocol_dict/protocol_dict_test.c @@ -1,5 +1,5 @@ #include -#include "../minunit.h" +#include "../test.h" #include typedef enum { @@ -219,4 +219,6 @@ MU_TEST_SUITE(test_protocol_dict_suite) { int run_minunit_test_protocol_dict(void) { MU_RUN_SUITE(test_protocol_dict_suite); return MU_EXIT_CODE; -} \ No newline at end of file +} + +TEST_API_DEFINE(run_minunit_test_protocol_dict) diff --git a/applications/debug/unit_tests/rpc/rpc_test.c b/applications/debug/unit_tests/tests/rpc/rpc_test.c similarity index 99% rename from applications/debug/unit_tests/rpc/rpc_test.c rename to applications/debug/unit_tests/tests/rpc/rpc_test.c index cd692d69de..be7b331f96 100644 --- a/applications/debug/unit_tests/rpc/rpc_test.c +++ b/applications/debug/unit_tests/tests/rpc/rpc_test.c @@ -17,7 +17,7 @@ #include #include -#include "../minunit.h" +#include "../test.h" #include #include @@ -1864,3 +1864,5 @@ int32_t delay_test_app(void* p) { return 0; } + +TEST_API_DEFINE(run_minunit_test_rpc) diff --git a/applications/debug/unit_tests/storage/storage_test.c b/applications/debug/unit_tests/tests/storage/storage_test.c similarity index 99% rename from applications/debug/unit_tests/storage/storage_test.c rename to applications/debug/unit_tests/tests/storage/storage_test.c index e4361f06c3..1d887ced06 100644 --- a/applications/debug/unit_tests/storage/storage_test.c +++ b/applications/debug/unit_tests/tests/storage/storage_test.c @@ -1,4 +1,4 @@ -#include "../minunit.h" +#include "../test.h" #include #include @@ -712,3 +712,5 @@ int run_minunit_test_storage(void) { MU_RUN_SUITE(test_md5_calc_suite); return MU_EXIT_CODE; } + +TEST_API_DEFINE(run_minunit_test_storage) diff --git a/applications/debug/unit_tests/stream/stream_test.c b/applications/debug/unit_tests/tests/stream/stream_test.c similarity index 99% rename from applications/debug/unit_tests/stream/stream_test.c rename to applications/debug/unit_tests/tests/stream/stream_test.c index 3e31773b4f..a9c22c7232 100644 --- a/applications/debug/unit_tests/stream/stream_test.c +++ b/applications/debug/unit_tests/tests/stream/stream_test.c @@ -4,7 +4,7 @@ #include #include #include -#include "../minunit.h" +#include "../test.h" static const char* stream_test_data = "I write differently from what I speak, " "I speak differently from what I think, " @@ -530,3 +530,5 @@ int run_minunit_test_stream(void) { MU_RUN_SUITE(stream_suite); return MU_EXIT_CODE; } + +TEST_API_DEFINE(run_minunit_test_stream) diff --git a/applications/debug/unit_tests/subghz/subghz_test.c b/applications/debug/unit_tests/tests/subghz/subghz_test.c similarity index 99% rename from applications/debug/unit_tests/subghz/subghz_test.c rename to applications/debug/unit_tests/tests/subghz/subghz_test.c index a2f00885b4..030a4223fd 100644 --- a/applications/debug/unit_tests/subghz/subghz_test.c +++ b/applications/debug/unit_tests/tests/subghz/subghz_test.c @@ -1,6 +1,6 @@ #include #include -#include "../minunit.h" +#include "../test.h" #include #include #include @@ -908,3 +908,5 @@ int run_minunit_test_subghz(void) { MU_RUN_SUITE(subghz); return MU_EXIT_CODE; } + +TEST_API_DEFINE(run_minunit_test_subghz) diff --git a/applications/debug/unit_tests/tests/test.h b/applications/debug/unit_tests/tests/test.h new file mode 100644 index 0000000000..bd7acc00e7 --- /dev/null +++ b/applications/debug/unit_tests/tests/test.h @@ -0,0 +1,12 @@ +#pragma once + +// Framework +#include "minunit.h" + +#include "test_api.h" + +int get_minunit_run(void); + +int get_minunit_assert(void); + +int get_minunit_status(void); diff --git a/applications/debug/unit_tests/tests/test_api.h b/applications/debug/unit_tests/tests/test_api.h new file mode 100644 index 0000000000..55b9f7885b --- /dev/null +++ b/applications/debug/unit_tests/tests/test_api.h @@ -0,0 +1,29 @@ +#pragma once + +#include + +#define APPID "UnitTest" +#define API_VERSION (0u) + +typedef struct { + int (*run)(void); + int (*get_minunit_run)(void); + int (*get_minunit_assert)(void); + int (*get_minunit_status)(void); +} TestApi; + +#define TEST_API_DEFINE(entrypoint) \ + const TestApi test_api = { \ + .run = entrypoint, \ + .get_minunit_run = get_minunit_run, \ + .get_minunit_assert = get_minunit_assert, \ + .get_minunit_status = get_minunit_status, \ + }; \ + const FlipperAppPluginDescriptor app_descriptor = { \ + .appid = APPID, \ + .ep_api_version = API_VERSION, \ + .entry_point = &test_api, \ + }; \ + const FlipperAppPluginDescriptor* get_api(void) { \ + return &app_descriptor; \ + } diff --git a/applications/debug/unit_tests/varint/varint_test.c b/applications/debug/unit_tests/tests/varint/varint_test.c similarity index 97% rename from applications/debug/unit_tests/varint/varint_test.c rename to applications/debug/unit_tests/tests/varint/varint_test.c index ac444013d3..3fdf5115ab 100644 --- a/applications/debug/unit_tests/varint/varint_test.c +++ b/applications/debug/unit_tests/tests/varint/varint_test.c @@ -1,6 +1,8 @@ #include #include -#include "../minunit.h" + +#include "../test.h" + #include #include @@ -85,4 +87,6 @@ MU_TEST_SUITE(test_varint_suite) { int run_minunit_test_varint(void) { MU_RUN_SUITE(test_varint_suite); return MU_EXIT_CODE; -} \ No newline at end of file +} + +TEST_API_DEFINE(run_minunit_test_varint) diff --git a/applications/debug/unit_tests/unit_test_api_table.cpp b/applications/debug/unit_tests/unit_test_api_table.cpp new file mode 100644 index 0000000000..8205d43722 --- /dev/null +++ b/applications/debug/unit_tests/unit_test_api_table.cpp @@ -0,0 +1,19 @@ +#include +#include + +#include "unit_test_api_table_i.h" + +static_assert(!has_hash_collisions(unit_tests_api_table), "Detected API method hash collision!"); + +constexpr HashtableApiInterface unit_tests_hashtable_api_interface{ + { + .api_version_major = 0, + .api_version_minor = 0, + .resolver_callback = &elf_resolve_from_hashtable, + }, + unit_tests_api_table.cbegin(), + unit_tests_api_table.cend(), +}; + +extern "C" const ElfApiInterface* const unit_tests_api_interface = + &unit_tests_hashtable_api_interface; diff --git a/applications/debug/unit_tests/unit_test_api_table_i.h b/applications/debug/unit_tests/unit_test_api_table_i.h new file mode 100644 index 0000000000..8c2fa4687f --- /dev/null +++ b/applications/debug/unit_tests/unit_test_api_table_i.h @@ -0,0 +1,29 @@ +#include +#include +#include +#include +#include + +#include +#include + +static constexpr auto unit_tests_api_table = sort(create_array_t( + API_METHOD(resource_manifest_reader_alloc, ResourceManifestReader*, (Storage*)), + API_METHOD(resource_manifest_reader_free, void, (ResourceManifestReader*)), + API_METHOD(resource_manifest_reader_open, bool, (ResourceManifestReader*, const char* filename)), + API_METHOD(resource_manifest_reader_next, ResourceManifestEntry*, (ResourceManifestReader*)), + API_METHOD(resource_manifest_reader_previous, ResourceManifestEntry*, (ResourceManifestReader*)), + API_METHOD(slix_process_iso15693_3_error, SlixError, (Iso15693_3Error)), + API_METHOD(iso15693_3_poller_get_data, const Iso15693_3Data*, (Iso15693_3Poller*)), + API_METHOD(rpc_system_storage_get_error, PB_CommandStatus, (FS_Error)), + API_METHOD(xQueueSemaphoreTake, BaseType_t, (QueueHandle_t, TickType_t)), + API_METHOD(vQueueDelete, void, (QueueHandle_t)), + API_METHOD( + xQueueGenericCreate, + QueueHandle_t, + (const UBaseType_t, const UBaseType_t, const uint8_t)), + API_METHOD( + xQueueGenericSend, + BaseType_t, + (QueueHandle_t, const void* const, TickType_t, const BaseType_t)), + API_VARIABLE(PB_Main_msg, PB_Main_msg_t))); diff --git a/applications/debug/unit_tests/unit_tests.c b/applications/debug/unit_tests/unit_tests.c new file mode 100644 index 0000000000..237cb9080e --- /dev/null +++ b/applications/debug/unit_tests/unit_tests.c @@ -0,0 +1,21 @@ +#include +#include + +#include "test_runner.h" + +void unit_tests_cli(Cli* cli, FuriString* args, void* context) { + UNUSED(cli); + UNUSED(context); + + TestRunner* test_runner = test_runner_alloc(cli, args); + test_runner_run(test_runner); + test_runner_free(test_runner); +} + +void unit_tests_on_system_start(void) { +#ifdef SRV_CLI + Cli* cli = furi_record_open(RECORD_CLI); + cli_add_command(cli, "unit_tests", CliCommandFlagParallelSafe, unit_tests_cli, NULL); + furi_record_close(RECORD_CLI); +#endif +} diff --git a/applications/services/bt/application.fam b/applications/services/bt/application.fam index 2e97dc1d65..2d2840e3a5 100644 --- a/applications/services/bt/application.fam +++ b/applications/services/bt/application.fam @@ -14,7 +14,7 @@ App( ], stack_size=1 * 1024, order=20, - sdk_headers=["bt_service/bt.h"], + sdk_headers=["bt_service/bt.h", "bt_service/bt_keys_storage.h"], ) App( diff --git a/applications/services/bt/bt_service/bt_keys_storage.h b/applications/services/bt/bt_service/bt_keys_storage.h index cb808ca304..587dd570dd 100644 --- a/applications/services/bt/bt_service/bt_keys_storage.h +++ b/applications/services/bt/bt_service/bt_keys_storage.h @@ -3,6 +3,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + typedef struct BtKeysStorage BtKeysStorage; BtKeysStorage* bt_keys_storage_alloc(const char* keys_storage_path); @@ -18,3 +22,7 @@ bool bt_keys_storage_load(BtKeysStorage* instance); bool bt_keys_storage_update(BtKeysStorage* instance, uint8_t* start_addr, uint32_t size); bool bt_keys_storage_delete(BtKeysStorage* instance); + +#ifdef __cplusplus +} +#endif diff --git a/applications/services/desktop/helpers/slideshow.c b/applications/services/desktop/helpers/slideshow.c index efd02c4bc8..ec02f27a1d 100644 --- a/applications/services/desktop/helpers/slideshow.c +++ b/applications/services/desktop/helpers/slideshow.c @@ -1,6 +1,5 @@ #include "slideshow.h" -#include #include #include #include diff --git a/applications/services/gui/canvas.c b/applications/services/gui/canvas.c index c293165879..de09305aab 100644 --- a/applications/services/gui/canvas.c +++ b/applications/services/gui/canvas.c @@ -15,7 +15,7 @@ const CanvasFontParameters canvas_font_params[FontTotalNumber] = { Canvas* canvas_init(void) { Canvas* canvas = malloc(sizeof(Canvas)); - canvas->compress_icon = compress_icon_alloc(); + canvas->compress_icon = compress_icon_alloc(ICON_DECOMPRESSOR_BUFFER_SIZE); // Initialize mutex canvas->mutex = furi_mutex_alloc(FuriMutexTypeNormal); @@ -390,7 +390,7 @@ void canvas_draw_icon_ex( x += canvas->offset_x; y += canvas->offset_y; uint8_t* icon_data = NULL; - compress_icon_decode(canvas->compress_icon, icon_get_data(icon), &icon_data); + compress_icon_decode(canvas->compress_icon, icon_get_frame_data(icon, 0), &icon_data); canvas_draw_u8g2_bitmap( &canvas->fb, x, y, icon_get_width(icon), icon_get_height(icon), icon_data, rotation); } @@ -402,7 +402,7 @@ void canvas_draw_icon(Canvas* canvas, int32_t x, int32_t y, const Icon* icon) { x += canvas->offset_x; y += canvas->offset_y; uint8_t* icon_data = NULL; - compress_icon_decode(canvas->compress_icon, icon_get_data(icon), &icon_data); + compress_icon_decode(canvas->compress_icon, icon_get_frame_data(icon, 0), &icon_data); canvas_draw_u8g2_bitmap( &canvas->fb, x, y, icon_get_width(icon), icon_get_height(icon), icon_data, IconRotation0); } diff --git a/applications/services/gui/canvas_i.h b/applications/services/gui/canvas_i.h index c204b970fb..449db71dbc 100644 --- a/applications/services/gui/canvas_i.h +++ b/applications/services/gui/canvas_i.h @@ -12,6 +12,8 @@ #include #include +#define ICON_DECOMPRESSOR_BUFFER_SIZE (128u * 64 / 8) + #ifdef __cplusplus extern "C" { #endif diff --git a/applications/services/gui/icon.c b/applications/services/gui/icon.c index e216b92551..6e015ed75a 100644 --- a/applications/services/gui/icon.c +++ b/applications/services/gui/icon.c @@ -1,13 +1,16 @@ +#include "icon.h" #include "icon_i.h" #include -uint8_t icon_get_width(const Icon* instance) { +#include + +uint16_t icon_get_width(const Icon* instance) { furi_check(instance); return instance->width; } -uint8_t icon_get_height(const Icon* instance) { +uint16_t icon_get_height(const Icon* instance) { furi_check(instance); return instance->height; @@ -16,5 +19,14 @@ uint8_t icon_get_height(const Icon* instance) { const uint8_t* icon_get_data(const Icon* instance) { furi_check(instance); - return instance->frames[0]; + return icon_get_frame_data(instance, 0); +} + +uint32_t icon_get_frame_count(const Icon* instance) { + return instance->frame_count; +} + +const uint8_t* icon_get_frame_data(const Icon* instance, uint32_t frame) { + furi_check(frame < instance->frame_count); + return instance->frames[frame]; } diff --git a/applications/services/gui/icon.h b/applications/services/gui/icon.h index e33c4d34d2..fc19c0a7df 100644 --- a/applications/services/gui/icon.h +++ b/applications/services/gui/icon.h @@ -6,6 +6,7 @@ #pragma once #include +#include #ifdef __cplusplus extern "C" { @@ -19,7 +20,7 @@ typedef struct Icon Icon; * * @return width in pixels */ -uint8_t icon_get_width(const Icon* instance); +uint16_t icon_get_width(const Icon* instance); /** Get icon height * @@ -27,15 +28,32 @@ uint8_t icon_get_width(const Icon* instance); * * @return height in pixels */ -uint8_t icon_get_height(const Icon* instance); +uint16_t icon_get_height(const Icon* instance); -/** Get Icon XBM bitmap data +/** Get Icon XBM bitmap data for the first frame * * @param[in] instance pointer to Icon data * - * @return pointer to XBM bitmap data + * @return pointer to compressed XBM bitmap data */ -const uint8_t* icon_get_data(const Icon* instance); +FURI_DEPRECATED const uint8_t* icon_get_data(const Icon* instance); + +/** Get Icon frame count + * + * @param[in] instance pointer to Icon data + * + * @return frame count + */ +uint32_t icon_get_frame_count(const Icon* instance); + +/** Get Icon XBM bitmap data for a particular frame + * + * @param[in] instance pointer to Icon data + * @param[in] frame frame index + * + * @return pointer to compressed XBM bitmap data + */ +const uint8_t* icon_get_frame_data(const Icon* instance, uint32_t frame); #ifdef __cplusplus } diff --git a/applications/services/gui/icon_i.h b/applications/services/gui/icon_i.h index 58cac8b412..e33cdbf236 100644 --- a/applications/services/gui/icon_i.h +++ b/applications/services/gui/icon_i.h @@ -4,11 +4,11 @@ */ #pragma once -#include "icon.h" +#include struct Icon { - const uint8_t width; - const uint8_t height; + const uint16_t width; + const uint16_t height; const uint8_t frame_count; const uint8_t frame_rate; const uint8_t* const* frames; diff --git a/applications/services/loader/firmware_api/firmware_api.cpp b/applications/services/loader/firmware_api/firmware_api.cpp index 833f99abe4..45953eddf4 100644 --- a/applications/services/loader/firmware_api/firmware_api.cpp +++ b/applications/services/loader/firmware_api/firmware_api.cpp @@ -10,19 +10,6 @@ static_assert(!has_hash_collisions(elf_api_table), "Detected API method hash collision!"); -#ifdef APP_UNIT_TESTS -constexpr HashtableApiInterface mock_elf_api_interface{ - { - .api_version_major = 0, - .api_version_minor = 0, - .resolver_callback = &elf_resolve_from_hashtable, - }, - nullptr, - nullptr, -}; - -const ElfApiInterface* const firmware_api_interface = &mock_elf_api_interface; -#else constexpr HashtableApiInterface elf_api_interface{ { .api_version_major = (elf_api_version >> 16), @@ -33,7 +20,6 @@ constexpr HashtableApiInterface elf_api_interface{ elf_api_table.cend(), }; const ElfApiInterface* const firmware_api_interface = &elf_api_interface; -#endif extern "C" void furi_hal_info_get_api_version(uint16_t* major, uint16_t* minor) { *major = firmware_api_interface->api_version_major; diff --git a/applications/services/loader/loader.c b/applications/services/loader/loader.c index cedc2e83ed..c02eefd044 100644 --- a/applications/services/loader/loader.c +++ b/applications/services/loader/loader.c @@ -353,6 +353,12 @@ static LoaderStatus loader_start_external_app( FURI_LOG_I(TAG, "Loaded in %zums", (size_t)(furi_get_tick() - start)); + if(flipper_application_is_plugin(loader->app.fap)) { + status = loader_make_status_error( + LoaderStatusErrorInternal, error_message, "Plugin %s is not runnable", path); + break; + } + loader->app.thread = flipper_application_alloc_thread(loader->app.fap, args); FuriString* app_name = furi_string_alloc(); path_extract_filename_no_ext(path, app_name); diff --git a/applications/services/loader/loader_applications.c b/applications/services/loader/loader_applications.c index d52aec097d..0c5d93cc8e 100644 --- a/applications/services/loader/loader_applications.c +++ b/applications/services/loader/loader_applications.c @@ -92,7 +92,7 @@ static bool loader_applications_item_callback( path, loader_applications_app->storage, icon_ptr, item_name); } else { path_extract_filename(path, item_name, false); - memcpy(*icon_ptr, icon_get_data(&I_js_script_10px), FAP_MANIFEST_MAX_ICON_SIZE); + memcpy(*icon_ptr, icon_get_frame_data(&I_js_script_10px, 0), FAP_MANIFEST_MAX_ICON_SIZE); return true; } } diff --git a/applications/services/rpc/rpc_i.h b/applications/services/rpc/rpc_i.h index ffca50231c..20baca7b12 100644 --- a/applications/services/rpc/rpc_i.h +++ b/applications/services/rpc/rpc_i.h @@ -7,6 +7,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + typedef void* (*RpcSystemAlloc)(RpcSession* session); typedef void (*RpcSystemFree)(void* context); typedef void (*PBMessageHandler)(const PB_Main* msg_request, void* context); @@ -45,3 +49,7 @@ void rpc_debug_print_data(const char* prefix, uint8_t* buffer, size_t size); void rpc_cli_command_start_session(Cli* cli, FuriString* args, void* context); PB_CommandStatus rpc_system_storage_get_error(FS_Error fs_error); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/lib/nfc/SConscript b/lib/nfc/SConscript index f047101e6c..c6caffdb08 100644 --- a/lib/nfc/SConscript +++ b/lib/nfc/SConscript @@ -33,6 +33,7 @@ env.Append( File("protocols/mf_ultralight/mf_ultralight_poller.h"), File("protocols/mf_classic/mf_classic_poller.h"), File("protocols/mf_desfire/mf_desfire_poller.h"), + File("protocols/slix/slix_poller.h"), File("protocols/st25tb/st25tb_poller.h"), File("protocols/felica/felica_poller.h"), # Listeners diff --git a/lib/nfc/nfc.c b/lib/nfc/nfc.c index 59d254592c..d0d342a6bc 100644 --- a/lib/nfc/nfc.c +++ b/lib/nfc/nfc.c @@ -660,4 +660,4 @@ NfcError nfc_felica_listener_set_sensf_res_data( return nfc_process_hal_error(error); } -#endif // APP_UNIT_TESTS +#endif // FW_CFG_unit_tests diff --git a/applications/debug/unit_tests/nfc/nfc_transport.c b/lib/nfc/nfc_mock.c similarity index 100% rename from applications/debug/unit_tests/nfc/nfc_transport.c rename to lib/nfc/nfc_mock.c diff --git a/lib/subghz/SConscript b/lib/subghz/SConscript index d0bc2a2543..933cd8f999 100644 --- a/lib/subghz/SConscript +++ b/lib/subghz/SConscript @@ -25,6 +25,7 @@ env.Append( File("subghz_protocol_registry.h"), File("devices/cc1101_configs.h"), File("devices/cc1101_int/cc1101_int_interconnect.h"), + File("subghz_file_encoder_worker.h"), ], ) diff --git a/lib/subghz/subghz_file_encoder_worker.h b/lib/subghz/subghz_file_encoder_worker.h index ae2f4a2a09..a6a24dc74f 100644 --- a/lib/subghz/subghz_file_encoder_worker.h +++ b/lib/subghz/subghz_file_encoder_worker.h @@ -2,6 +2,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + typedef void (*SubGhzFileEncoderWorkerCallbackEnd)(void* context); typedef struct SubGhzFileEncoderWorker SubGhzFileEncoderWorker; @@ -59,3 +63,7 @@ void subghz_file_encoder_worker_stop(SubGhzFileEncoderWorker* instance); * @return bool - true if running */ bool subghz_file_encoder_worker_is_running(SubGhzFileEncoderWorker* instance); + +#ifdef __cplusplus +} +#endif diff --git a/lib/toolbox/SConscript b/lib/toolbox/SConscript index 121362424e..11e01a8c9d 100644 --- a/lib/toolbox/SConscript +++ b/lib/toolbox/SConscript @@ -35,6 +35,9 @@ env.Append( File("simple_array.h"), File("bit_buffer.h"), File("keys_dict.h"), + File("pulse_protocols/pulse_glue.h"), + File("md5_calc.h"), + File("varint.h"), ], ) diff --git a/lib/toolbox/compress.c b/lib/toolbox/compress.c index 70db479680..780bea27ab 100644 --- a/lib/toolbox/compress.c +++ b/lib/toolbox/compress.c @@ -3,6 +3,9 @@ #include #include #include +#include + +#define TAG "Compress" /** Defines encoder and decoder window size */ #define COMPRESS_EXP_BUFF_SIZE_LOG (8u) @@ -10,9 +13,16 @@ /** Defines encoder and decoder lookahead buffer size */ #define COMPRESS_LOOKAHEAD_BUFF_SIZE_LOG (4u) -/** Buffer sizes for input and output data */ -#define COMPRESS_ICON_ENCODED_BUFF_SIZE (1024u) -#define COMPRESS_ICON_DECODED_BUFF_SIZE (1024u) +/** Buffer size for input data */ +#define COMPRESS_ICON_ENCODED_BUFF_SIZE (256u) + +static bool compress_decode_internal( + heatshrink_decoder* decoder, + const uint8_t* data_in, + size_t data_in_size, + uint8_t* data_out, + size_t data_out_size, + size_t* data_res_size); typedef struct { uint8_t is_compressed; @@ -24,55 +34,51 @@ _Static_assert(sizeof(CompressHeader) == 4, "Incorrect CompressHeader size"); struct CompressIcon { heatshrink_decoder* decoder; - uint8_t decoded_buff[COMPRESS_ICON_DECODED_BUFF_SIZE]; + uint8_t* buffer; + size_t buffer_size; }; -CompressIcon* compress_icon_alloc(void) { +CompressIcon* compress_icon_alloc(size_t decode_buf_size) { CompressIcon* instance = malloc(sizeof(CompressIcon)); instance->decoder = heatshrink_decoder_alloc( COMPRESS_ICON_ENCODED_BUFF_SIZE, COMPRESS_EXP_BUFF_SIZE_LOG, COMPRESS_LOOKAHEAD_BUFF_SIZE_LOG); heatshrink_decoder_reset(instance->decoder); - memset(instance->decoded_buff, 0, sizeof(instance->decoded_buff)); + + instance->buffer_size = decode_buf_size + 4; /* To account for heatshrink's poller quirks */ + instance->buffer = malloc(instance->buffer_size); return instance; } void compress_icon_free(CompressIcon* instance) { furi_check(instance); + free(instance->buffer); heatshrink_decoder_free(instance->decoder); free(instance); } -void compress_icon_decode(CompressIcon* instance, const uint8_t* icon_data, uint8_t** decoded_buff) { +void compress_icon_decode(CompressIcon* instance, const uint8_t* icon_data, uint8_t** output) { furi_check(instance); furi_check(icon_data); - furi_check(decoded_buff); + furi_check(output); CompressHeader* header = (CompressHeader*)icon_data; if(header->is_compressed) { - size_t data_processed = 0; - heatshrink_decoder_sink( + size_t decoded_size = 0; + /* If decompression fails - check that decode_buf_size is large enough */ + furi_check(compress_decode_internal( instance->decoder, - (uint8_t*)&icon_data[sizeof(CompressHeader)], - header->compressed_buff_size, - &data_processed); - while(1) { - HSD_poll_res res = heatshrink_decoder_poll( - instance->decoder, - instance->decoded_buff, - sizeof(instance->decoded_buff), - &data_processed); - furi_check((res == HSDR_POLL_EMPTY) || (res == HSDR_POLL_MORE)); - if(res != HSDR_POLL_MORE) { - break; - } - } - heatshrink_decoder_reset(instance->decoder); - *decoded_buff = instance->decoded_buff; + icon_data, + /* Decoder will check/process headers again - need to pass them */ + sizeof(CompressHeader) + header->compressed_buff_size, + instance->buffer, + instance->buffer_size, + &decoded_size)); + *output = instance->buffer; } else { - *decoded_buff = (uint8_t*)&icon_data[1]; + *output = (uint8_t*)&icon_data[1]; } } @@ -81,12 +87,6 @@ struct Compress { heatshrink_decoder* decoder; }; -static void compress_reset(Compress* compress) { - furi_assert(compress); - heatshrink_encoder_reset(compress->encoder); - heatshrink_decoder_reset(compress->decoder); -} - Compress* compress_alloc(uint16_t compress_buff_size) { Compress* compress = malloc(sizeof(Compress)); compress->encoder = @@ -105,16 +105,16 @@ void compress_free(Compress* compress) { free(compress); } -bool compress_encode( - Compress* compress, +static bool compress_encode_internal( + heatshrink_encoder* encoder, uint8_t* data_in, size_t data_in_size, uint8_t* data_out, size_t data_out_size, size_t* data_res_size) { - furi_assert(compress); - furi_assert(data_in); - furi_assert(data_in_size); + furi_check(encoder); + furi_check(data_in); + furi_check(data_in_size); size_t sink_size = 0; size_t poll_size = 0; @@ -125,10 +125,10 @@ bool compress_encode( size_t sunk = 0; size_t res_buff_size = sizeof(CompressHeader); - // Sink data to encoding buffer + /* Sink data to encoding buffer */ while((sunk < data_in_size) && !encode_failed) { - sink_res = heatshrink_encoder_sink( - compress->encoder, &data_in[sunk], data_in_size - sunk, &sink_size); + sink_res = + heatshrink_encoder_sink(encoder, &data_in[sunk], data_in_size - sunk, &sink_size); if(sink_res != HSER_SINK_OK) { encode_failed = true; break; @@ -136,10 +136,7 @@ bool compress_encode( sunk += sink_size; do { poll_res = heatshrink_encoder_poll( - compress->encoder, - &data_out[res_buff_size], - data_out_size - res_buff_size, - &poll_size); + encoder, &data_out[res_buff_size], data_out_size - res_buff_size, &poll_size); if(poll_res < 0) { encode_failed = true; break; @@ -148,31 +145,30 @@ bool compress_encode( } while(poll_res == HSER_POLL_MORE); } - // Notify sinking complete and poll encoded data - finish_res = heatshrink_encoder_finish(compress->encoder); + /* Notify sinking complete and poll encoded data */ + finish_res = heatshrink_encoder_finish(encoder); if(finish_res < 0) { encode_failed = true; } else { do { poll_res = heatshrink_encoder_poll( - compress->encoder, - &data_out[res_buff_size], - data_out_size - 4 - res_buff_size, - &poll_size); + encoder, &data_out[res_buff_size], data_out_size - res_buff_size, &poll_size); if(poll_res < 0) { encode_failed = true; break; } res_buff_size += poll_size; - finish_res = heatshrink_encoder_finish(compress->encoder); + finish_res = heatshrink_encoder_finish(encoder); } while(finish_res != HSER_FINISH_DONE); } bool result = true; - // Write encoded data to output buffer if compression is efficient. Else - write header and original data + /* Write encoded data to output buffer if compression is efficient. Otherwise, write header and original data */ if(!encode_failed && (res_buff_size < data_in_size + 1)) { CompressHeader header = { - .is_compressed = 0x01, .reserved = 0x00, .compressed_buff_size = res_buff_size}; + .is_compressed = 0x01, + .reserved = 0x00, + .compressed_buff_size = res_buff_size - sizeof(CompressHeader)}; memcpy(data_out, &header, sizeof(header)); *data_res_size = res_buff_size; } else if(data_out_size > data_in_size) { @@ -183,22 +179,21 @@ bool compress_encode( *data_res_size = 0; result = false; } - compress_reset(compress); - + heatshrink_encoder_reset(encoder); return result; } -bool compress_decode( - Compress* compress, - uint8_t* data_in, +static bool compress_decode_internal( + heatshrink_decoder* decoder, + const uint8_t* data_in, size_t data_in_size, uint8_t* data_out, size_t data_out_size, size_t* data_res_size) { - furi_assert(compress); - furi_assert(data_in); - furi_assert(data_out); - furi_assert(data_res_size); + furi_check(decoder); + furi_check(data_in); + furi_check(data_out); + furi_check(data_res_size); bool result = false; bool decode_failed = false; @@ -211,12 +206,15 @@ bool compress_decode( CompressHeader* header = (CompressHeader*)data_in; if(header->is_compressed) { - // Sink data to decoding buffer + /* Sink data to decoding buffer */ size_t compressed_size = header->compressed_buff_size; - size_t sunk = sizeof(CompressHeader); + size_t sunk = 0; while(sunk < compressed_size && !decode_failed) { sink_res = heatshrink_decoder_sink( - compress->decoder, &data_in[sunk], compressed_size - sunk, &sink_size); + decoder, + (uint8_t*)&data_in[sizeof(CompressHeader) + sunk], + compressed_size - sunk, + &sink_size); if(sink_res < 0) { decode_failed = true; break; @@ -224,25 +222,28 @@ bool compress_decode( sunk += sink_size; do { poll_res = heatshrink_decoder_poll( - compress->decoder, &data_out[res_buff_size], data_out_size, &poll_size); - if(poll_res < 0) { + decoder, &data_out[res_buff_size], data_out_size - res_buff_size, &poll_size); + if((poll_res < 0) || ((data_out_size - res_buff_size) == 0)) { decode_failed = true; break; } res_buff_size += poll_size; } while(poll_res == HSDR_POLL_MORE); } - // Notify sinking complete and poll decoded data + /* Notify sinking complete and poll decoded data */ if(!decode_failed) { - finish_res = heatshrink_decoder_finish(compress->decoder); + finish_res = heatshrink_decoder_finish(decoder); if(finish_res < 0) { decode_failed = true; } else { do { poll_res = heatshrink_decoder_poll( - compress->decoder, &data_out[res_buff_size], data_out_size, &poll_size); + decoder, + &data_out[res_buff_size], + data_out_size - res_buff_size, + &poll_size); res_buff_size += poll_size; - finish_res = heatshrink_decoder_finish(compress->decoder); + finish_res = heatshrink_decoder_finish(decoder); } while(finish_res != HSDR_FINISH_DONE); } } @@ -253,9 +254,31 @@ bool compress_decode( *data_res_size = data_in_size - 1; result = true; } else { + /* Not enough space in output buffer */ result = false; } - compress_reset(compress); - + heatshrink_decoder_reset(decoder); return result; } + +bool compress_encode( + Compress* compress, + uint8_t* data_in, + size_t data_in_size, + uint8_t* data_out, + size_t data_out_size, + size_t* data_res_size) { + return compress_encode_internal( + compress->encoder, data_in, data_in_size, data_out, data_out_size, data_res_size); +} + +bool compress_decode( + Compress* compress, + uint8_t* data_in, + size_t data_in_size, + uint8_t* data_out, + size_t data_out_size, + size_t* data_res_size) { + return compress_decode_internal( + compress->decoder, data_in, data_in_size, data_out, data_out_size, data_res_size); +} diff --git a/lib/toolbox/compress.h b/lib/toolbox/compress.h index f844802ec5..f08e175840 100644 --- a/lib/toolbox/compress.h +++ b/lib/toolbox/compress.h @@ -16,10 +16,14 @@ extern "C" { typedef struct CompressIcon CompressIcon; /** Initialize icon compressor + * + * @param[in] decode_buf_size The icon buffer size for decoding. Ensure that + * it's big enough for any icons that you are + * planning to decode with it. * * @return Compress Icon instance */ -CompressIcon* compress_icon_alloc(void); +CompressIcon* compress_icon_alloc(size_t decode_buf_size); /** Free icon compressor * @@ -29,14 +33,16 @@ void compress_icon_free(CompressIcon* instance); /** Decompress icon * - * @warning decoded_buff pointer set by this function is valid till next + * @warning output pointer set by this function is valid till next * `compress_icon_decode` or `compress_icon_free` call * - * @param instance The Compress Icon instance - * @param icon_data pointer to icon data - * @param[in] decoded_buff pointer to decoded buffer pointer + * @param instance The Compress Icon instance + * @param icon_data pointer to icon data. + * @param[in] output pointer to decoded buffer pointer. Data in buffer is + * valid till next call. If icon data was not compressed, + * pointer within icon_data is returned */ -void compress_icon_decode(CompressIcon* instance, const uint8_t* icon_data, uint8_t** decoded_buff); +void compress_icon_decode(CompressIcon* instance, const uint8_t* icon_data, uint8_t** output); /** Compress control structure */ typedef struct Compress Compress; diff --git a/scripts/assets.py b/scripts/assets.py index 711c1b440b..c3d6081c88 100755 --- a/scripts/assets.py +++ b/scripts/assets.py @@ -24,8 +24,8 @@ ICONS_TEMPLATE_C_FRAME = "const uint8_t {name}[] = {data};\n" ICONS_TEMPLATE_C_DATA = "const uint8_t* const {name}[] = {data};\n" ICONS_TEMPLATE_C_ICONS = "const Icon {name} = {{.width={width},.height={height},.frame_count={frame_count},.frame_rate={frame_rate},.frames=_{name}}};\n" -MAX_IMAGE_WIDTH = 128 -MAX_IMAGE_HEIGHT = 64 +MAX_IMAGE_WIDTH = 2**16 - 1 +MAX_IMAGE_HEIGHT = 2**16 - 1 class Main(App): diff --git a/scripts/fbt/appmanifest.py b/scripts/fbt/appmanifest.py index d32869b106..b5b5d6e121 100644 --- a/scripts/fbt/appmanifest.py +++ b/scripts/fbt/appmanifest.py @@ -351,10 +351,10 @@ class AppBuildset: ).append(app) def get_ext_apps(self): - return self.extapps + return list(self.extapps) def get_incompatible_ext_apps(self): - return self.incompatible_extapps + return list(self.incompatible_extapps) def _check_conflicts(self): conflicts = [] @@ -399,14 +399,30 @@ class AppBuildset: def _group_plugins(self): known_extensions = self.get_apps_of_type(FlipperAppType.PLUGIN, all_known=True) for extension_app in known_extensions: + keep_app = False for parent_app_id in extension_app.requires: try: parent_app = self.appmgr.get(parent_app_id) parent_app._plugins.append(extension_app) + + if ( + parent_app.apptype in self.BUILTIN_APP_TYPES + and parent_app_id in self.appnames + ) or parent_app.apptype not in self.BUILTIN_APP_TYPES: + keep_app |= True + except FlipperManifestException: self._writer( f"Module {extension_app.appid} has unknown parent {parent_app_id}" ) + keep_app = True + # Debug output for plugin parentage + # print( + # f"Module {extension_app.appid} has parents {extension_app.requires} keep={keep_app}" + # ) + if not keep_app and extension_app in self.extapps: + # print(f"Excluding plugin {extension_app.appid}") + self.extapps.remove(extension_app) def get_apps_cdefs(self): cdefs = set() @@ -432,9 +448,11 @@ class AppBuildset: return sorted( filter( lambda app: app.apptype == apptype, - self.appmgr.known_apps.values() - if all_known - else map(self.appmgr.get, self.appnames), + ( + self.appmgr.known_apps.values() + if all_known + else map(self.appmgr.get, self.appnames) + ), ), key=lambda app: app.order, ) diff --git a/scripts/fbt_tools/fbt_extapps.py b/scripts/fbt_tools/fbt_extapps.py index a7914c4f87..540510b0d4 100644 --- a/scripts/fbt_tools/fbt_extapps.py +++ b/scripts/fbt_tools/fbt_extapps.py @@ -461,7 +461,8 @@ def _gather_app_components(env, appname) -> AppDeploymentComponents: else: # host app is a built-in app components.add_app(artifacts_app_to_run) - components.extra_launch_args = f"-a {host_app.name}" + if host_app.name: + components.extra_launch_args = f"-a {host_app.name}" else: raise UserError("Host app is unknown") else: diff --git a/scripts/fbt_tools/fbt_sdk.py b/scripts/fbt_tools/fbt_sdk.py index a3f7faa577..ef2aa91461 100644 --- a/scripts/fbt_tools/fbt_sdk.py +++ b/scripts/fbt_tools/fbt_sdk.py @@ -198,6 +198,7 @@ def gen_sdk_data(sdk_cache: SdkCache): api_def.extend( (f"#include <{h.name}>" for h in sdk_cache.get_headers()), ) + api_def.append('#pragma GCC diagnostic ignored "-Wdeprecated-declarations"') api_def.append(f"const int elf_api_version = {sdk_cache.version.as_int()};") diff --git a/targets/f18/api_symbols.csv b/targets/f18/api_symbols.csv index ce7ad25369..04ceb928cb 100644 --- a/targets/f18/api_symbols.csv +++ b/targets/f18/api_symbols.csv @@ -1,6 +1,7 @@ entry,status,name,type,params -Version,+,61.4,, +Version,+,62.3,, Header,+,applications/services/bt/bt_service/bt.h,, +Header,+,applications/services/bt/bt_service/bt_keys_storage.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, Header,+,applications/services/dialogs/dialogs.h,, @@ -156,10 +157,12 @@ Header,+,lib/toolbox/hex.h,, Header,+,lib/toolbox/keys_dict.h,, Header,+,lib/toolbox/manchester_decoder.h,, Header,+,lib/toolbox/manchester_encoder.h,, +Header,+,lib/toolbox/md5_calc.h,, Header,+,lib/toolbox/name_generator.h,, Header,+,lib/toolbox/path.h,, Header,+,lib/toolbox/pretty_format.h,, Header,+,lib/toolbox/protocols/protocol_dict.h,, +Header,+,lib/toolbox/pulse_protocols/pulse_glue.h,, Header,+,lib/toolbox/saved_struct.h,, Header,+,lib/toolbox/simple_array.h,, Header,+,lib/toolbox/stream/buffered_file_stream.h,, @@ -168,6 +171,7 @@ Header,+,lib/toolbox/stream/stream.h,, Header,+,lib/toolbox/stream/string_stream.h,, Header,+,lib/toolbox/tar/tar_archive.h,, Header,+,lib/toolbox/value_index.h,, +Header,+,lib/toolbox/varint.h,, Header,+,lib/toolbox/version.h,, Header,+,targets/f18/furi_hal/furi_hal_resources.h,, Header,+,targets/f18/furi_hal/furi_hal_spi_config.h,, @@ -680,8 +684,15 @@ Function,+,ble_svc_serial_update_tx,_Bool,"BleServiceSerial*, uint8_t*, uint16_t Function,-,bsearch,void*,"const void*, const void*, size_t, size_t, __compar_fn_t" Function,+,bt_disconnect,void,Bt* Function,+,bt_forget_bonded_devices,void,Bt* +Function,+,bt_keys_storage_alloc,BtKeysStorage*,const char* +Function,+,bt_keys_storage_delete,_Bool,BtKeysStorage* +Function,+,bt_keys_storage_free,void,BtKeysStorage* +Function,+,bt_keys_storage_load,_Bool,BtKeysStorage* Function,+,bt_keys_storage_set_default_path,void,Bt* +Function,+,bt_keys_storage_set_file_path,void,"BtKeysStorage*, const char*" +Function,+,bt_keys_storage_set_ram_params,void,"BtKeysStorage*, uint8_t*, uint16_t" Function,+,bt_keys_storage_set_storage_path,void,"Bt*, const char*" +Function,+,bt_keys_storage_update,_Bool,"BtKeysStorage*, uint8_t*, uint32_t" Function,+,bt_profile_restore_default,_Bool,Bt* Function,+,bt_profile_start,FuriHalBleProfileBase*,"Bt*, const FuriHalBleProfileTemplate*, FuriHalBleProfileParams" Function,+,bt_set_status_changed_callback,void,"Bt*, BtStatusChangedCallback, void*" @@ -773,7 +784,7 @@ Function,+,compress_alloc,Compress*,uint16_t Function,+,compress_decode,_Bool,"Compress*, uint8_t*, size_t, uint8_t*, size_t, size_t*" Function,+,compress_encode,_Bool,"Compress*, uint8_t*, size_t, uint8_t*, size_t, size_t*" Function,+,compress_free,void,Compress* -Function,+,compress_icon_alloc,CompressIcon*, +Function,+,compress_icon_alloc,CompressIcon*,size_t Function,+,compress_icon_decode,void,"CompressIcon*, const uint8_t*, uint8_t**" Function,+,compress_icon_free,void,CompressIcon* Function,-,copysign,double,"double, double" @@ -1490,7 +1501,7 @@ Function,+,furi_mutex_free,void,FuriMutex* Function,+,furi_mutex_get_owner,FuriThreadId,FuriMutex* Function,+,furi_mutex_release,FuriStatus,FuriMutex* Function,+,furi_pubsub_alloc,FuriPubSub*, -Function,-,furi_pubsub_free,void,FuriPubSub* +Function,+,furi_pubsub_free,void,FuriPubSub* Function,+,furi_pubsub_publish,void,"FuriPubSub*, void*" Function,+,furi_pubsub_subscribe,FuriPubSubSubscription*,"FuriPubSub*, FuriPubSubCallback, void*" Function,+,furi_pubsub_unsubscribe,void,"FuriPubSub*, FuriPubSubSubscription*" @@ -1675,8 +1686,10 @@ Function,+,icon_animation_set_update_callback,void,"IconAnimation*, IconAnimatio Function,+,icon_animation_start,void,IconAnimation* Function,+,icon_animation_stop,void,IconAnimation* Function,+,icon_get_data,const uint8_t*,const Icon* -Function,+,icon_get_height,uint8_t,const Icon* -Function,+,icon_get_width,uint8_t,const Icon* +Function,+,icon_get_frame_count,uint32_t,const Icon* +Function,+,icon_get_frame_data,const uint8_t*,"const Icon*, uint32_t" +Function,+,icon_get_height,uint16_t,const Icon* +Function,+,icon_get_width,uint16_t,const Icon* Function,-,ilogb,int,double Function,-,ilogbf,int,float Function,-,ilogbl,int,long double @@ -1980,6 +1993,8 @@ Function,-,mbedtls_sha256_update,int,"mbedtls_sha256_context*, const unsigned ch 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" +Function,+,md5_calc_file,_Bool,"File*, const char*, unsigned char[16], FS_Error*" +Function,+,md5_string_calc_file,_Bool,"File*, const char*, FuriString*, FS_Error*" Function,-,memccpy,void*,"void*, const void*, int, size_t" Function,+,memchr,void*,"const void*, int, size_t" Function,+,memcmp,int,"const void*, const void*, size_t" @@ -2254,6 +2269,11 @@ Function,+,protocol_dict_render_brief_data,void,"ProtocolDict*, FuriString*, siz Function,+,protocol_dict_render_data,void,"ProtocolDict*, FuriString*, size_t" Function,+,protocol_dict_render_uid,void,"ProtocolDict*, FuriString*, size_t" Function,+,protocol_dict_set_data,void,"ProtocolDict*, size_t, const uint8_t*, size_t" +Function,+,pulse_glue_alloc,PulseGlue*, +Function,+,pulse_glue_free,void,PulseGlue* +Function,+,pulse_glue_pop,void,"PulseGlue*, uint32_t*, uint32_t*" +Function,+,pulse_glue_push,_Bool,"PulseGlue*, _Bool, uint32_t" +Function,+,pulse_glue_reset,void,PulseGlue* Function,-,pulse_reader_alloc,PulseReader*,"const GpioPin*, uint32_t" Function,-,pulse_reader_free,void,PulseReader* Function,-,pulse_reader_receive,uint32_t,"PulseReader*, int" @@ -2642,6 +2662,12 @@ Function,+,variable_item_list_set_selected_item,void,"VariableItemList*, uint8_t Function,+,variable_item_set_current_value_index,void,"VariableItem*, uint8_t" Function,+,variable_item_set_current_value_text,void,"VariableItem*, const char*" Function,+,variable_item_set_values_count,void,"VariableItem*, uint8_t" +Function,+,varint_int32_length,size_t,int32_t +Function,+,varint_int32_pack,size_t,"int32_t, uint8_t*" +Function,+,varint_int32_unpack,size_t,"int32_t*, const uint8_t*, size_t" +Function,+,varint_uint32_length,size_t,uint32_t +Function,+,varint_uint32_pack,size_t,"uint32_t, uint8_t*" +Function,+,varint_uint32_unpack,size_t,"uint32_t*, const uint8_t*, size_t" Function,-,vasiprintf,int,"char**, const char*, __gnuc_va_list" Function,-,vasniprintf,char*,"char*, size_t*, const char*, __gnuc_va_list" Function,-,vasnprintf,char*,"char*, size_t*, const char*, __gnuc_va_list" diff --git a/targets/f18/target.json b/targets/f18/target.json index 43e9254cd4..229ec0a7ad 100644 --- a/targets/f18/target.json +++ b/targets/f18/target.json @@ -30,7 +30,6 @@ "mjs", "mbedtls", "flipper_application", - "toolbox", "u8g2", "nanopb", "update_util", @@ -38,6 +37,7 @@ "flipperformat", "flipper18", "bit_lib", + "toolbox", "datetime" ], "excluded_sources": [ diff --git a/targets/f7/api_symbols.csv b/targets/f7/api_symbols.csv index 5a44dbc6fd..e7a97aff95 100644 --- a/targets/f7/api_symbols.csv +++ b/targets/f7/api_symbols.csv @@ -1,7 +1,8 @@ entry,status,name,type,params -Version,+,61.4,, +Version,+,62.3,, Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,, Header,+,applications/services/bt/bt_service/bt.h,, +Header,+,applications/services/bt/bt_service/bt_keys_storage.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, Header,+,applications/services/dialogs/dialogs.h,, @@ -158,6 +159,7 @@ Header,+,lib/nfc/protocols/mf_ultralight/mf_ultralight_listener.h,, Header,+,lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.h,, Header,+,lib/nfc/protocols/mf_ultralight/mf_ultralight_poller_sync.h,, Header,+,lib/nfc/protocols/slix/slix.h,, +Header,+,lib/nfc/protocols/slix/slix_poller.h,, Header,+,lib/nfc/protocols/st25tb/st25tb.h,, Header,+,lib/nfc/protocols/st25tb/st25tb_poller.h,, Header,+,lib/nfc/protocols/st25tb/st25tb_poller_sync.h,, @@ -206,6 +208,7 @@ Header,+,lib/subghz/protocols/public_api.h,, Header,+,lib/subghz/protocols/raw.h,, Header,+,lib/subghz/receiver.h,, Header,+,lib/subghz/registry.h,, +Header,+,lib/subghz/subghz_file_encoder_worker.h,, Header,+,lib/subghz/subghz_protocol_registry.h,, Header,+,lib/subghz/subghz_setting.h,, Header,+,lib/subghz/subghz_tx_rx_worker.h,, @@ -222,10 +225,12 @@ Header,+,lib/toolbox/hex.h,, Header,+,lib/toolbox/keys_dict.h,, Header,+,lib/toolbox/manchester_decoder.h,, Header,+,lib/toolbox/manchester_encoder.h,, +Header,+,lib/toolbox/md5_calc.h,, Header,+,lib/toolbox/name_generator.h,, Header,+,lib/toolbox/path.h,, Header,+,lib/toolbox/pretty_format.h,, Header,+,lib/toolbox/protocols/protocol_dict.h,, +Header,+,lib/toolbox/pulse_protocols/pulse_glue.h,, Header,+,lib/toolbox/saved_struct.h,, Header,+,lib/toolbox/simple_array.h,, Header,+,lib/toolbox/stream/buffered_file_stream.h,, @@ -234,6 +239,7 @@ Header,+,lib/toolbox/stream/stream.h,, Header,+,lib/toolbox/stream/string_stream.h,, Header,+,lib/toolbox/tar/tar_archive.h,, Header,+,lib/toolbox/value_index.h,, +Header,+,lib/toolbox/varint.h,, Header,+,lib/toolbox/version.h,, Header,+,targets/f7/ble_glue/furi_ble/event_dispatcher.h,, Header,+,targets/f7/ble_glue/furi_ble/gatt.h,, @@ -751,8 +757,15 @@ Function,+,ble_svc_serial_update_tx,_Bool,"BleServiceSerial*, uint8_t*, uint16_t Function,-,bsearch,void*,"const void*, const void*, size_t, size_t, __compar_fn_t" Function,+,bt_disconnect,void,Bt* Function,+,bt_forget_bonded_devices,void,Bt* +Function,+,bt_keys_storage_alloc,BtKeysStorage*,const char* +Function,+,bt_keys_storage_delete,_Bool,BtKeysStorage* +Function,+,bt_keys_storage_free,void,BtKeysStorage* +Function,+,bt_keys_storage_load,_Bool,BtKeysStorage* Function,+,bt_keys_storage_set_default_path,void,Bt* +Function,+,bt_keys_storage_set_file_path,void,"BtKeysStorage*, const char*" +Function,+,bt_keys_storage_set_ram_params,void,"BtKeysStorage*, uint8_t*, uint16_t" Function,+,bt_keys_storage_set_storage_path,void,"Bt*, const char*" +Function,+,bt_keys_storage_update,_Bool,"BtKeysStorage*, uint8_t*, uint32_t" Function,+,bt_profile_restore_default,_Bool,Bt* Function,+,bt_profile_start,FuriHalBleProfileBase*,"Bt*, const FuriHalBleProfileTemplate*, FuriHalBleProfileParams" Function,+,bt_set_status_changed_callback,void,"Bt*, BtStatusChangedCallback, void*" @@ -844,7 +857,7 @@ Function,+,compress_alloc,Compress*,uint16_t Function,+,compress_decode,_Bool,"Compress*, uint8_t*, size_t, uint8_t*, size_t, size_t*" Function,+,compress_encode,_Bool,"Compress*, uint8_t*, size_t, uint8_t*, size_t, size_t*" Function,+,compress_free,void,Compress* -Function,+,compress_icon_alloc,CompressIcon*, +Function,+,compress_icon_alloc,CompressIcon*,size_t Function,+,compress_icon_decode,void,"CompressIcon*, const uint8_t*, uint8_t**" Function,+,compress_icon_free,void,CompressIcon* Function,-,copysign,double,"double, double" @@ -1696,7 +1709,7 @@ Function,+,furi_mutex_free,void,FuriMutex* Function,+,furi_mutex_get_owner,FuriThreadId,FuriMutex* Function,+,furi_mutex_release,FuriStatus,FuriMutex* Function,+,furi_pubsub_alloc,FuriPubSub*, -Function,-,furi_pubsub_free,void,FuriPubSub* +Function,+,furi_pubsub_free,void,FuriPubSub* Function,+,furi_pubsub_publish,void,"FuriPubSub*, void*" Function,+,furi_pubsub_subscribe,FuriPubSubSubscription*,"FuriPubSub*, FuriPubSubCallback, void*" Function,+,furi_pubsub_unsubscribe,void,"FuriPubSub*, FuriPubSubSubscription*" @@ -1920,8 +1933,10 @@ Function,+,icon_animation_set_update_callback,void,"IconAnimation*, IconAnimatio Function,+,icon_animation_start,void,IconAnimation* Function,+,icon_animation_stop,void,IconAnimation* Function,+,icon_get_data,const uint8_t*,const Icon* -Function,+,icon_get_height,uint8_t,const Icon* -Function,+,icon_get_width,uint8_t,const Icon* +Function,+,icon_get_frame_count,uint32_t,const Icon* +Function,+,icon_get_frame_data,const uint8_t*,"const Icon*, uint32_t" +Function,+,icon_get_height,uint16_t,const Icon* +Function,+,icon_get_width,uint16_t,const Icon* Function,-,ilogb,int,double Function,-,ilogbf,int,float Function,-,ilogbl,int,long double @@ -2390,6 +2405,8 @@ Function,-,mbedtls_sha256_update,int,"mbedtls_sha256_context*, const unsigned ch 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" +Function,+,md5_calc_file,_Bool,"File*, const char*, unsigned char[16], FS_Error*" +Function,+,md5_string_calc_file,_Bool,"File*, const char*, FuriString*, FS_Error*" Function,-,memccpy,void*,"void*, const void*, int, size_t" Function,+,memchr,void*,"const void*, int, size_t" Function,+,memcmp,int,"const void*, const void*, size_t" @@ -2852,6 +2869,11 @@ Function,+,protocol_dict_render_brief_data,void,"ProtocolDict*, FuriString*, siz Function,+,protocol_dict_render_data,void,"ProtocolDict*, FuriString*, size_t" Function,+,protocol_dict_render_uid,void,"ProtocolDict*, FuriString*, size_t" Function,+,protocol_dict_set_data,void,"ProtocolDict*, size_t, const uint8_t*, size_t" +Function,+,pulse_glue_alloc,PulseGlue*, +Function,+,pulse_glue_free,void,PulseGlue* +Function,+,pulse_glue_pop,void,"PulseGlue*, uint32_t*, uint32_t*" +Function,+,pulse_glue_push,_Bool,"PulseGlue*, _Bool, uint32_t" +Function,+,pulse_glue_reset,void,PulseGlue* Function,-,pulse_reader_alloc,PulseReader*,"const GpioPin*, uint32_t" Function,-,pulse_reader_free,void,PulseReader* Function,-,pulse_reader_receive,uint32_t,"PulseReader*, int" @@ -2992,6 +3014,11 @@ Function,+,slix_is_counter_increment_protected,_Bool,const SlixData* Function,+,slix_is_equal,_Bool,"const SlixData*, const SlixData*" Function,+,slix_is_privacy_mode,_Bool,const SlixData* Function,+,slix_load,_Bool,"SlixData*, FlipperFormat*, uint32_t" +Function,+,slix_poller_get_nxp_system_info,SlixError,"SlixPoller*, SlixSystemInfo*" +Function,+,slix_poller_get_random_number,SlixError,"SlixPoller*, SlixRandomNumber*" +Function,+,slix_poller_read_signature,SlixError,"SlixPoller*, SlixSignature*" +Function,+,slix_poller_send_frame,SlixError,"SlixPoller*, const BitBuffer*, BitBuffer*, uint32_t" +Function,+,slix_poller_set_password,SlixError,"SlixPoller*, SlixPasswordType, SlixPassword, SlixRandomNumber" Function,+,slix_reset,void,SlixData* Function,+,slix_save,_Bool,"const SlixData*, FlipperFormat*" Function,+,slix_set_uid,_Bool,"SlixData*, const uint8_t*, size_t" @@ -3244,6 +3271,13 @@ Function,+,subghz_environment_set_alutech_at_4n_rainbow_table_file_name,void,"Su Function,+,subghz_environment_set_came_atomo_rainbow_table_file_name,void,"SubGhzEnvironment*, const char*" Function,+,subghz_environment_set_nice_flor_s_rainbow_table_file_name,void,"SubGhzEnvironment*, const char*" Function,+,subghz_environment_set_protocol_registry,void,"SubGhzEnvironment*, const SubGhzProtocolRegistry*" +Function,+,subghz_file_encoder_worker_alloc,SubGhzFileEncoderWorker*, +Function,+,subghz_file_encoder_worker_callback_end,void,"SubGhzFileEncoderWorker*, SubGhzFileEncoderWorkerCallbackEnd, void*" +Function,+,subghz_file_encoder_worker_free,void,SubGhzFileEncoderWorker* +Function,+,subghz_file_encoder_worker_get_level_duration,LevelDuration,void* +Function,+,subghz_file_encoder_worker_is_running,_Bool,SubGhzFileEncoderWorker* +Function,+,subghz_file_encoder_worker_start,_Bool,"SubGhzFileEncoderWorker*, const char*, const char*" +Function,+,subghz_file_encoder_worker_stop,void,SubGhzFileEncoderWorker* Function,-,subghz_keystore_alloc,SubGhzKeystore*, Function,-,subghz_keystore_free,void,SubGhzKeystore* Function,-,subghz_keystore_get_data,SubGhzKeyArray_t*,SubGhzKeystore* @@ -3442,6 +3476,12 @@ Function,+,variable_item_list_set_selected_item,void,"VariableItemList*, uint8_t Function,+,variable_item_set_current_value_index,void,"VariableItem*, uint8_t" Function,+,variable_item_set_current_value_text,void,"VariableItem*, const char*" Function,+,variable_item_set_values_count,void,"VariableItem*, uint8_t" +Function,+,varint_int32_length,size_t,int32_t +Function,+,varint_int32_pack,size_t,"int32_t, uint8_t*" +Function,+,varint_int32_unpack,size_t,"int32_t*, const uint8_t*, size_t" +Function,+,varint_uint32_length,size_t,uint32_t +Function,+,varint_uint32_pack,size_t,"uint32_t, uint8_t*" +Function,+,varint_uint32_unpack,size_t,"uint32_t*, const uint8_t*, size_t" Function,-,vasiprintf,int,"char**, const char*, __gnuc_va_list" Function,-,vasniprintf,char*,"char*, size_t*, const char*, __gnuc_va_list" Function,-,vasnprintf,char*,"char*, size_t*, const char*, __gnuc_va_list" diff --git a/targets/f7/target.json b/targets/f7/target.json index 25872198bf..eae92a5cd6 100644 --- a/targets/f7/target.json +++ b/targets/f7/target.json @@ -45,7 +45,6 @@ "mbedtls", "lfrfid", "flipper_application", - "toolbox", "u8g2", "nanopb", "update_util", @@ -53,6 +52,7 @@ "flipperformat", "flipper7", "bit_lib", + "toolbox", "datetime" ] }