Merge branch 'dev' into astra/3746-mfp-detect

This commit is contained in:
gornekich 2024-05-28 17:11:43 +01:00 committed by GitHub
commit 8cdb8aafac
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
83 changed files with 1232 additions and 393 deletions

View File

@ -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)",

View File

@ -18,6 +18,33 @@ static const TextBoxViewTestContent text_box_view_test_content_arr[] = {
.focus = TextBoxFocusStart,
.text = "Hello, let's test text box. Press Right and Left to switch content",
},
{
.font = TextBoxFontText,
.focus = TextBoxFocusEnd,
.text = "First test to add dynamically lines with EndFocus set\nLine 0",
},
{
.font = TextBoxFontText,
.focus = TextBoxFocusEnd,
.text = "First test to add dynamically lines with EndFocus set\nLine 0\nLine 1",
},
{
.font = TextBoxFontText,
.focus = TextBoxFocusEnd,
.text = "First test to add dynamically lines with EndFocus set\nLine 0\nLine 1\nLine 2",
},
{
.font = TextBoxFontText,
.focus = TextBoxFocusEnd,
.text =
"First test to add dynamically lines with EndFocus set\nLine 0\nLine 1\nLine 2\nLine 3",
},
{
.font = TextBoxFontText,
.focus = TextBoxFocusEnd,
.text =
"First test to add dynamically lines with EndFocus set\nLine 0\nLine 1\nLine 2\nLine 3\nLine 4",
},
{
.font = TextBoxFontText,
.focus = TextBoxFocusStart,
@ -57,7 +84,8 @@ typedef struct {
} TextBoxViewTest;
static void text_box_update_view(TextBoxViewTest* instance) {
text_box_reset(instance->text_box);
// Intentional incorrect way to reset text box to verify that state resets if text changes
text_box_set_text(instance->text_box, "");
const TextBoxViewTestContent* content =
&text_box_view_test_content_arr[instance->current_content_i];

View File

@ -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"],
)

View File

@ -1,168 +0,0 @@
#include <stdio.h>
#include <furi.h>
#include <furi_hal.h>
#include "minunit_vars.h"
#include <notification/notification_messages.h>
#include <cli/cli.h>
#include <loader/loader.h>
#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
}

View File

@ -0,0 +1,216 @@
#include "test_runner.h"
#include "tests/test_api.h"
#include <cli/cli.h>
#include <toolbox/path.h>
#include <loader/loader.h>
#include <storage/storage.h>
#include <notification/notification_messages.h>
#include <loader/firmware_api/firmware_api.h>
#include <flipper_application/flipper_application.h>
#include <flipper_application/api_hashtable/api_hashtable.h>
#include <flipper_application/plugins/composite_resolver.h>
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");
}
}
}
}

View File

@ -0,0 +1,12 @@
#pragma once
#include <furi.h>
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);

View File

@ -1,5 +1,5 @@
#include <furi.h>
#include "../minunit.h"
#include "../test.h"
#include <bit_lib/bit_lib.h>
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;
}
}
TEST_API_DEFINE(run_minunit_test_bit_lib)

View File

@ -1,6 +1,6 @@
#include <furi.h>
#include <furi_hal.h>
#include "../minunit.h"
#include "../test.h"
#include <bt/bt_service/bt_keys_storage.h>
#include <storage/storage.h>
@ -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)

View File

@ -0,0 +1,42 @@
#include "../test.h"
#include "../minunit_vars.h"
#include <furi.h>
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;
}

View File

@ -0,0 +1,159 @@
#include "../test.h"
#include <toolbox/compress.h>
#include <furi.h>
#include <furi_hal.h>
#include <furi_hal_random.h>
#include <storage/storage.h>
#include <stdint.h>
#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)

View File

@ -1,5 +1,5 @@
#include <furi.h>
#include "../minunit.h"
#include "../test.h"
#include <datetime/datetime.h>
@ -188,4 +188,6 @@ int run_minunit_test_datetime(void) {
MU_RUN_SUITE(test_datetime_validate_datetime);
return MU_EXIT_CODE;
}
}
TEST_API_DEFINE(run_minunit_test_datetime)

View File

@ -1,6 +1,6 @@
#include <dialogs/dialogs.h>
#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)

View File

@ -1,4 +1,4 @@
#include "../minunit.h"
#include "../test.h"
#include <furi.h>
#include <m-dict.h>
#include <toolbox/dir_walk.h>
@ -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;
}
}
TEST_API_DEFINE(run_minunit_test_dirwalk)

View File

@ -1,4 +1,4 @@
#include "../minunit.h"
#include "../test.h"
#include <furi.h>
#include <furi_hal_random.h>
@ -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)

View File

@ -2,7 +2,7 @@
#include <flipper_format/flipper_format.h>
#include <flipper_format/flipper_format_i.h>
#include <toolbox/stream/stream.h>
#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)

View File

@ -3,7 +3,7 @@
#include <flipper_format/flipper_format_i.h>
#include <toolbox/stream/stream.h>
#include <storage/storage.h>
#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)

View File

@ -1,7 +1,7 @@
#include <float.h>
#include <float_tools.h>
#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)

View File

@ -1,4 +1,4 @@
#include "../minunit.h"
#include "../test.h"
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

View File

@ -1,7 +1,7 @@
#include <stdio.h>
#include <string.h>
#include <furi.h>
#include "../minunit.h"
#include "../test.h"
const uint32_t context_value = 0xdeadbeef;
const uint32_t notify_value_0 = 0x12345678;

View File

@ -1,7 +1,7 @@
#include <stdio.h>
#include <string.h>
#include <furi.h>
#include "../minunit.h"
#include "../test.h"
#define TEST_RECORD_NAME "test/holding"

View File

@ -1,7 +1,7 @@
#include <stdio.h>
#include <furi.h>
#include <furi_hal.h>
#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)

View File

@ -4,7 +4,7 @@
#include <furi.h>
#include <furi_hal.h>
#include <lp5562_reg.h>
#include "../minunit.h"
#include "../test.h"
#include <stdlib.h>
#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)

View File

@ -1,7 +1,7 @@
#include <stdio.h>
#include <furi.h>
#include <furi_hal.h>
#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)

View File

@ -1,5 +1,5 @@
#include <furi.h>
#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;
}
}
TEST_API_DEFINE(run_minunit_test_furi_string)

View File

@ -2,7 +2,7 @@
#include <flipper_format.h>
#include <infrared.h>
#include <common/infrared_common_i.h>
#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)

View File

@ -1,5 +1,5 @@
#include <furi.h>
#include "../minunit.h"
#include "../test.h"
#include <toolbox/protocols/protocol_dict.h>
#include <lfrfid/protocols/lfrfid_protocols.h>
#include <toolbox/pulse_protocols/pulse_glue.h>
@ -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;
}
}
TEST_API_DEFINE(run_minunit_test_lfrfid_protocols)

View File

@ -1,5 +1,5 @@
#include <furi.c>
#include "../minunit.h"
#include "../test.h"
#include <update_util/resources/manifest.h>
#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;
}
}
TEST_API_DEFINE(run_minunit_test_manifest)

View File

@ -24,7 +24,7 @@
#include <toolbox/keys_dict.h>
#include <nfc/nfc.h>
#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)

View File

@ -1,6 +1,6 @@
#include <furi.h>
#include <furi_hal.h>
#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)

View File

@ -1,5 +1,5 @@
#include <furi.h>
#include "../minunit.h"
#include "../test.h"
#include <toolbox/protocols/protocol_dict.h>
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;
}
}
TEST_API_DEFINE(run_minunit_test_protocol_dict)

View File

@ -17,7 +17,7 @@
#include <lib/toolbox/path.h>
#include <m-list.h>
#include "../minunit.h"
#include "../test.h"
#include <protobuf_version.h>
#include <pb.h>
@ -1864,3 +1864,5 @@ int32_t delay_test_app(void* p) {
return 0;
}
TEST_API_DEFINE(run_minunit_test_rpc)

View File

@ -1,4 +1,4 @@
#include "../minunit.h"
#include "../test.h"
#include <furi.h>
#include <storage/storage.h>
@ -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)

View File

@ -4,7 +4,7 @@
#include <toolbox/stream/file_stream.h>
#include <toolbox/stream/buffered_file_stream.h>
#include <storage/storage.h>
#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)

View File

@ -1,6 +1,6 @@
#include <furi.h>
#include <furi_hal.h>
#include "../minunit.h"
#include "../test.h"
#include <lib/subghz/receiver.h>
#include <lib/subghz/transmitter.h>
#include <lib/subghz/subghz_keystore.h>
@ -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)

View File

@ -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);

View File

@ -0,0 +1,29 @@
#pragma once
#include <flipper_application/flipper_application.h>
#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; \
}

View File

@ -1,6 +1,8 @@
#include <furi.h>
#include <furi_hal.h>
#include "../minunit.h"
#include "../test.h"
#include <toolbox/varint.h>
#include <toolbox/profiler.h>
@ -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;
}
}
TEST_API_DEFINE(run_minunit_test_varint)

View File

@ -0,0 +1,19 @@
#include <flipper_application/api_hashtable/api_hashtable.h>
#include <flipper_application/api_hashtable/compilesort.hpp>
#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;

View File

@ -0,0 +1,29 @@
#include <update_util/resources/manifest.h>
#include <nfc/protocols/slix/slix_i.h>
#include <nfc/protocols/iso15693_3/iso15693_3_poller_i.h>
#include <FreeRTOS.h>
#include <FreeRTOS-Kernel/include/queue.h>
#include <rpc/rpc_i.h>
#include <flipper.pb.h>
static constexpr auto unit_tests_api_table = sort(create_array_t<sym_entry>(
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)));

View File

@ -0,0 +1,21 @@
#include <furi.h>
#include <cli/cli.h>
#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
}

View File

@ -16,6 +16,7 @@ ArchiveApp* archive_alloc(void) {
ArchiveApp* archive = malloc(sizeof(ArchiveApp));
archive->gui = furi_record_open(RECORD_GUI);
archive->loader = furi_record_open(RECORD_LOADER);
archive->text_input = text_input_alloc();
archive->fav_move_str = furi_string_alloc();
@ -61,6 +62,8 @@ void archive_free(ArchiveApp* archive) {
text_input_free(archive->text_input);
furi_record_close(RECORD_LOADER);
archive->loader = NULL;
furi_record_close(RECORD_GUI);
archive->gui = NULL;

View File

@ -22,6 +22,7 @@ typedef enum {
struct ArchiveApp {
Gui* gui;
Loader* loader;
ViewDispatcher* view_dispatcher;
SceneManager* scene_manager;
ArchiveBrowserView* browser;

View File

@ -86,10 +86,8 @@ void archive_scene_browser_on_enter(void* context) {
archive_update_focus(browser, archive->text_store);
view_dispatcher_switch_to_view(archive->view_dispatcher, ArchiveViewBrowser);
Loader* loader = furi_record_open(RECORD_LOADER);
archive->loader_stop_subscription =
furi_pubsub_subscribe(loader_get_pubsub(loader), archive_loader_callback, archive);
furi_record_close(RECORD_LOADER);
archive->loader_stop_subscription = furi_pubsub_subscribe(
loader_get_pubsub(archive->loader), archive_loader_callback, archive);
uint32_t state = scene_manager_get_scene_state(archive->scene_manager, ArchiveAppSceneBrowser);
@ -213,10 +211,11 @@ bool archive_scene_browser_on_event(void* context, SceneManagerEvent event) {
if(!archive_is_home(browser)) {
archive_leave_dir(browser);
} else {
Loader* loader = furi_record_open(RECORD_LOADER);
furi_pubsub_unsubscribe(
loader_get_pubsub(loader), archive->loader_stop_subscription);
furi_record_close(RECORD_LOADER);
if(archive->loader_stop_subscription) {
furi_pubsub_unsubscribe(
loader_get_pubsub(archive->loader), archive->loader_stop_subscription);
archive->loader_stop_subscription = NULL;
}
view_dispatcher_stop(archive->view_dispatcher);
}
@ -232,8 +231,9 @@ bool archive_scene_browser_on_event(void* context, SceneManagerEvent event) {
void archive_scene_browser_on_exit(void* context) {
ArchiveApp* archive = (ArchiveApp*)context;
Loader* loader = furi_record_open(RECORD_LOADER);
furi_pubsub_unsubscribe(loader_get_pubsub(loader), archive->loader_stop_subscription);
furi_record_close(RECORD_LOADER);
if(archive->loader_stop_subscription) {
furi_pubsub_unsubscribe(
loader_get_pubsub(archive->loader), archive->loader_stop_subscription);
archive->loader_stop_subscription = NULL;
}
}

View File

@ -2,22 +2,12 @@
#include "../helpers/protocol_support/nfc_protocol_support_gui_common.h"
static void nfc_scene_set_uid_byte_input_changed_callback(void* context) {
NfcApp* instance = context;
// Retrieve previously saved UID length
const size_t uid_len = scene_manager_get_scene_state(instance->scene_manager, NfcSceneSetUid);
nfc_device_set_uid(instance->nfc_device, instance->byte_input_store, uid_len);
}
void nfc_scene_set_uid_on_enter(void* context) {
NfcApp* instance = context;
size_t uid_len;
const uint8_t* uid = nfc_device_get_uid(instance->nfc_device, &uid_len);
memcpy(instance->byte_input_store, uid, uid_len);
// Save UID length for use in callback
scene_manager_set_scene_state(instance->scene_manager, NfcSceneSetUid, uid_len);
// Setup view
ByteInput* byte_input = instance->byte_input;
@ -25,7 +15,7 @@ void nfc_scene_set_uid_on_enter(void* context) {
byte_input_set_result_callback(
byte_input,
nfc_protocol_support_common_byte_input_done_callback,
nfc_scene_set_uid_byte_input_changed_callback,
NULL,
instance,
instance->byte_input_store,
uid_len);
@ -39,6 +29,9 @@ bool nfc_scene_set_uid_on_event(void* context, SceneManagerEvent event) {
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == NfcCustomEventByteInputDone) {
size_t uid_len = 0;
nfc_device_get_uid(instance->nfc_device, &uid_len);
nfc_device_set_uid(instance->nfc_device, instance->byte_input_store, uid_len);
if(scene_manager_has_previous_scene(instance->scene_manager, NfcSceneSavedMenu)) {
if(nfc_save(instance)) {
scene_manager_next_scene(instance->scene_manager, NfcSceneSaveSuccess);

View File

@ -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(

View File

@ -3,6 +3,10 @@
#include <stdint.h>
#include <stdbool.h>
#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

View File

@ -1,6 +1,5 @@
#include "slideshow.h"
#include <stddef.h>
#include <storage/storage.h>
#include <gui/icon.h>
#include <gui/icon_i.h>

View File

@ -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);
}

View File

@ -12,6 +12,8 @@
#include <m-algo.h>
#include <furi.h>
#define ICON_DECOMPRESSOR_BUFFER_SIZE (128u * 64 / 8)
#ifdef __cplusplus
extern "C" {
#endif

View File

@ -1,13 +1,16 @@
#include "icon.h"
#include "icon_i.h"
#include <furi.h>
uint8_t icon_get_width(const Icon* instance) {
#include <furi.h>
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];
}

View File

@ -6,6 +6,7 @@
#pragma once
#include <stdint.h>
#include <core/common_defines.h>
#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
}

View File

@ -4,11 +4,11 @@
*/
#pragma once
#include "icon.h"
#include <stdint.h>
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;

View File

@ -227,14 +227,13 @@ static void text_box_prepare_model(Canvas* canvas, TextBoxModel* model) {
text_box_seek_next_line(canvas, model);
lines_num++;
} while(!text_box_end_of_text_reached(model));
model->text_offset = 0;
lines_num++;
if(model->focus == TextBoxFocusEnd) {
if(lines_num > model->lines_on_screen) {
model->text_offset = window_offset[(lines_num - 1) % model->lines_on_screen];
}
} else {
model->text_offset = 0;
}
if(lines_num > model->lines_on_screen) {

View File

@ -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;

View File

@ -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);

View File

@ -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;
}
}

View File

@ -7,6 +7,10 @@
#include <flipper.pb.h>
#include <cli/cli.h>
#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

View File

@ -80,6 +80,7 @@ void desktop_settings_scene_favorite_on_enter(void* context) {
furi_assert(favorite_id < DummyAppNumber);
curr_favorite_app = &app->settings.dummy_apps[favorite_id];
default_passport = true;
favorite_id |= SCENE_STATE_SET_DUMMY_APP;
}
// Special case: Application browser
@ -141,28 +142,24 @@ void desktop_settings_scene_favorite_on_enter(void* context) {
switch(favorite_id) {
case SCENE_STATE_SET_FAVORITE_APP | FavoriteAppLeftShort:
submenu_set_header(submenu, "Left - Short");
case SCENE_STATE_SET_DUMMY_APP | DummyAppLeft:
submenu_set_header(submenu, "Left - Press");
break;
case SCENE_STATE_SET_FAVORITE_APP | FavoriteAppLeftLong:
submenu_set_header(submenu, "Left - Long");
submenu_set_header(submenu, "Left - Hold");
break;
case SCENE_STATE_SET_FAVORITE_APP | FavoriteAppRightShort:
submenu_set_header(submenu, "Right - Short");
case SCENE_STATE_SET_DUMMY_APP | DummyAppRight:
submenu_set_header(submenu, "Right - Press");
break;
case SCENE_STATE_SET_FAVORITE_APP | FavoriteAppRightLong:
submenu_set_header(submenu, "Right - Long");
break;
case SCENE_STATE_SET_DUMMY_APP | DummyAppLeft:
submenu_set_header(submenu, "Left");
break;
case SCENE_STATE_SET_DUMMY_APP | DummyAppRight:
submenu_set_header(submenu, "Right");
submenu_set_header(submenu, "Right - Hold");
break;
case SCENE_STATE_SET_DUMMY_APP | DummyAppDown:
submenu_set_header(submenu, "Down");
submenu_set_header(submenu, "Down - Press");
break;
case SCENE_STATE_SET_DUMMY_APP | DummyAppOk:
submenu_set_header(submenu, "Middle");
submenu_set_header(submenu, "Middle - Press");
break;
default:
break;

View File

@ -34,14 +34,14 @@ void desktop_settings_scene_quick_apps_direction_menu_on_enter(void* context) {
if(favorite_id == SCENE_STATE_SET_FAVORITE_APP) {
submenu_add_item(
submenu,
"Left - Click",
"Left - Press",
QuickAppsSubmenuIndexFavoriteLeftClick,
desktop_settings_scene_quick_apps_direction_menu_submenu_callback,
app);
submenu_add_item(
submenu,
"Right - Click",
"Right - Press",
QuickAppsSubmenuIndexFavoriteRightClick,
desktop_settings_scene_quick_apps_direction_menu_submenu_callback,
app);
@ -64,28 +64,28 @@ void desktop_settings_scene_quick_apps_direction_menu_on_enter(void* context) {
} else {
submenu_add_item(
submenu,
"Left - Click",
"Left - Press",
QuickAppsSubmenuIndexDummyLeftClick,
desktop_settings_scene_quick_apps_direction_menu_submenu_callback,
app);
submenu_add_item(
submenu,
"Right - Click",
"Right - Press",
QuickAppsSubmenuIndexDummyRightClick,
desktop_settings_scene_quick_apps_direction_menu_submenu_callback,
app);
submenu_add_item(
submenu,
"Down - Click",
"Down - Press",
QuickAppsSubmenuIndexDummyDownClick,
desktop_settings_scene_quick_apps_direction_menu_submenu_callback,
app);
submenu_add_item(
submenu,
"Middle - Click",
"Middle - Press",
QuickAppsSubmenuIndexDummyMiddleClick,
desktop_settings_scene_quick_apps_direction_menu_submenu_callback,
app);

View File

@ -411,6 +411,7 @@ bool protocol_electra_write_data(ProtocolElectra* protocol, void* data) {
};
void protocol_electra_render_data(ProtocolElectra* protocol, FuriString* result) {
protocol_electra_encoder_start(protocol);
furi_string_printf(result, "Epilogue: %016llX", protocol->encoded_epilogue);
};

View File

@ -35,6 +35,7 @@ env.Append(
File("protocols/mf_classic/mf_classic_poller.h"),
File("protocols/mf_plus/mf_plus_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

View File

@ -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

View File

@ -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"),
],
)

View File

@ -2,6 +2,10 @@
#include <furi_hal.h>
#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

View File

@ -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"),
],
)

View File

@ -3,6 +3,9 @@
#include <furi.h>
#include <lib/heatshrink/heatshrink_encoder.h>
#include <lib/heatshrink/heatshrink_decoder.h>
#include <stdint.h>
#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);
}

View File

@ -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;

View File

@ -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):

View File

@ -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,
)

View File

@ -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:

View File

@ -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()};")

View File

@ -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"

1 entry status name type params
2 Version + 61.4 62.3
3 Header + applications/services/bt/bt_service/bt.h
4 Header + applications/services/bt/bt_service/bt_keys_storage.h
5 Header + applications/services/cli/cli.h
6 Header + applications/services/cli/cli_vcp.h
7 Header + applications/services/dialogs/dialogs.h
157 Header + lib/toolbox/keys_dict.h
158 Header + lib/toolbox/manchester_decoder.h
159 Header + lib/toolbox/manchester_encoder.h
160 Header + lib/toolbox/md5_calc.h
161 Header + lib/toolbox/name_generator.h
162 Header + lib/toolbox/path.h
163 Header + lib/toolbox/pretty_format.h
164 Header + lib/toolbox/protocols/protocol_dict.h
165 Header + lib/toolbox/pulse_protocols/pulse_glue.h
166 Header + lib/toolbox/saved_struct.h
167 Header + lib/toolbox/simple_array.h
168 Header + lib/toolbox/stream/buffered_file_stream.h
171 Header + lib/toolbox/stream/string_stream.h
172 Header + lib/toolbox/tar/tar_archive.h
173 Header + lib/toolbox/value_index.h
174 Header + lib/toolbox/varint.h
175 Header + lib/toolbox/version.h
176 Header + targets/f18/furi_hal/furi_hal_resources.h
177 Header + targets/f18/furi_hal/furi_hal_spi_config.h
684 Function - bsearch void* const void*, const void*, size_t, size_t, __compar_fn_t
685 Function + bt_disconnect void Bt*
686 Function + bt_forget_bonded_devices void Bt*
687 Function + bt_keys_storage_alloc BtKeysStorage* const char*
688 Function + bt_keys_storage_delete _Bool BtKeysStorage*
689 Function + bt_keys_storage_free void BtKeysStorage*
690 Function + bt_keys_storage_load _Bool BtKeysStorage*
691 Function + bt_keys_storage_set_default_path void Bt*
692 Function + bt_keys_storage_set_file_path void BtKeysStorage*, const char*
693 Function + bt_keys_storage_set_ram_params void BtKeysStorage*, uint8_t*, uint16_t
694 Function + bt_keys_storage_set_storage_path void Bt*, const char*
695 Function + bt_keys_storage_update _Bool BtKeysStorage*, uint8_t*, uint32_t
696 Function + bt_profile_restore_default _Bool Bt*
697 Function + bt_profile_start FuriHalBleProfileBase* Bt*, const FuriHalBleProfileTemplate*, FuriHalBleProfileParams
698 Function + bt_set_status_changed_callback void Bt*, BtStatusChangedCallback, void*
784 Function + compress_decode _Bool Compress*, uint8_t*, size_t, uint8_t*, size_t, size_t*
785 Function + compress_encode _Bool Compress*, uint8_t*, size_t, uint8_t*, size_t, size_t*
786 Function + compress_free void Compress*
787 Function + compress_icon_alloc CompressIcon* size_t
788 Function + compress_icon_decode void CompressIcon*, const uint8_t*, uint8_t**
789 Function + compress_icon_free void CompressIcon*
790 Function - copysign double double, double
1501 Function + furi_mutex_get_owner FuriThreadId FuriMutex*
1502 Function + furi_mutex_release FuriStatus FuriMutex*
1503 Function + furi_pubsub_alloc FuriPubSub*
1504 Function - + furi_pubsub_free void FuriPubSub*
1505 Function + furi_pubsub_publish void FuriPubSub*, void*
1506 Function + furi_pubsub_subscribe FuriPubSubSubscription* FuriPubSub*, FuriPubSubCallback, void*
1507 Function + furi_pubsub_unsubscribe void FuriPubSub*, FuriPubSubSubscription*
1686 Function + icon_animation_start void IconAnimation*
1687 Function + icon_animation_stop void IconAnimation*
1688 Function + icon_get_data const uint8_t* const Icon*
1689 Function + icon_get_height icon_get_frame_count uint8_t uint32_t const Icon*
1690 Function + icon_get_width icon_get_frame_data uint8_t const uint8_t* const Icon* const Icon*, uint32_t
1691 Function + icon_get_height uint16_t const Icon*
1692 Function + icon_get_width uint16_t const Icon*
1693 Function - ilogb int double
1694 Function - ilogbf int float
1695 Function - ilogbl int long double
1993 Function - mblen int const char*, size_t
1994 Function - mbstowcs size_t wchar_t*, const char*, size_t
1995 Function - mbtowc int wchar_t*, const char*, size_t
1996 Function + md5_calc_file _Bool File*, const char*, unsigned char[16], FS_Error*
1997 Function + md5_string_calc_file _Bool File*, const char*, FuriString*, FS_Error*
1998 Function - memccpy void* void*, const void*, int, size_t
1999 Function + memchr void* const void*, int, size_t
2000 Function + memcmp int const void*, const void*, size_t
2269 Function + protocol_dict_render_data void ProtocolDict*, FuriString*, size_t
2270 Function + protocol_dict_render_uid void ProtocolDict*, FuriString*, size_t
2271 Function + protocol_dict_set_data void ProtocolDict*, size_t, const uint8_t*, size_t
2272 Function + pulse_glue_alloc PulseGlue*
2273 Function + pulse_glue_free void PulseGlue*
2274 Function + pulse_glue_pop void PulseGlue*, uint32_t*, uint32_t*
2275 Function + pulse_glue_push _Bool PulseGlue*, _Bool, uint32_t
2276 Function + pulse_glue_reset void PulseGlue*
2277 Function - pulse_reader_alloc PulseReader* const GpioPin*, uint32_t
2278 Function - pulse_reader_free void PulseReader*
2279 Function - pulse_reader_receive uint32_t PulseReader*, int
2662 Function + variable_item_set_current_value_index void VariableItem*, uint8_t
2663 Function + variable_item_set_current_value_text void VariableItem*, const char*
2664 Function + variable_item_set_values_count void VariableItem*, uint8_t
2665 Function + varint_int32_length size_t int32_t
2666 Function + varint_int32_pack size_t int32_t, uint8_t*
2667 Function + varint_int32_unpack size_t int32_t*, const uint8_t*, size_t
2668 Function + varint_uint32_length size_t uint32_t
2669 Function + varint_uint32_pack size_t uint32_t, uint8_t*
2670 Function + varint_uint32_unpack size_t uint32_t*, const uint8_t*, size_t
2671 Function - vasiprintf int char**, const char*, __gnuc_va_list
2672 Function - vasniprintf char* char*, size_t*, const char*, __gnuc_va_list
2673 Function - vasnprintf char* char*, size_t*, const char*, __gnuc_va_list

View File

@ -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": [

View File

@ -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,,
@ -160,6 +161,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,,
@ -208,6 +210,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,,
@ -224,10 +227,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,,
@ -236,6 +241,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,,
@ -753,8 +759,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*"
@ -846,7 +859,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"
@ -1698,7 +1711,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*"
@ -1922,8 +1935,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
@ -2392,6 +2407,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"
@ -2867,6 +2884,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"
@ -3007,6 +3029,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"
@ -3259,6 +3286,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*
@ -3457,6 +3491,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"

1 entry status name type params
2 Version + 61.4 62.3
3 Header + applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h
4 Header + applications/services/bt/bt_service/bt.h
5 Header + applications/services/bt/bt_service/bt_keys_storage.h
6 Header + applications/services/cli/cli.h
7 Header + applications/services/cli/cli_vcp.h
8 Header + applications/services/dialogs/dialogs.h
161 Header + lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.h
162 Header + lib/nfc/protocols/mf_ultralight/mf_ultralight_poller_sync.h
163 Header + lib/nfc/protocols/slix/slix.h
164 Header + lib/nfc/protocols/slix/slix_poller.h
165 Header + lib/nfc/protocols/st25tb/st25tb.h
166 Header + lib/nfc/protocols/st25tb/st25tb_poller.h
167 Header + lib/nfc/protocols/st25tb/st25tb_poller_sync.h
210 Header + lib/subghz/protocols/raw.h
211 Header + lib/subghz/receiver.h
212 Header + lib/subghz/registry.h
213 Header + lib/subghz/subghz_file_encoder_worker.h
214 Header + lib/subghz/subghz_protocol_registry.h
215 Header + lib/subghz/subghz_setting.h
216 Header + lib/subghz/subghz_tx_rx_worker.h
227 Header + lib/toolbox/keys_dict.h
228 Header + lib/toolbox/manchester_decoder.h
229 Header + lib/toolbox/manchester_encoder.h
230 Header + lib/toolbox/md5_calc.h
231 Header + lib/toolbox/name_generator.h
232 Header + lib/toolbox/path.h
233 Header + lib/toolbox/pretty_format.h
234 Header + lib/toolbox/protocols/protocol_dict.h
235 Header + lib/toolbox/pulse_protocols/pulse_glue.h
236 Header + lib/toolbox/saved_struct.h
237 Header + lib/toolbox/simple_array.h
238 Header + lib/toolbox/stream/buffered_file_stream.h
241 Header + lib/toolbox/stream/string_stream.h
242 Header + lib/toolbox/tar/tar_archive.h
243 Header + lib/toolbox/value_index.h
244 Header + lib/toolbox/varint.h
245 Header + lib/toolbox/version.h
246 Header + targets/f7/ble_glue/furi_ble/event_dispatcher.h
247 Header + targets/f7/ble_glue/furi_ble/gatt.h
759 Function - bsearch void* const void*, const void*, size_t, size_t, __compar_fn_t
760 Function + bt_disconnect void Bt*
761 Function + bt_forget_bonded_devices void Bt*
762 Function + bt_keys_storage_alloc BtKeysStorage* const char*
763 Function + bt_keys_storage_delete _Bool BtKeysStorage*
764 Function + bt_keys_storage_free void BtKeysStorage*
765 Function + bt_keys_storage_load _Bool BtKeysStorage*
766 Function + bt_keys_storage_set_default_path void Bt*
767 Function + bt_keys_storage_set_file_path void BtKeysStorage*, const char*
768 Function + bt_keys_storage_set_ram_params void BtKeysStorage*, uint8_t*, uint16_t
769 Function + bt_keys_storage_set_storage_path void Bt*, const char*
770 Function + bt_keys_storage_update _Bool BtKeysStorage*, uint8_t*, uint32_t
771 Function + bt_profile_restore_default _Bool Bt*
772 Function + bt_profile_start FuriHalBleProfileBase* Bt*, const FuriHalBleProfileTemplate*, FuriHalBleProfileParams
773 Function + bt_set_status_changed_callback void Bt*, BtStatusChangedCallback, void*
859 Function + compress_decode _Bool Compress*, uint8_t*, size_t, uint8_t*, size_t, size_t*
860 Function + compress_encode _Bool Compress*, uint8_t*, size_t, uint8_t*, size_t, size_t*
861 Function + compress_free void Compress*
862 Function + compress_icon_alloc CompressIcon* size_t
863 Function + compress_icon_decode void CompressIcon*, const uint8_t*, uint8_t**
864 Function + compress_icon_free void CompressIcon*
865 Function - copysign double double, double
1711 Function + furi_mutex_get_owner FuriThreadId FuriMutex*
1712 Function + furi_mutex_release FuriStatus FuriMutex*
1713 Function + furi_pubsub_alloc FuriPubSub*
1714 Function - + furi_pubsub_free void FuriPubSub*
1715 Function + furi_pubsub_publish void FuriPubSub*, void*
1716 Function + furi_pubsub_subscribe FuriPubSubSubscription* FuriPubSub*, FuriPubSubCallback, void*
1717 Function + furi_pubsub_unsubscribe void FuriPubSub*, FuriPubSubSubscription*
1935 Function + icon_animation_start void IconAnimation*
1936 Function + icon_animation_stop void IconAnimation*
1937 Function + icon_get_data const uint8_t* const Icon*
1938 Function + icon_get_height icon_get_frame_count uint8_t uint32_t const Icon*
1939 Function + icon_get_width icon_get_frame_data uint8_t const uint8_t* const Icon* const Icon*, uint32_t
1940 Function + icon_get_height uint16_t const Icon*
1941 Function + icon_get_width uint16_t const Icon*
1942 Function - ilogb int double
1943 Function - ilogbf int float
1944 Function - ilogbl int long double
2407 Function - mblen int const char*, size_t
2408 Function - mbstowcs size_t wchar_t*, const char*, size_t
2409 Function - mbtowc int wchar_t*, const char*, size_t
2410 Function + md5_calc_file _Bool File*, const char*, unsigned char[16], FS_Error*
2411 Function + md5_string_calc_file _Bool File*, const char*, FuriString*, FS_Error*
2412 Function - memccpy void* void*, const void*, int, size_t
2413 Function + memchr void* const void*, int, size_t
2414 Function + memcmp int const void*, const void*, size_t
2884 Function + protocol_dict_render_data void ProtocolDict*, FuriString*, size_t
2885 Function + protocol_dict_render_uid void ProtocolDict*, FuriString*, size_t
2886 Function + protocol_dict_set_data void ProtocolDict*, size_t, const uint8_t*, size_t
2887 Function + pulse_glue_alloc PulseGlue*
2888 Function + pulse_glue_free void PulseGlue*
2889 Function + pulse_glue_pop void PulseGlue*, uint32_t*, uint32_t*
2890 Function + pulse_glue_push _Bool PulseGlue*, _Bool, uint32_t
2891 Function + pulse_glue_reset void PulseGlue*
2892 Function - pulse_reader_alloc PulseReader* const GpioPin*, uint32_t
2893 Function - pulse_reader_free void PulseReader*
2894 Function - pulse_reader_receive uint32_t PulseReader*, int
3029 Function + slix_is_equal _Bool const SlixData*, const SlixData*
3030 Function + slix_is_privacy_mode _Bool const SlixData*
3031 Function + slix_load _Bool SlixData*, FlipperFormat*, uint32_t
3032 Function + slix_poller_get_nxp_system_info SlixError SlixPoller*, SlixSystemInfo*
3033 Function + slix_poller_get_random_number SlixError SlixPoller*, SlixRandomNumber*
3034 Function + slix_poller_read_signature SlixError SlixPoller*, SlixSignature*
3035 Function + slix_poller_send_frame SlixError SlixPoller*, const BitBuffer*, BitBuffer*, uint32_t
3036 Function + slix_poller_set_password SlixError SlixPoller*, SlixPasswordType, SlixPassword, SlixRandomNumber
3037 Function + slix_reset void SlixData*
3038 Function + slix_save _Bool const SlixData*, FlipperFormat*
3039 Function + slix_set_uid _Bool SlixData*, const uint8_t*, size_t
3286 Function + subghz_environment_set_came_atomo_rainbow_table_file_name void SubGhzEnvironment*, const char*
3287 Function + subghz_environment_set_nice_flor_s_rainbow_table_file_name void SubGhzEnvironment*, const char*
3288 Function + subghz_environment_set_protocol_registry void SubGhzEnvironment*, const SubGhzProtocolRegistry*
3289 Function + subghz_file_encoder_worker_alloc SubGhzFileEncoderWorker*
3290 Function + subghz_file_encoder_worker_callback_end void SubGhzFileEncoderWorker*, SubGhzFileEncoderWorkerCallbackEnd, void*
3291 Function + subghz_file_encoder_worker_free void SubGhzFileEncoderWorker*
3292 Function + subghz_file_encoder_worker_get_level_duration LevelDuration void*
3293 Function + subghz_file_encoder_worker_is_running _Bool SubGhzFileEncoderWorker*
3294 Function + subghz_file_encoder_worker_start _Bool SubGhzFileEncoderWorker*, const char*, const char*
3295 Function + subghz_file_encoder_worker_stop void SubGhzFileEncoderWorker*
3296 Function - subghz_keystore_alloc SubGhzKeystore*
3297 Function - subghz_keystore_free void SubGhzKeystore*
3298 Function - subghz_keystore_get_data SubGhzKeyArray_t* SubGhzKeystore*
3491 Function + variable_item_set_current_value_index void VariableItem*, uint8_t
3492 Function + variable_item_set_current_value_text void VariableItem*, const char*
3493 Function + variable_item_set_values_count void VariableItem*, uint8_t
3494 Function + varint_int32_length size_t int32_t
3495 Function + varint_int32_pack size_t int32_t, uint8_t*
3496 Function + varint_int32_unpack size_t int32_t*, const uint8_t*, size_t
3497 Function + varint_uint32_length size_t uint32_t
3498 Function + varint_uint32_pack size_t uint32_t, uint8_t*
3499 Function + varint_uint32_unpack size_t uint32_t*, const uint8_t*, size_t
3500 Function - vasiprintf int char**, const char*, __gnuc_va_list
3501 Function - vasniprintf char* char*, size_t*, const char*, __gnuc_va_list
3502 Function - vasnprintf char* char*, size_t*, const char*, __gnuc_va_list

View File

@ -133,7 +133,7 @@ void furi_hal_clock_switch_hse2hsi(void) {
;
LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_HSI);
furi_assert(LL_RCC_GetSMPSClockSelection() == LL_RCC_SMPS_CLKSOURCE_HSI);
furi_check(LL_RCC_GetSMPSClockSelection() == LL_RCC_SMPS_CLKSOURCE_HSI);
while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSI)
;
@ -170,7 +170,7 @@ void furi_hal_clock_switch_hsi2hse(void) {
}
bool furi_hal_clock_switch_hse2pll(void) {
furi_assert(LL_RCC_GetSysClkSource() == LL_RCC_SYS_CLKSOURCE_STATUS_HSE);
furi_check(LL_RCC_GetSysClkSource() == LL_RCC_SYS_CLKSOURCE_STATUS_HSE);
LL_RCC_PLL_Enable();
LL_RCC_PLLSAI1_Enable();
@ -180,12 +180,13 @@ bool furi_hal_clock_switch_hse2pll(void) {
while(!LL_RCC_PLLSAI1_IsReady())
;
if(SHCI_C2_SetSystemClock(SET_SYSTEM_CLOCK_HSE_TO_PLL) != SHCI_Success) {
// This API returns garbage if stack version < 1.20.0
SHCI_C2_SetSystemClock(SET_SYSTEM_CLOCK_HSE_TO_PLL);
// So we'll check results by asking hardware directly
if(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) {
return false;
}
furi_check(LL_RCC_GetSysClkSource() == LL_RCC_SYS_CLKSOURCE_STATUS_PLL);
LL_SetSystemCoreClock(CPU_CLOCK_PLL_HZ);
SysTick->LOAD = (uint32_t)((SystemCoreClock / 1000) - 1UL);
@ -193,18 +194,19 @@ bool furi_hal_clock_switch_hse2pll(void) {
}
bool furi_hal_clock_switch_pll2hse(void) {
furi_assert(LL_RCC_GetSysClkSource() == LL_RCC_SYS_CLKSOURCE_STATUS_PLL);
furi_check(LL_RCC_GetSysClkSource() == LL_RCC_SYS_CLKSOURCE_STATUS_PLL);
LL_RCC_HSE_Enable();
while(!LL_RCC_HSE_IsReady())
;
if(SHCI_C2_SetSystemClock(SET_SYSTEM_CLOCK_PLL_ON_TO_HSE) != SHCI_Success) {
// This API returns garbage if stack version < 1.20.0
SHCI_C2_SetSystemClock(SET_SYSTEM_CLOCK_PLL_ON_TO_HSE);
// So we'll check results by asking hardware directly
if(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSE) {
return false;
}
furi_check(LL_RCC_GetSysClkSource() == LL_RCC_SYS_CLKSOURCE_STATUS_HSE);
LL_SetSystemCoreClock(CPU_CLOCK_HSE_HZ);
SysTick->LOAD = (uint32_t)((SystemCoreClock / 1000) - 1UL);

View File

@ -16,6 +16,11 @@
#define TAG "FuriHalFlash"
#ifdef FLASH_OP_DEBUG
#undef FURI_LOG_T
#define FURI_LOG_T(...)
#endif
#define FURI_HAL_CRITICAL_MSG "Critical flash operation fail"
#define FURI_HAL_FLASH_READ_BLOCK (8U)
#define FURI_HAL_FLASH_WRITE_BLOCK (8U)
@ -144,9 +149,8 @@ static void furi_hal_flash_begin_with_core2(bool erase_flag) {
/* Erase activity notification */
if(erase_flag) SHCI_C2_FLASH_EraseActivity(ERASE_ACTIVITY_ON);
/* 64mHz 5us core2 flag protection */
for(volatile uint32_t i = 0; i < 35; i++)
;
/* 5us core2 flag protection */
furi_delay_us(5);
FuriHalCortexTimer timer = furi_hal_cortex_timer_get(FURI_HAL_FLASH_C2_LOCK_TIMEOUT_MS * 1000);
while(true) {
@ -291,6 +295,7 @@ bool furi_hal_flash_wait_last_operation(uint32_t timeout) {
}
void furi_hal_flash_erase(uint8_t page) {
uint32_t op_stat = DWT->CYCCNT;
furi_hal_flash_begin(true);
/* Ensure that controller state is valid */
@ -313,6 +318,12 @@ void furi_hal_flash_erase(uint8_t page) {
furi_hal_flush_cache();
furi_hal_flash_end(true);
op_stat = DWT->CYCCNT - op_stat;
FURI_LOG_T(
TAG,
"erase took %lu clocks or %fus",
op_stat,
(double)((float)op_stat / (float)furi_hal_cortex_instructions_per_microsecond()));
}
static inline void furi_hal_flash_write_dword_internal_nowait(size_t address, uint64_t* data) {
@ -335,6 +346,7 @@ static inline void furi_hal_flash_write_dword_internal(size_t address, uint64_t*
}
void furi_hal_flash_write_dword(size_t address, uint64_t data) {
uint32_t op_stat = DWT->CYCCNT;
furi_hal_flash_begin(false);
/* Ensure that controller state is valid */
@ -357,6 +369,12 @@ void furi_hal_flash_write_dword(size_t address, uint64_t data) {
/* Wait for last operation to be completed */
furi_check(furi_hal_flash_wait_last_operation(FURI_HAL_FLASH_TIMEOUT));
op_stat = DWT->CYCCNT - op_stat;
FURI_LOG_T(
TAG,
"write_dword took %lu clocks or %fus",
op_stat,
(double)((float)op_stat / (float)furi_hal_cortex_instructions_per_microsecond()));
}
static size_t furi_hal_flash_get_page_address(uint8_t page) {
@ -369,6 +387,7 @@ void furi_hal_flash_program_page(const uint8_t page, const uint8_t* data, uint16
furi_hal_flash_erase(page);
uint32_t op_stat = DWT->CYCCNT;
furi_hal_flash_begin(false);
furi_check(furi_hal_flash_wait_last_operation(FURI_HAL_FLASH_TIMEOUT));
@ -428,6 +447,12 @@ void furi_hal_flash_program_page(const uint8_t page, const uint8_t* data, uint16
CLEAR_BIT(FLASH->CR, FLASH_CR_PG);
furi_hal_flash_end(false);
op_stat = DWT->CYCCNT - op_stat;
FURI_LOG_T(
TAG,
"program_page took %lu clocks or %fus",
op_stat,
(double)((float)op_stat / (float)furi_hal_cortex_instructions_per_microsecond()));
}
int16_t furi_hal_flash_get_page_number(size_t address) {

View File

@ -45,7 +45,6 @@
"mbedtls",
"lfrfid",
"flipper_application",
"toolbox",
"u8g2",
"nanopb",
"update_util",
@ -53,6 +52,7 @@
"flipperformat",
"flipper7",
"bit_lib",
"toolbox",
"datetime"
]
}